0

I was wondering how to drag a object through a canvas and I've come up with this: JsFiddle

Now the thing is: I have two different paths which I need to drag two objects on they (balls), the balls should move on both paths independently on which one I am moving.

I am trying to do something like the Google Maps Elevation Service, which you can move a ball along the path and visualize on the other side the elevation that corresponds to that area of the path.

(To look forward into this, go to Google maps and select A to B points and select Bike, then Elevation will show up on the left side of screen.)

Google Maps

I have some piece of code using Raphael.js but I can't find a way through.

var searchDl = 1;
var l = 0;

// Creates canvas 320 × 200 at 10, 50
var r = Raphael(10, 50, 320, 200);

var p = r.path("M100,100c0,50 100-50 100,0c0,50 -100-50 -100,0z").attr({stroke: "#ddf"}),
    pt = p.getPointAtLength(l);
    e = r.ellipse(pt.x, pt.y, 4, 4).attr({stroke: "none", fill: "#f00"}),
    totLen = p.getTotalLength(),


start = function () {
    // storing original coordinates
    this.ox = this.attr("cx");
    this.oy = this.attr("cy");
    this.attr({opacity: 1});
},
move = function (dx, dy) {
    var tmpPt = {
        x : this.ox + dx, 
        y : this.oy + dy
    };
    // move will be called with dx and dy
    l = gradSearch(l, tmpPt);
    pt = p.getPointAtLength(l);
    this.attr({cx: pt.x, cy: pt.y});
},
up = function () {
    // restoring state
    this.attr({opacity: 1});
},
gradSearch = function (l0, pt) {
    l0 = l0 + totLen;
    var l1 = l0,
        dist0 = dist(p.getPointAtLength(l0 % totLen), pt),
        dist1,
        searchDir;

    if (dist(p.getPointAtLength((l0 - searchDl) % totLen), pt) > 
       dist(p.getPointAtLength((l0 + searchDl) % totLen), pt)) {
        searchDir = searchDl;
    } else {
        searchDir = -searchDl;
    }

    l1 += searchDir;
    dist1 = dist(p.getPointAtLength(l1 % totLen), pt);
    while (dist1 < dist0) {
        dist0 = dist1;
        l1 += searchDir;
        dist1 = dist(p.getPointAtLength(l1 % totLen), pt);
    }
    l1 -= searchDir;

    return (l1 % totLen);
},
dist = function (pt1, pt2) {
    var dx = pt1.x - pt2.x;
    var dy = pt1.y - pt2.y;
    return Math.sqrt(dx * dx + dy * dy);
};
e.drag(move, start, up);
markE
  • 102,905
  • 11
  • 164
  • 176
Henrique M.
  • 512
  • 2
  • 14

1 Answers1

2

You can create a 2nd path (assuming they are different, if not, you could just clone() the first and scale it or something), figure out the ratio travelled, then adjust the 2nd path circle to move along the same ratio. So it could look something like...

var p2 = r.path("M150 0 L75 200 L225 200 Z").attr({ stroke: 'blue' }),
    pt2 = p2.getPointAtLength(l),
    e2 = r.ellipse(pt2.x, pt2.y, 4, 4).attr({stroke: "none", fill: "#f00"}),
    p2totLen = p2.getTotalLength();

Then inside your move() func...

var ratioDone = l / totLen;
var p2Len = ratioDone * p2totLen
var p2Pt = p2.getPointAtLength( p2Len )
e2.attr({ cx: p2Pt.x, cy: p2Pt.y })

jsfiddle (drag infinity circle)

Ian
  • 13,724
  • 4
  • 52
  • 75
  • 1
    My bad! I think you're right. Now that I look at the OP's fiddle, I see they want to navigate 2 paths simultaneously -- one on a map and the other on an elevation chart. I'm deleting my misguided answer :-o – markE Feb 25 '16 at 18:05
  • Your code is great, but we should be able to drag both balls. Is possible to make a command to both? – Henrique M. Feb 29 '16 at 14:54
  • How do I adjust ratio without messing up with the final points? Whenever I try, the first path ends before the second one ends. In other words, I need to make the 2nd ball go a little bit slower but still reach the end whenever the first one does it too – Henrique M. Mar 08 '16 at 21:20
  • Not sure I follow, if you make the 2nd ball go slower, it won't reach the end (unless the path is smaller). As the ratio is the difference between the two paths. It may be worth asking a new question with a testing example and try and explain a bit further, or post a fiddle here. – Ian Mar 08 '16 at 23:15
  • Can`t I make the ratio bigger? Path1 travelled is equal to Path 2 travelled space times anything which still reach the end – Henrique M. Mar 09 '16 at 14:07
  • Or is that impossible, forcing me to make the 1st path longer to adjust its ratio compared to the 2nd? – Henrique M. Mar 09 '16 at 14:12
  • If you make the ratio bigger, the other one will just reach the end quicker, which may be what you really want, I don't know. Its not clear, eg what does " Path1 travelled is equal to Path 2 travelled space times anything which still reach the end" mean ? I think something is getting lost in translation, so maybe some pics for example would help. – Ian Mar 09 '16 at 14:30
  • Perhaps I can give you a practical example. Let's suppose I have a point named a3 and it should correspond to b3 in the 2nd path, but actually it are corresponding to point b4. What I need to do to synchronize, without losing its proportion? I mean, a10 must correspond to b10 since a1 corresponds to b1. You know what I mean? In that case I should make the A path bigger so the ratio automatically get right or is there any math I could do? – Henrique M. Mar 09 '16 at 16:49
  • Still not sure what you mean, as I'm assuming you can make the path whatever you want, is scaling any use to you ? Eg drag a small path and it will move an equivalent on a bigger path ? – Ian Mar 09 '16 at 18:13
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/105836/discussion-between-henrique-m-and-ian). – Henrique M. Mar 09 '16 at 18:21