Reputation: 502
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.)
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);
Upvotes: 0
Views: 387
Reputation: 13842
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)
Upvotes: 2