0

I am having canvas code for dragging and resizing rectangle.But i cant able to convert this canvas code to svg.how to convert canvas code to svg.

That stackoverflow link is not use for me.

Thanks in advance.

var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    rect = {
        x: 150,
        y: 100,
        w: 123,
        h: 58
    },
    handlesSize = 8,
    currentHandle = false,
    drag = false;

function init() {
    canvas.addEventListener('mousedown', mouseDown, false);
    canvas.addEventListener('mouseup', mouseUp, false);
    canvas.addEventListener('mousemove', mouseMove, false);
}

function point(x, y) {
    return {
        x: x,
        y: y
    };
}

function dist(p1, p2) {
    return Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
}

function getHandle(mouse) {
    if (dist(mouse, point(rect.x, rect.y)) <= handlesSize) return 'topleft';
    if (dist(mouse, point(rect.x + rect.w, rect.y)) <= handlesSize) return 'topright';
    if (dist(mouse, point(rect.x, rect.y + rect.h)) <= handlesSize) return 'bottomleft';
    if (dist(mouse, point(rect.x + rect.w, rect.y + rect.h)) <= handlesSize) return 'bottomright';
    if (dist(mouse, point(rect.x + rect.w / 2, rect.y)) <= handlesSize) return 'top';
    if (dist(mouse, point(rect.x, rect.y + rect.h / 2)) <= handlesSize) return 'left';
    if (dist(mouse, point(rect.x + rect.w / 2, rect.y + rect.h)) <= handlesSize) return 'bottom';
    if (dist(mouse, point(rect.x + rect.w, rect.y + rect.h / 2)) <= handlesSize) return 'right';
    return false;
}

function mouseDown(e) {
    if (currentHandle) drag = true;
    draw();
}

function mouseUp() {
    drag = false;
    currentHandle = false;
    draw();
}

function mouseMove(e) {
    var previousHandle = currentHandle;
    if (!drag) currentHandle = getHandle(point(e.pageX - this.offsetLeft, e.pageY - this.offsetTop));
    if (currentHandle && drag) {
        var mousePos = point(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
        switch (currentHandle) {
            case 'topleft':
                rect.w += rect.x - mousePos.x;
                rect.h += rect.y - mousePos.y;
                rect.x = mousePos.x;
                rect.y = mousePos.y;
                break;
            case 'topright':
                rect.w = mousePos.x - rect.x;
                rect.h += rect.y - mousePos.y;
                rect.y = mousePos.y;
                break;
            case 'bottomleft':
                rect.w += rect.x - mousePos.x;
                rect.x = mousePos.x;
                rect.h = mousePos.y - rect.y;
                break;
            case 'bottomright':
                rect.w = mousePos.x - rect.x;
                rect.h = mousePos.y - rect.y;
                break;

            case 'top':
                rect.h += rect.y - mousePos.y;
                rect.y = mousePos.y;
                break;

            case 'left':
                rect.w += rect.x - mousePos.x;
                rect.x = mousePos.x;
                break;

            case 'bottom':
                rect.h = mousePos.y - rect.y;
                break;

            case 'right':
                rect.w = mousePos.x - rect.x;
                break;
        }
    }
    if (drag || currentHandle != previousHandle) draw();
}

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = 'black';
    ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
    if (currentHandle) {
        var posHandle = point(0, 0);
        switch (currentHandle) {
            case 'topleft':
                posHandle.x = rect.x;
                posHandle.y = rect.y;
                break;
            case 'topright':
                posHandle.x = rect.x + rect.w;
                posHandle.y = rect.y;
                break;
            case 'bottomleft':
                posHandle.x = rect.x;
                posHandle.y = rect.y + rect.h;
                break;
            case 'bottomright':
                posHandle.x = rect.x + rect.w;
                posHandle.y = rect.y + rect.h;
                break;
            case 'top':
                posHandle.x = rect.x + rect.w / 2;
                posHandle.y = rect.y;
                break;
            case 'left':
                posHandle.x = rect.x;
                posHandle.y = rect.y + rect.h / 2;
                break;
            case 'bottom':
                posHandle.x = rect.x + rect.w / 2;
                posHandle.y = rect.y + rect.h;
                break;
            case 'right':
                posHandle.x = rect.x + rect.w;
                posHandle.y = rect.y + rect.h / 2;
                break;
        }
        ctx.globalCompositeOperation = 'xor';
        ctx.beginPath();
        ctx.arc(posHandle.x, posHandle.y, handlesSize, 0, 2 * Math.PI);
        ctx.fill();
        ctx.globalCompositeOperation = 'source-over';
    }
}

