How to drag a shape along a given path

与世无争的帅哥 提交于 2019-11-30 05:05:29

You didn't specify exactly how you want the interaction to work, so I used what feels most natural to me.

We can assume the dot must remain on the path, so its position must be given by

p.getPointAtLength(l);

for some l. To find l we can search for the local minimum of the distance between the curve and the cursor position. We initialize the search with l0 where l0 is the value of l currently defining the location of the dot.

See the JSfiddle here for a working example:

http://jsfiddle.net/fuzic/kKLtH/

Here is the code:

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: "#ddd"}),
    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
    };
    l = gradSearch(l, tmpPt);
    pt = p.getPointAtLength(l);
    this.attr({cx: pt.x, cy: pt.y});
},
up = function () {
    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);​

A circle object has an x,y coordinate for its center, and a radius. To make sure the circle remains on the line, simply find the intersection of the center of the circle and the line itself.

To do this, you will need to store the start and end coordinates of your line. Then using the equation of a line: y = mx + b, you can find the slope and y-intercept. Once you have a function for the line, you can generate new coordinates for the circle by plugging in different values of x.

Also, by plugging in the x,y coordinates of the circle into your function, you can check to see if the circle is on the line.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!