Javascript 如何组合元素转换?
在HTML5中,我想实现画布元素的转换功能,这样用户就可以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;
翻译(移动),缩放(放大/缩小)和旋转画布元素。每个这样的变换都可以用不同的变换原点来完成
第一种转换很容易:
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种转换,但它们的起源因之前的转换而改变。另外,到目前为止,我从未使用过CSStransform
,但是您不应该减去
p2 = M2 * (M1 * (p - o1) + q1 + o1 - o2) + q2 + o2