为 transform: rotate 创建一个跨浏览器的 mixin

20

我想创建一个Sass mixin,可以对指定元素应用旋转。这个mixin应该有一个参数,用于指定要应用的旋转角度。

在css3please.com上,我找到了一种跨浏览器实现该效果的CSS方法:

.box_rotate {
     -moz-transform: rotate(7.5deg);  /* FF3.5+ */
       -o-transform: rotate(7.5deg);  /* Opera 10.5 */
  -webkit-transform: rotate(7.5deg);  /* Saf3.1+, Chrome */
      -ms-transform: rotate(7.5deg);  /* IE9 */
          transform: rotate(7.5deg);  
             filter: progid:DXImageTransform.Microsoft.Matrix(/* IE6–IE9  */
                     M11=0.9914448613738104, M12=-0.13052619222005157,M21=0.13052619222005157, M22=0.9914448613738104, sizingMethod='auto expand');
               zoom: 1;
}

除了讨厌的IE矩阵符号外,这一切都很容易制作成一个mixin。是否有人有任何建议,可以使用Sass、JavaScript或两者的组合将度数转换为IE矩阵变换?


如果有人感兴趣,我写了这个mixin,并且它托管在这里:https://github.com/adambom/CSS3-Please-for-SASS - Adam
我知道使用IE的filter/Matrix Transform的最大问题是,当一个盒子被旋转时,它并不是围绕着盒子的中心旋转。想象一下旋转盒子,画一个最小包含旋转盒子的矩形,然后将该容器放置在盒子原来的位置。这会产生一个偏移量,这些解决方案(截至2012年10月31日)都没有考虑到。如果这个说法不太清楚,请这样想:如果你在html body的开头只使用IE中的矩阵旋转一个盒子,那么旋转后的盒子将完全可见。在其他浏览器中,它将被裁剪。 - JayC
5个回答

21

这里是答案:

SASS:

@mixin rotate( $degrees )
  -webkit-transform: rotate(#{$degrees}deg)
  -moz-transform: rotate(#{$degrees}deg)
  -ms-transform: rotate(#{$degrees}deg)
  -o-transform: rotate(#{$degrees}deg)
  transform: rotate(#{$degrees}deg)

  filter:  progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=#{cos($degrees)}, M12=-#{sin($degrees)}, M21=#{sin($degrees)}, M22=#{cos($degrees)})
  -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=#{cos($degrees)}, M12=-#{sin($degrees)}, M21=#{sin($degrees)}, M22=#{cos($degrees)})"
  zoom: 1

SCSS:

@mixin rotate( $degrees ) {
  -webkit-transform: rotate(#{$degrees}deg);
  -moz-transform: rotate(#{$degrees}deg);
  -ms-transform: rotate(#{$degrees}deg);
  -o-transform: rotate(#{$degrees}deg);
  transform: rotate(#{$degrees}deg);

  filter:  progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=#{cos($degrees)}, M12=-#{sin($degrees)}, M21=#{sin($degrees)}, M22=#{cos($degrees)});
  -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=#{cos($degrees)}, M12=-#{sin($degrees)}, M21=#{sin($degrees)}, M22=#{cos($degrees)})";
  zoom: 1;
 }

用法:

@include rotate( 24 )

或者你可以简单地使用Compass,让你的生活变得更加轻松 :P


看起来前缀声明应该是rotate(#{$degrees}deg);但感谢IE声明 :) - mlarcher
1
还有一件事需要注意,Compass的sin和cos函数期望弧度而不是角度,因此可以使用类似$rad : $deg * pi() / 180;这样的前缀,并在cos和sin函数中使用$rad - J Griffiths

10

旋转矩阵是这样定义的

[[cos(A), -sin(A)],
 [sin(A),  cos(A)]]

其中A是角度。IE矩阵中的M11是第一行的第一个元素;M12是第一行的第二个元素,以此类推。

JavaScript的Math.sinMath.cos函数使用弧度制,因此您需要将度数转换为弧度。

radians = degrees * Math.PI / 180

将它们组合起来,我们得到以下函数:

function rotationMatrix(degrees) {
  var A = degrees * Math.PI / 180;
  return [[Math.cos(A), -Math.sin(A)], [Math.sin(A),  Math.cos(A)]]
}

示例:

rotationMatrix(10) 
// => [[0.984807753012208, -0.17364817766693033], 
//     [0.17364817766693033, 0.984807753012208]]

1
通常情况下,您会将最佳答案标记为您的已接受答案。而不是第一个回答,但如果您认为@lbdremy的答案是最好的! - ase
我只需要算法,但最终还是在Sass中编写了这个函数。 - Adam

7

此函数可将度数转换为IE矩阵变换。

//deg input defines the requested angle of rotation.
function degreeToIEMatrix(deg){   
    var deg2radians = Math.PI * 2 / 360;
    var rad = deg * deg2radians ;
    var costheta = Math.cos(rad);
    var sintheta = Math.sin(rad);

    var M11 = costheta;
    var M12 = -sintheta;
    var M21 = sintheta;
    var M22 = costheta;
}

您可以在这里找到更多关于元素旋转和IE矩阵滤镜的信息。


1
不应鼓励使用隐式全局变量。 - ase
1
你的函数中每个变量定义都会创建一个全局变量。你需要使用 var 来创建局部变量。 - ase
1
我现在明白你为什么说“隐式”的了,谢谢@adamse。有关作用域的更多信息,请访问http://rx4ajax-jscore.com/ecmacore/more/scope.html。 - Remy

1
这是@Remy代码的一个版本,适用于javascript控制台。只需将其粘贴到控制台中,然后尝试makeIErotate(270),它将输出跨浏览器样式,准备粘贴到CSS文件中。
注意:除非您有纯色背景,否则IE中的抗锯齿效果很丑陋-即使有时也会很模糊。更多信息
function makeIErotate(deg) {    
    var deg2radians = Math.PI * 2 / 360;
    var rad = deg * deg2radians ;
    var costheta = Math.cos(rad);
    var sintheta = Math.sin(rad);
    return "-moz-transform: rotate(" + deg + "deg);\n\
            -o-transform: rotate(" + deg + "deg);\n\
            -webkit-transform: rotate(" + deg + "deg);\n\
            -ms-transform: rotate(" + deg + "deg);\n\
            transform: rotate(" + deg + "deg);\n\
            filter: progid:DXImageTransform.Microsoft.Matrix(\n\
                    M11=" + costheta + ",\n\
                    M12=" + -sintheta + ",\n\
                    M21=" + sintheta + ",\n\
                    M22=" + costheta + ", sizingMethod='auto expand');";
}

0

要使用mixin,您应该使用

@include rotate(24)

1
RobinH的回答是正确的。如果你正在使用Compass(而且你应该这样做),那么它就像输入以下内容一样简单:.yourbox {@include rotate(-90deg);} 让Compass来完成所有的繁重工作,保持你的代码整洁 =) - C13L0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接