Raphael.js has weird behavior on drag

124 Views Asked by At

I have circle with a line from the center to the edge of the circle. The user can click on and drag the line and get the degrees from wherever they set the line. I'm using the code from the answer here and have adjusted the code accordingly.

Everything works fine, but the farther down the page the element affected by raphael is, the farther outside of the circle the mouse has to be in order to drag the line. jsfiddle

var canvas = Raphael('pivot', 0, 0, 320, 320);

var clock = canvas.circle(200, 150, 100).attr("stroke-width", 2);
canvas.circle(200, 150, 3).attr("fill", "#000");

var angleplus = 360,
    rad = Math.PI / 180,
    cx = 200,
    cy = 150,
    r = 90,
    startangle = -90,
    angle = 90,
    x, y, endangle;

for (i = 1; i < 5; i++) {

    endangle = startangle + angle;
    x = cx + r * Math.sin(endangle * rad);
    y = cy - r * Math.cos(endangle * rad);

    canvas.text(x, y, endangle);

    startangle = endangle;
}

var hand = canvas.path("M200 50L200 150").attr("stroke-width", 5);

hand.drag( move, start, end );

function move (dx,dy,x,y) {
    var pt = this.node.ownerSVGElement.createSVGPoint();
    pt.x = x; 
    pt.y = y;

    var angle = ( 90 + Math.atan2(pt.y - clock.attr('cy') - 5, pt.x - clock.attr('cx') - 5 ) * 180 / Math.PI + 360) % 360;
    this.rotate(angle, 200,150);
    this.angle = angle;
}

function start() {
};

function end() {
    alert(parseInt(this.angle));
}

I'm wondering why this happens and if it's even fixable?

1

There are 1 best solutions below

3
On BEST ANSWER

Here is an updated original one, a bit added and another bit of redundancy removed, and I've added an extra fiddle to the original answer to reflect it.

The key bits I've added are...

var cpt = clock.node.ownerSVGElement.createSVGPoint();
cpt.x = clock.attr('cx');
cpt.y = clock.attr('cy');
cpt = cpt.matrixTransform(clock.node.getScreenCTM());

The centre of the clock has now moved, so using cx of the circle alone, doesn't really make sense relative to the mouse event. We need to take into account any offset and transforms on the screen to the clock.

We can get this with getScreenCTM (get the matrix from element to the screen), and we can use that matrix with the original cx, cy to figure out where it is on the screen.

Then later, instead of cx, cy, we use the new adjusted coordinates cpt.x/y

var angle = ( 90 + Math.atan2(y - cpt.y - 5, x - cpt.x - 5 ) * 180 / Math.PI + 360)

jsfiddle - drag any hand