init();
draw();

here is fiddle link for rendering rectangle in canvas:

http://jsfiddle.net/BaliBalo/9HXMG/

Rekha
  • 39
  • 1
  • 8
  • rewrite it from scratch. svg is an XML markup language while canvas is a pixel drawing context. You should code svg as you would with HTML elements. – Kaiido Aug 18 '15 at 06:33
  • 1
    possible duplicate of [Method to convert HTML5 canvas to SVG?](http://stackoverflow.com/questions/8571294/method-to-convert-html5-canvas-to-svg) – kpimov Aug 18 '15 at 06:37
  • As far as I remember, it is just NOT possible to convert Canvas to SVG. The opposite is possible. – Julo0sS Aug 18 '15 at 06:42
  • @Kaiido what you are said is correct.But i dont know how to change this canvas context to html elements. – Rekha Aug 18 '15 at 10:04

1 Answers1

1

It's quite simple to convert this to SVG.

The only slight gotcha is that we have to add some handling to cater for when the rectangle width or height are negative. Canvas2D doesn't mind that, but SVG does.

Also, there isn't an easy way to simulate the XOR operation when drawing the drag handles. So I've just made them plain blue.

var canvas = document.getElementById('canvas'),
    rect = {
        x: 150,
        y: 100,
        w: 123,
        h: 58
    },
    handlesSize = 8,
    currentHandle = false,
    drag = false
    svgns = 'http://www.w3.org/2000/svg';

function init() {
    canvas.addEventListener('mousedown', mouseDown, false);
    canvas.addEventListener('mouseup', mouseUp, false);
    canvas.addEventListener('mousemove', mouseMove, false);
}

function point(x, y) {
    return {
        x: x,
        y: y
    };
}

function dist(p1, p2) {
    return Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
}

function getHandle(mouse) {
    if (dist(mouse, point(rect.x, rect.y)) <= handlesSize) return 'topleft';
    if (dist(mouse, point(rect.x + rect.w, rect.y)) <= handlesSize) return 'topright';
    if (dist(mouse, point(rect.x, rect.y + rect.h)) <= handlesSize) return 'bottomleft';
    if (dist(mouse, point(rect.x + rect.w, rect.y + rect.h)) <= handlesSize) return 'bottomright';
    if (dist(mouse, point(rect.x + rect.w / 2, rect.y)) <= handlesSize) return 'top';
    if (dist(mouse, point(rect.x, rect.y + rect.h / 2)) <= handlesSize) return 'left';
    if (dist(mouse, point(rect.x + rect.w / 2, rect.y + rect.h)) <= handlesSize) return 'bottom';
    if (dist(mouse, point(rect.x + rect.w, rect.y + rect.h / 2)) <= handlesSize) return 'right';
    return false;
}

function mouseDown(e) {
    if (currentHandle) drag = true;
    draw();
}

function mouseUp() {
    drag = false;
    currentHandle = false;
    draw();
}

function mouseMove(e) {
    var previousHandle = currentHandle;
    var svgPos = this.getBoundingClientRect();
    if (!drag) currentHandle = getHandle(point(e.pageX - svgPos.left, e.pageY - svgPos.top));
    if (currentHandle && drag) {
        var mousePos = point(e.pageX - svgPos.left, e.pageY - svgPos.top);
        switch (currentHandle) {
            case 'topleft':
                rect.w += rect.x - mousePos.x;
                rect.h += rect.y - mousePos.y;
                rect.x = mousePos.x;
                rect.y = mousePos.y;
                break;
            case 'topright':
                rect.w = mousePos.x - rect.x;
                rect.h += rect.y - mousePos.y;
                rect.y = mousePos.y;
                break;
            case 'bottomleft':
                rect.w += rect.x - mousePos.x;
                rect.x = mousePos.x;
                rect.h = mousePos.y - rect.y;
                break;
            case 'bottomright':
                rect.w = mousePos.x - rect.x;
                rect.h = mousePos.y - rect.y;
                break;

            case 'top':
                rect.h += rect.y - mousePos.y;
                rect.y = mousePos.y;
                break;

            case 'left':
                rect.w += rect.x - mousePos.x;
                rect.x = mousePos.x;
                break;

            case 'bottom':
                rect.h = mousePos.y - rect.y;
                break;

            case 'right':
                rect.w = mousePos.x - rect.x;
                break;
        }
    }
    if (drag || currentHandle != previousHandle) draw();
}

function draw() {
    //ctx.clearRect(0, 0, canvas.width, canvas.height);
    while (canvas.firstChild) {
        canvas.removeChild(canvas.firstChild);
    }
    //ctx.fillStyle = 'black';
    //ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
    var svgrect = document.createElementNS(svgns, 'rect');
    svgrect.setAttribute('x', Math.min(rect.x, rect.x+rect.w));
    svgrect.setAttribute('y', Math.min(rect.y, rect.y+rect.h));
    svgrect.setAttribute('width', Math.abs(rect.w));
    svgrect.setAttribute('height', Math.abs(rect.h));
    canvas.appendChild(svgrect);

    if (currentHandle) {
        var posHandle = point(0, 0);
        switch (currentHandle) {
            case 'topleft':
                posHandle.x = rect.x;
                posHandle.y = rect.y;
                break;
            case 'topright':
                posHandle.x = rect.x + rect.w;
                posHandle.y = rect.y;
                break;
            case 'bottomleft':
                posHandle.x = rect.x;
                posHandle.y = rect.y + rect.h;
                break;
            case 'bottomright':
                posHandle.x = rect.x + rect.w;
                posHandle.y = rect.y + rect.h;
                break;
            case 'top':
                posHandle.x = rect.x + rect.w / 2;
                posHandle.y = rect.y;
                break;
            case 'left':
                posHandle.x = rect.x;
                posHandle.y = rect.y + rect.h / 2;
                break;
            case 'bottom':
                posHandle.x = rect.x + rect.w / 2;
                posHandle.y = rect.y + rect.h;
                break;
            case 'right':
                posHandle.x = rect.x + rect.w;
                posHandle.y = rect.y + rect.h / 2;
                break;
        }
        //ctx.globalCompositeOperation = 'xor';
        //ctx.beginPath();
        //ctx.arc(posHandle.x, posHandle.y, handlesSize, 0, 2 * Math.PI);
        //ctx.fill();
        //ctx.globalCompositeOperation = 'source-over';
        var circ = document.createElementNS(svgns, 'circle');
        circ.setAttribute('cx', posHandle.x);
        circ.setAttribute('cy', posHandle.y);
        circ.setAttribute('r', handlesSize);
        circ.setAttribute('fill', 'blue');
        canvas.appendChild(circ);
    }
}

init();
draw();
<svg id="canvas" width="500" height="500"></svg>
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • Also, doing this direct translation doesn't seem to be a great idea, I mean canvas is meant to perform a lot of redraw but here, you are creating and removing a lot of elements. Won't those populate the memory until the browser performs a garbageCollection ? Won't it be better to just create those 7 elements once and then just change their `x` `y` properties (and `width` and `height` for the rect) on drag? – Kaiido Aug 18 '15 at 11:38
  • Yes it can be improved. Ideally it would update the elements rather than recreating them. I wanted to keep it simple for the OP. – Paul LeBeau Aug 18 '15 at 11:41
  • yes it is not working in firefox and IE also.how to change the code that is working for all browsers – Rekha Aug 18 '15 at 11:55
  • 1
    offsetLeft is only for HTML elements. You're relying on a Chrome bug http://www.w3.org/TR/cssom-view/#extensions-to-the-htmlelement-interface – Robert Longson Aug 18 '15 at 11:57
  • actually in this code canvas based rect created.but i want to draw the rect in svg.like this. – Rekha Aug 24 '15 at 06:15
  • That is going to be a lot trickier to get working because you are using a `viewBox` which will add a scaling transform when the rectangle gets drawn. Are you sure you need to do that? However adding the class is easy. Just add an extra line `svgrect.setAttribute("class","resize-drag");`. – Paul LeBeau Aug 24 '15 at 16:36
  • Thanks Paul LeBeau.actually i want to draw the rectangle in svg format.so can you provide any suggestion on this. – Rekha Aug 25 '15 at 07:29
  • The code listed above, in this answer, draws the rect in SVG format. – Paul LeBeau Aug 25 '15 at 09:41
  • i have drawn the rect using this code. using this code only i have drawn the svg rect. – Rekha Aug 25 '15 at 10:33
  • I have drag and resize the rect based on the above code.but want to drag using cursor types.wont circle for dragging.how to do this.Thanks in advance. – Rekha Sep 03 '15 at 07:17