Snap.svg沿路径拖动组 [英] Snap.svg drag group along path

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

问题描述

我需要按照这个的方式做一些事情,但我需要使用Snap.svg和您可以:

I need to do something along the lines of this, but I with Snap.svg and with the ability to:


  1. 沿着路径拖动整个群组
  2. / li>
  3. 允许从任何组项目拖动组

  4. 支持任意数量的组项目

  5. 支持各种不同形状的路径

我开始这个jsfiddle 作为工作的起点(也发布在下面),但我对如何最好地解决这个问题感到茫然。

I started this jsfiddle as a working starting point (and also posted below), but I'm at a loss at how best to attack the problem.

var paper = Snap('#panel');

var path = paper.path('M44.16,44.16 L44.16,44.16 L73.6,14.719999999999999 L132.48,73.6 L14.719999999999999,191.35999999999999 L132.48,309.12 L103.03999999999999,338.55999999999995 L44.16,279.67999999999995 L44.16,279.67999999999995')
.attr({
    stroke: 'gray',
    strokeWidth: 3,
    fill: 'none'
});

var c1 = paper.circle(103.03999999999999, 103.03999999999999, 15);
var c2 = paper.circle(44.16, 161.92, 15);
var c3 = paper.circle(73.6, 132.48, 15);

var cGroup = paper.g();
cGroup.add(c1,c2,c3);


推荐答案

整体而言,这相当棘手。作为一种可能的方法,这个解决方案的大部分应该至少能够让你摆脱困境。对于距离检查,我使用了原始小提琴中的代码,因此可以归功于编写该代码的人,因为它可能很棘手(并且可能值得自己提出SO问题,但我认为它需要进行调整)。

This quite a tricky one overall. Here's most of the solution which should at least set you off right as one possible method. For the distance checking, I used the code in the original fiddle, so credit to the person who wrote that, as its potentially tricky (and maybe worthy of its own SO question, I think it will need a tweak though).

在这里摆弄编辑:你需要调整以允许更好的开始位置。

fiddle here edit: You'll need to tweak to allow for starting position better.

拖动圆圈开始它,因为我没有设置开始位置。您将需要调整元素的起始位置,具体取决于您是否将零点抵消它们或其他(否则在移动/变换时您需要考虑这一点)。您可能还想检查第一个/最后一个元素是否到达结尾并将它们全部停止,因此如果一个元素到达路径末尾它们都会停止。

Drag the circle to start it off, as I haven't set the start positions. You will want to adjust the elements starting positions, depending on whether you will zero offset them or whatever (otherwise you will need to allow for this when moving/transforming). You may also want to check for if the first/last element reaches the end and stops them all, so they all stop if one element reaches the path end.

它的工作原理通过将所有对象放在一个集合中,并为每个对象附加一个处理程序(您可能只需在该组中有一个处理程序,更优雅,但可能有点棘手)。

It works by putting all the of the objects in a set, and attaching a handler to each of them (you could possibly just have one handler on the group, more elegant but may be a bit trickier).

我们跟踪每个元素索引

this.data('index')

因此,当涉及到沿着线移动它们时,我们知道它在'链'中的位置并且可以抵消以补偿,即下面的行...

So when it comes to moving them along the line, we know where it is in the 'chain' and can offset to compensate, ie the following line...

 var whichDrag = this;
 ....
 mySet.forEach( function( el, i ) {

    var which = whichDrag.data("index") - i;
    pt = path.getPointAtLength(l + (which * spacer ));
    if( !isNaN(pt.x) && !isNaN(pt.x) ) { // check if over end
        el.transform('t' + pt.x + ',' + pt.y );
    };
 } ); 

完整代码......

Complete code...


var paper = Snap('#panel');

var spacer = 70;

var path = paper.path('M44.16,44.16 L44.16,44.16 L73.6,14.719999999999999 L132.48,73.6 L14.719999999999999,191.35999999999999 L132.48,309.12 L103.03999999999999,338.55999999999995 L44.16,279.67999999999995 L44.16,279.67999999999995')
.attr({
    stroke: 'gray',
    strokeWidth: 3,
    fill: 'none'
});
var pt = path.getPointAtLength(l);
    //e = r.ellipse(pt.x, pt.y, 4, 4).attr({stroke: "none", fill: "#f00"}),
var totLen = path.getTotalLength();


var r1 = paper.rect(0,0,10,10);
var c3 = paper.circle(0,0, 15);
var c2 = paper.circle(0,0, 15);
var c1 = paper.circle(0,0, 15);
var l = 0;
var searchDl = 1;

var cGroup = paper.g();
cGroup.add(c3,c2,c1,r1);

var mySet = cGroup.selectAll("*");

start = function () {
    this.data("ox", +this.getBBox().cx );
    this.data("oy", +this.getBBox().cy );
    this.attr({opacity: 1});
},
move = function (dx, dy) {
    var whichDrag = this;
    var tmpPt = {
        x : this.data("ox") + dx, 
        y : this.data("oy") + dy
    };
    // move will be called with dx and dy
    l = gradSearch(l, tmpPt);
    pt = path.getPointAtLength(l);
  //  this.attr({cx: pt.x, cy: pt.y});

    mySet.forEach( function( el, i ) {
        var which = whichDrag.data("index") - i;
        pt = path.getPointAtLength(l + (which * spacer ));
        if( !isNaN(pt.x) && !isNaN(pt.x) ) {
             //el.attr({cx: pt.x, cy: pt.y});
            el.transform('t' + pt.x + ',' + pt.y );
        };
    } );

},
up = function () {
    // restoring state
    this.attr({opacity: 1});
},

gradSearch = function (l0, pt) {
    l0 = l0 + totLen;
    var l1 = l0,
        dist0 = dist(path.getPointAtLength(l0 % totLen), pt),
        dist1,
        searchDir;

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

    l1 += searchDir;
    dist1 = dist(path.getPointAtLength(l1 % totLen), pt);
    while (dist1 

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

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