首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Javascript启动和编辑animateTransform

用Javascript启动和编辑animateTransform
EN

Stack Overflow用户
提问于 2012-01-12 10:11:20
回答 2查看 7.9K关注 0票数 4

我想通过一个转换矩阵(这是动态决定的)来转换SVG画布上的元素。我可以用JQuery动画()来完成它,但结果一点也不顺利。因此,我想使用本机SVG animateTransform,问题是:

  • 如何使它在我想要的时候启动(可能是beginElement()),以及
  • 如何动态地从矩阵中设置参数?

预先感谢:D

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-14 12:56:47

谢谢你的回答!由于我想使用本地SVG动画,所以我找到了这个解决方案(仍然不能很好地工作)。这是不存在的animateTransform(attributeName="transform“”type=“矩阵)的一种版本。

注意:我保留了group.transform中每个元素的svg转换,而group.transform.matrix()只返回该元素的转换矩阵。

我首先将这些元素添加到我想要动画的元素中:

代码语言:javascript
复制
<animateTransform id="canvTranslate" begin="indefinite" attributeName="transform" type="translate" to="" dur="1s" additive="sum" fill="freeze"/>
<animateTransform id="canvRotate" begin="indefinite" attributeName="transform" type="rotate" to="" dur="1s" additive="sum" fill="freeze"/>
<animateTransform id="canvScale" begin="indefinite" attributeName="transform" type="scale" to="" dur="1s" additive="sum" fill="freeze"/>

那我就做:

代码语言:javascript
复制
 var tMatrix = transformation.matrix(); //this is the transformation i want to obtain
    var cMatrix = group.transform.matrix(); //this is the actual CTM of the element

    //getting the animations
    var animTrans = document.getElementById('canvTranslate');
    var animRotaz = document.getElementById('canvRotate');
    var animScale = document.getElementById('canvScale');

    //setting duration (it's got somewhere before)
    animTrans.setAttribute('dur', duration/1000+'s');
    animRotaz.setAttribute('dur', duration/1000+'s');
    animScale.setAttribute('dur', duration/1000+'s');

    //calculating the 'from' attribute
    var transX = cMatrix.e;
    var transY = cMatrix.f;
    var scaleX = Math.sqrt(Math.pow(cMatrix.a, 2)+Math.pow(cMatrix.b, 2));
        var rotate = Math.atan(cMatrix.c/cMatrix.d);

    animTrans.setAttribute('from', transX+','+transY);
    animRotaz.setAttribute('from', -rotate*180/Math.PI);
    animScale.setAttribute('from', scaleX);
    //end 'from'

    //calculating the 'to' attribute to set
    var transX = tMatrix.e;
    var transY = tMatrix.f;
    var scaleX = Math.sqrt(Math.pow(tMatrix.a, 2)+Math.pow(tMatrix.b, 2));
    var rotate = Math.atan(tMatrix.c/tMatrix.d);

    animTrans.setAttribute('to', transX+','+transY);
    animRotaz.setAttribute('to', -rotate*180/Math.PI);
    animScale.setAttribute('to', scaleX);
    //end 'to'

    animTrans.beginElement();
    animRotaz.beginElement();
    animScale.beginElement();

group.transform = transformation;,最后,更新元素的transform属性:

代码语言:javascript
复制
    setTimeout(function(){ //i will change this somehow better :)

        //this is a problematic step. with it animations work on Chrome, without it they work good on firefox and opera too
        $(group).attr('transform', 'matrix('+tMatrix.a+','+tMatrix.b+','+tMatrix.c+','+tMatrix.d+','+tMatrix.e+','+tMatrix.f+')');
    }, duration+100);

最后一步是有问题的一步。我不明白为什么它在Chrome中运行得很好,而在火狐和Opera中动画的规模却要大得多(在这里,不调用setTimeout很好)。

票数 3
EN

Stack Overflow用户

发布于 2012-01-12 16:27:50

动画可以用许多不同的方式来完成。

向图形/形状元素添加动画元素适用于预定义动画。“动画元素”提供了非常简短的贴心解决方案,演示:http://jsfiddle.net/UjuR8

交互式动画需要更多的手工解决方案与相当多的Javascript样板代码。您必须创建一个函数render,它将被requestAnimationFrame每秒调用60次(参见http://paulirish.com/2011/requestanimationframe-for-smart-animating/)。在render中,您可以获得“当前转换矩阵”(CTM),并在此基础上应用更改。这是一个很小的概念证明:http://jsfiddle.net/PaSD8/

在一个大项目中,我建议包装SVG元素,也许可以不使用字符串连接,而直接使用矩阵和转换来完成动画。这是一个我躺在旁边的例子类:

代码语言:javascript
复制
var SVG, Object2D;

SVG = document.querySelector( 'svg' );

// ...

Object2D = ( function () {
  var proto;

  function Object2D ( domElement ) {
    this.domElement = domElement;
    this.transform  = SVG.createSVGTransform();
    this.matrix     = SVG.createSVGMatrix();
    this.position   = SVG.createSVGPoint();
    this.rotation   = 0;
    this.scale      = 1;
  }


  proto = Object2D.prototype;


  proto.draw = function ( timestamp ) {
    // update scale and position, apply rotation
    var transform = this.transform,
        matrix    = this.matrix,
        position  = this.position,
        rotation  = this.rotation,
        scale     = this.scale;

    matrix.a = scale;
    matrix.d = scale;
    matrix.e = position.x;
    matrix.f = position.y;

    transform.setMatrix( matrix.multiply( rotation ) );
    this.domElement.transform.baseVal.initialize( transform ); // clear then put
  };


  return Object2D;
} )();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8833290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档