【问题标题】:Raphael JS : how to move/animate a path object?Raphael JS:如何移动/动画路径对象?
【发布时间】:2011-06-08 16:35:12
【问题描述】:

不知怎的,这不起作用......

var paper = Raphael("test", 500, 500);

var testpath = paper.path('M100 100L190 190');

var a = paper.rect(0,0,10,10);
a.attr('fill', 'silver');

a.mousedown( function() {
  testpath.animate({x: 400}, 1000);
});

我可以以这种方式移动矩形,但不能移动路径,为什么会这样,那么我该如何移动路径对象?!

【问题讨论】:

  • 有没有在线示例即jsbin

标签: javascript animation path raphael move


【解决方案1】:

使用最新版本的 Raphael,您可以这样做:

var _transformedPath = Raphael.transformPath('M100 100L190 190', 'T400,0');
testpath.animate({path: _transformedPath}, 1000);

这使您免于必须clone 临时对象的麻烦。

【讨论】:

  • 这是最正确的答案,因为它包含了 Raphael 的最新功能,并分两行解决。像魅力一样工作,谢谢。
  • 我唯一要添加的是获得一个实际的动画,你必须在第二个大括号之后包含一个速度参数,如下所示:({path: _transformedPath},1000);
  • 最佳答案在这里,也是最简单的!
【解决方案2】:

似乎 path 对象没有获得 x,y 值 - 所以您的动画可能仍在运行,但什么也不做。尝试为路径函数设置动画:

testpath.animate({path:'M400 100L490 190'},1000);

编写动画有点棘手,但您可以免费获得旋转和缩放的好处!

顺便说一句:我确定这只是一个示例,但在您上面的代码中,testpath 被放入全局范围内,因为您没有初始化为 var testpath

