Javascript 如何组合元素转换?

Javascript 如何组合元素转换?,javascript,css,html,linear-algebra,css-transforms,Javascript,Css,Html,Linear Algebra,Css Transforms,在HTML5中,我想实现画布元素的转换功能,这样用户就可以翻译(移动),缩放(放大/缩小)和旋转画布元素。每个这样的变换都可以用不同的变换原点来完成 第一种转换很容易: function transform(el, value, origin) { el.style.Transform = value; el.style.MozTransform = value; el.style.msTransform = value; el.style.OTransform = value;

在HTML5中,我想实现画布元素的转换功能,这样用户就可以
翻译
(移动),
缩放
(放大/缩小)和
旋转
画布元素。每个这样的变换都可以用不同的变换原点来完成

第一种转换很容易:

function transform(el, value, origin) {
  el.style.Transform = value;
  el.style.MozTransform = value;
  el.style.msTransform = value;
  el.style.OTransform = value;
  el.style.webkitTransform = value;
  el.style.TransformOrigin = origin;
  el.style.MozTransformOrigin = origin;
  el.style.msTransformOrigin = origin;
  el.style.OTransformOrigin = origin;
  el.style.webkitTransformOrigin = origin;
}

transform(myCanvas, 'translate('+ dx +'px, ' + dy + 'px) ' +
                    'scale(' + zoom + ', ' + zoom + ') ' +
                    'rotate(' + angle + 'deg)',
                    cx + 'px ' + cy + 'px');
用户将移动、缩放或旋转图元,而不是一次移动所有图元,因此某些转换参数将保持默认值(dx=0,dy=0,zoom=1,angle=0)


在这样的转换之后,如果用户想要进行另一次转换(以及其他转换,以及其他转换…),我如何将(dx1、dy1、zoom1、angle1、cx1、cy1)与(dx2、dy2、zoom2、angle2、cx2、cy2)组合以获得最终值,这些值可以在以后与新的转换参数组合?我无法将另一个转换附加到
transform
参数,因为
tranform origin
可能不同。有没有一个公式可以将变换与不同的变换原点结合起来?

你必须处理矩阵变换

每个线性运算都可以用一个3x3矩阵和一个3x1向量表示,可以应用于平面的点上。如果p是一个点,M是矩阵,q是另一个向量,则每个线性变换都可以表示为Mp+q

如果有一个2d点,则其向量将为[x;y;1](垂直向量),而矩阵可以有多种形式

对于转换,矩阵就是单位矩阵。向量q是平移向量

对于缩放,M类似于

其中a和b分别是x和y的比例因子。向量q为空

对于旋转,比如说角度a,你会得到

    [cos(a) -sin(a) 0]
M = [sin(a)  cos(a) 0]
    [  0       0    1]
q又是空的

也有用于倾斜的矩阵。所以,如果你必须应用三个连续的变换,你必须应用这些线性变换。你的问题是你也必须处理原点,所以你必须从p中减去向量o,然后应用M,加q,然后再加o

假设你有这些变换(M1,q1,o1)和(M2,q2,o2)。当你申请第一个你得到的

p1 = M1 * (p - o1) + q1 + o1
然后,您必须应用第二个转换:

p2 = M2 * (p1 - o2) + q2 + o2
最终你会得到:

p2 = M2 * (M1 * (p - o1) + q1 + o1 - o2) + q2 + o2
以此类推,最后是第三个(M3、q3、o3)

一团糟?看起来像。但是如果你知道矩阵的样子,事情可以简化一点


现在,进行数学运算,并将其应用于变换:矩阵(a,b,c,d,tx,ty)

您不必学习矩阵数学。据

  • 从身份矩阵开始
  • 通过“变换原点”的计算X、Y和Z值进行平移
  • 依次乘以“transform”属性中的每个变换函数
  • 通过“变换原点”的求反计算的X、Y和Z值进行平移
  • 换句话说,
    变换原点:A;transform:B
    与transform:translate(-A)B translate(A)
    相同。(转换从右向左应用,因此您希望发生的第一件事是在末尾。)

    因此,使用上面的规则来消除
    变换原点
    ,现在您只需要连接普通变换

    例如:

  • 变换原点:5px 5px;转换:转换(10px,40px)
  • 变换原点:25px 30px;变换:比例(2)
  • 变换原点:10px 10px;变换:旋转(30度)
  • 变成

  • transform:translate(-5px,-5px)translate(10px,40px)translate(5px,5px)
  • transform:translate(-25px,-30px)比例(2)translate(25px,30px)
  • 变换:平移(-10px,-10px)旋转(30度)平移(10px,10px)
  • 现在您可以合并它们,因为它们都同意来源(即,无来源)

    变换:平移(-5px,-5px)平移(10px,40px)平移(5px,5px)平移(-25px,-30px)缩放(2)平移(25px,30px)平移(-10px,-10px)旋转(30度)平移(10px,10px)

    当然,如果需要,可以折叠连续的翻译

    变换:平移(-15px,10px)缩放(2)平移(15px,20px)旋转(30度)平移(10px,10px)

    或者你可以翻出你的数学课本,然后


    编辑:从右向左应用变换。

    您尝试过将其可视化吗?在纸上画一个盒子。然后,考虑当你想要翻译/旋转/缩放框时会发生什么。再一次。@RobW-我花了一个多星期的时间做了很多尝试:-/我能够组合无限移动(平移)和缩放(缩放)变换,但一旦涉及到旋转,我就迷路了……我不确定线性代数标签是否属于这个问题。它更多的是结合CSS属性,而不是使用线性代数。在上一个公式中,我准确地写了如何处理起源。请记住,虽然矩阵积不是可交换的,但它是线性的,因此
    p2=M2*M1*(p-o1)+M2*(q1+o1-o2)+q2+o2
    。只是要说清楚,你的组合变换以M2xM1为矩阵,以o1为原点,以M2(q1+o1-o2)+q2+o2为转换向量。你是天才,但我不是。很抱歉我只有矩阵(M1,M2,…)用于变换和原点(o1,o2,…)。我不想计算每个点(p),我想计算最终的矩阵(M),它可以作为多重变换的组合。我遗漏了什么吗?不,先生,你是对的。但是您必须计算矩阵和平移向量,然后在
    transform:matrix(…)
    中使用它们的值。我的建议是创建一个函数来组合两个线性变换,知道它们的种类(缩放、旋转、平移)和参数。我们中的任何一个都没有得到Omega想要的。我认为问题在于已知3种转换,但它们的起源因之前的转换而改变。另外,到目前为止,我从未使用过CSS
    transform
    ,但是您不应该减去
    p2 = M2 * (M1 * (p - o1) + q1 + o1 - o2) + q2 + o2