如何沿给定路径拖动形状 [英] How to drag a shape along a given path

查看:95
本文介绍了如何沿给定路径拖动形状的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个简单的虚拟文件,我正用它来做一些测试。预期的结果是沿路径拖动红色圆圈。

 <!DOCTYPE html>这是我无法弄清楚如何关联这两种形状。 
< html lang =en>
< head>
< meta charset =utf-8/>
< script src =raphael-min.js>< / script>
< / head>
< body>
< script type =text / javascript>
//在10,50
创建画布320×200 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} ),
e = r.ellipse(104,100,4,4).attr({stroke:none,fill:#f00}),


/ * var c = r.circle(100,100,50).attr({
fill:hsb(.8,1,1),
stroke:none,
不透明度:.5
)); * /


var start = function(){
//存储原始坐标
this.ox = this.attr( CX);
this.oy = this.attr(cy);
this.attr({opacity:1});
},
move = function(dx,dy){
//移动将被调用dx和dy
this.attr({cx:this.ox + dx, cy:this.oy + dy});
},
up = function(){
//恢复状态
this.attr({opacity:1});
};
e.drag(move,start,up);
< / script>
< / body>
< / html>


解决方案

您没有具体指定您想要的交互方式工作,所以我用我感觉最自然的。



我们可以假设点必须留在路径上,所以它的位置必须由

  p.getPointAtLength(l); 

代表 l 。要找到 l ,我们可以搜索曲线和光标位置之间距离的最小值 local 。我们用 l0 来初始化搜索,其中 l0 l

请参阅JSfiddle以获得一个工作示例:

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



以下是代码:

  var searchDl = 1; 
var l = 0;

//在10,50
创建画布320×200 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(){
//存储原始坐标
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; (p.getPointAtLength((10-searchD1)%totLen),pt)>
dist(p.getPointAtLength((10+ searchD1)%totLen),pt) ){
searchDir = searchDl;
} else {
searchDir = -searchDl;
}

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

return(l1%totLen);
},
dist =函数(pt1,pt2){
var dx = pt1.x - pt2.x;
var dy = pt1.y - pt2.y;
返回Math.sqrt(dx * dx + dy * dy);
};
e.drag(move,start,up);


I've this simple dummy file that I'm using to do some testing. The intended result is to drag the red circle along the path. The thing is that I can't figure out how to associate both shapes.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />    
    <script src="raphael-min.js"></script>    
</head>
<body>    
<script type="text/javascript">    
// 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"}),
    e = r.ellipse(104, 100, 4, 4).attr({stroke: "none", fill: "#f00"}),


/*var c = r.circle(100, 100, 50).attr({
    fill: "hsb(.8, 1, 1)",
    stroke: "none",
    opacity: .5
});*/


var start = function () {
    // storing original coordinates
    this.ox = this.attr("cx");
    this.oy = this.attr("cy");
    this.attr({opacity: 1});
},
move = function (dx, dy) {
    // move will be called with dx and dy
    this.attr({cx: this.ox + dx, cy: this.oy + dy});
},
up = function () {
    // restoring state
    this.attr({opacity: 1});
};
e.drag(move, start, up);    
</script>
</body>
</html>

解决方案

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);​

这篇关于如何沿给定路径拖动形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