Javascript 使用矩阵围绕中心旋转Svg路径

Javascript 使用矩阵围绕中心旋转Svg路径,javascript,matrix,svg,Javascript,Matrix,Svg,我有许多不同大小的svg形状,我必须以不同的角度动态旋转它们。我想使用矩阵集中旋转它们,我在计算矩阵的e,f时遇到了一个问题。如何计算矩阵(a,b,c,d,e,f)中的e,f。我有一个角度,但不知道如何计算新的位置,所以看起来它在中心旋转。下面是一个例子形状,我旋转了45度, 基本上,你需要做的是加上你的X位置和负的Y位置。 比如说 如果你有这个代码 然后在第二个矩形中使用这些值,这样新的X位置将是25,新的Y位置将是-25。关于变换和矩阵乘法如何工作的介绍超出了堆栈溢出答案的范围。有大量

我有许多不同大小的svg形状,我必须以不同的角度动态旋转它们。我想使用矩阵集中旋转它们,我在计算矩阵的e,f时遇到了一个问题。如何计算矩阵(a,b,c,d,e,f)中的e,f。我有一个角度,但不知道如何计算新的位置,所以看起来它在中心旋转。下面是一个例子形状,我旋转了45度,


基本上,你需要做的是加上你的X位置和负的Y位置。 比如说

如果你有这个代码


然后在第二个矩形中使用这些值,这样新的X位置将是25,新的Y位置将是-25。关于变换和矩阵乘法如何工作的介绍超出了堆栈溢出答案的范围。有大量的在线资源可供参考

您可以阅读SVG规范中SVG转换的工作原理:

但基本上要围绕一个特定点(cx,cy)旋转角度(a),必须结合(矩阵乘法)三种运算:

  • 将中心向后平移到原点(-cx,-cy)
  • 执行旋转(a)
  • 翻译回原来的位置
  • 其中:

    ca = cos(angle)
    sa = sin(angle)
    
    这是一个演示。绿色矩形使用的是
    transform=“rotate(a,x,y)”
    ,红色矩形使用的是我们计算出的等效值

    var矩阵=getMatrixForRotation(45250250);
    document.getElementById(“myrect”).setAttribute(“转换”,矩阵);
    函数getMatrixForRotation(a、cx、cy)
    {
    var ca=Math.cos(a*Math.PI/180);
    var sa=Math.sin(a*Math.PI/180);
    var a=约固定(4);
    var b=sa.toFixed(4);
    var c=(-sa).toFixed(4);
    var d=约固定(4);
    var e=(-ca*cx+sa*cy+cx).toFixed(4);
    var f=(-sa*cx-ca*cy+cy).toFixed(4);
    返回“矩阵(“+[a,b,c,d,e,f]),连接(“”)+”;
    }
    
    
    使用
    矩阵()
    而不使用
    旋转(角度、cx、cy)
    有什么原因吗?技巧是围绕原点绘制
    (0,0),然后使用
    旋转(度)
    平移(x,y)
    。与矩阵(…)@PaulLeBeau相比,它可以一直工作,并且更容易阅读。我想学习旋转的机制,以及旋转在matrix@AlvinK. 我仍然需要使用矩阵
    rotate(degree offset-x offset-y)
    求解它,其中
    offset-x
    =width/2&
    offset-y
    =height/2。检查
    矩阵(…)
    是否等效于
    rotate()
    translate()
    。换言之,无论您使用其中一个或另一个,都等于相同的旋转。为什么要使用
    .toFixed
    ?这毫无必要地失去了准确性!两个原因:(1)JS数字是双精度的,而SVG数字是单精度的。所以我们不能直接将JS值作为字符串输出。(2) 外观整洁的输出。大多数情况下,四位小数就足够了。两个相反的论点:(1)是的,你可以看到这个。(2) 大部分时间并不是全部时间;当您可以提供不准确的代码时,为什么要提供失去准确性的代码?
        <rect x="0" y="0" width="50" height="50" style="stroke: #3333cc;          fill:none;" transform="matrix(1,0,0,1,100,100)"></rect>
    
        <rect x="25" y="-25" width="50" height="50" style="fill: #3333cc" transform="matrix(0.5,0.5,-0.5,0.5,100,100)"></rect>
    
    </svg>
    
    Divide the width by your x transform (0.5) : 50 / 0.5 = 25
    Divide the height by your y transform (0.5) : 50 / 0.5 = 25
    
    [1 0 cx] [cos(a) -sin(a) 0] [1 0 -cx] [0 1 cy] [sin(a) cos(a) 0] [0 1 -cy] [0 0 1 ] [ 0 0 1] [0 0 1 ] [cos(a) -sin(a) (-cos(a) * x + sin(a) * y + x)] [sin(a) cos(a) (-sin(a) * x - cos(a) * y + y)] [0 0 1 ]
    matrix( ca, sa, -sa, ca, (-ca * x + sa * y + x), (-sa * x - ca * y + y) )
    
    ca = cos(angle)
    sa = sin(angle)