【讨论】:

    【解决方案3】:

    已解决,感谢 Rudu!

    您需要创建一个新的动画路径。您可以使用 clone() 执行此操作,然后将转换应用于该克隆。像这样一个简单的动作似乎很复杂,但它确实有效......

    var paper = Raphael("test", 500, 500);
    
    var testpath = paper.path('M100 100L190 190');
    
    var a = paper.rect(0,0,10,10);
    a.attr('fill', 'silver');
    
    a.mousedown( function() {
    
      var temp = testpath.clone();
      temp.translate(400,0);
      testpath.animate({path: temp.attr('path')}, 1000);
      temp.remove();
    
    });
    

    【讨论】:

    • 你的意思是var temp=testpath.clone(); ;)
    • 非常好。另一个答案完全忽略了您不想为了侧向跳跃而定义新路径的面孔。好话。
    【解决方案4】:

    TimDog 的回答是最好的解决方案。

    另外,请记住,在这种情况下,变换字符串的意思是,它将为每个路径点/线 X 坐标添加 400 个点,每个 Y 坐标添加 0 个点。

    这意味着,M100 100L190 190 将变成M500 100L590 190

    因此,如果您需要将路径元素移动到另一个位置,则应计算当前位置与新位置坐标之间的差异。您可以使用第一个元素来做到这一点:

    var newCoordinates = [300, 200],
    curPos = testpath.path[0],
    newPosX = newCoordinates[0] - curPos[1],
    newPosY = newCoordinates[1] - curPos[2];
    
    var _transformedPath = Raphael.transformPath(testpath.path, "T"+newPosX+","+newPosY);
    testpath.animate({path: _transformedPath});
    

    希望这会对某人有所帮助。

    【讨论】:

      【解决方案5】:

      以下代码概括了上述最佳答案,并为 Raphael 路径提供了一个简单的 .attr({pathXY: [newXPos, newYPos]}) 属性,类似于形状的 .attr({x: newXPosition}).animate({x: newXPosition})

      这可让您以标准方式将路径移动到固定的绝对位置移动相对量,无需硬编码路径字符串或自定义计算。 p>


      编辑:以下代码适用于 IE7 和 IE8。由于a Raphael bug that returns arrays to .attr('path') in SVG mode but strings to .attr('path') in VML mode,早期版本在 IE8 / VML 模式下失败。


      代码

      在定义paper后添加此代码(Raphael customAttribute和辅助函数),使用如下。

      paper.customAttributes.pathXY = function( x,y ) {
        // use with .attr({pathXY: [x,y]});
        // call element.pathXY() before animating with .animate({pathXY: [x,y]})
        var pathArray = Raphael.parsePathString(this.attr('path'));
        var transformArray = ['T', x - this.pathXY('x'), y - this.pathXY('y') ];
          return { 
            path: Raphael.transformPath( pathArray, transformArray) 
          };
      };
      Raphael.st.pathXY = function(xy) { 
         // pass 'x' or 'y' to get average x or y pos of set
         // pass nothing to initiate set for pathXY animation
         // recursive to work for sets, sets of sets, etc
         var sum = 0, counter = 0;
         this.forEach( function( element ){
           var position = ( element.pathXY(xy) );
           if(position){
             sum += parseFloat(position);
             counter++;
           }
         });
         return (sum / counter);
      };
      Raphael.el.pathXY = function(xy) {
         // pass 'x' or 'y' to get x or y pos of element
         // pass nothing to initiate element for pathXY animation
         // can use in same way for elements and sets alike
         if(xy == 'x' || xy == 'y'){ // to get x or y of path
           xy = (xy == 'x') ? 1 : 2;
           var pathPos = Raphael.parsePathString(this.attr('path'))[0][xy];
           return pathPos;
         } else { // to initialise a path's pathXY, for animation
           this.attr({pathXY: [this.pathXY('x'),this.pathXY('y')]});
         }
      };
      

      用法

      对于绝对平移(移动固定X、Y位置)-Live JSBIN demo

      适用于任何路径或set of paths including sets of sets (demo)。请注意,由于 Raphael 集合是数组而不是组,因此它将集合中的每个项目移动到定义的位置 - 而不是集合的中心。

      // moves to x=200, y=300 regardless of previous transformations
      path.attr({pathXY: [200,300]});
      
      // moves x only, keeps current y position
      path.attr({pathXY: [200,path.pathXY('y')]});
      
      // moves y only, keeps current x position
      path.attr({pathXY: [path.pathXY('x'),300]});
      

      Raphael 需要在同一个 customAttribute 中同时处理 x 和 y 坐标,以便它们可以一起制作动画并保持彼此同步。

      用于相对平移(移动 +/- X,Y) - Live JSBIN demo

      // moves down, right by 10
      path.attr({pathXY: [ path.pathXY('x')+10, path.pathXY('y')+10 ]},500);
      

      这也适用于集合,但同样不要忘记 Raphael 的集合不像组 - 每个对象相对于集合的平均位置移动到一个位置,因此结果可能不是预期的 (@987654326 @)。


      用于动画(将路径移动到相对或绝对位置)

      在第一次制作动画之前,您需要设置 pathXY 值,这是由于 Raphael 2.1.0 之前的一个错误/缺失功能,其中所有 customAttributes 都需要在它们被赋予之前被赋予一个数值动画(否则,他们会将每个数字都变成 NaN 并且什么都不做,默默地失败而没有错误,或者没有动画并直接跳到最终位置)。

      在使用.animate({pathXY: [newX,newY]});之前,运行这个辅助函数:

      somePath.pathXY();
      

      【讨论】:

        【解决方案6】:

        还有一种方法是使用“transform”属性:

        testpath.animate({transform: "t400,0"}, 1000);
        

        将路径相对于原始位置向右移动 400 像素。

        这应该适用于所有形状,包括路径和矩形。

        注意:

        • “transform”属性独立于x、y、cx、cy等,所以上面的动画不会更新这些属性。
        • “transform”属性的值始终基于原始位置,而不是当前位置。如果在上面的动画之后应用下面的动画,它会相对向左移动800px,而不是回到原来的位置。

          testpath.animate({transform: "t-400,0"}, 1000);
          

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-06-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-17
          • 1970-01-01
          相关资源
          最近更新 更多