原文地址: https://css-tricks.com/get-value-of-css-rotation-through-javascript/
一条来自Aditya的评论:
在javascript当中,能否有一种方法可以获取到元素的旋转角度?
这个看起来是个很合理的要求。所以,我们先写一段html
<div id="i-am-rotated">text</div>
接下来,利用css将它旋转一定角度。
#i-am-rotated {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
}
我们的目标是通过javascript,获取到数值为30的属性。通常情况下,我们获取以一个元素的css的属性值使用用这样的方法。 getComutedStyle() (只有现代的浏览器和IE9+才支持这个方法,老版本的IE仅支持 currentStyle())。我们现在利用 getComutedStyle() 方法尝试去获取样式。
顺便说一句,如果你先知道怎么去兼容两者,建议去看我之前写的博客。
var el = document.getElementById("i-am-rotated");
var st = window.getComputedStyle(el, null);
var tr = st.getPropertyValue("-webkit-transform") ||
st.getPropertyValue("-moz-transform") ||
st.getPropertyValue("-ms-transform") ||
st.getPropertyValue("-o-transform") ||
st.getPropertyValue("transform") ||
"Either no transform set, or browser doesn't do getComputedStyle";
你可能认为返回的值将会是“rotate(30deg)”然后,我们可以使用parseInt()进行类型转换得到”30”。但是,非常不幸的是——他将不起作用。因为,事实上,我们获取到的返回值是这样的
console.log(tr);
// matrix(0.8660254037844387, 0.49999999999999994, -0.49999999999999994, 0.8660254037844387, 0, 0)
浏览器将CSS的旋转属性转化成了矩阵。我猜象它可能是,它可能是一个元素上面transform属性值的简化版。所以,我们改做点什么呢?
Nicolas Gallager研究过矩阵变化所对应的旋转变化。其本质是这样的
rotate(Xdeg) = matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
我们现在仅仅需要一个可以转化的公式。我们需要得到 arcsin的值(就是sin的倒数,sin-1)。以确保它能转化成弧度。
首先,我们必须将开手头上面的数据分割成独立的矩阵值。
// UPDATE: below was causing errors sometimes...
// var values = tr.split('(')[1].split(')')[0].split(',');
// Replace with... (thanks Thierry)
var values = tr.split('(')[1],
values = values.split(')')[0],
values = values.split(',');
var a = values[0]; // 0.866025
var b = values[1]; // 0.5
var c = values[2]; // -0.5
var d = values[3]; // 0.866025
我们都知道
sin(X) == 0.5 so asin(0.5) == radians 和 degrees == radians * 180/π.公式
所以:
var angle = Math.round(Math.asin(b) * (180/Math.PI));
console.log(angle);
网友补充:
一位叫做Nicolas的网友做了一点改进,可以得出scale的属性值。
#complex-transform {
-webkit-transform: rotate(30deg) scale(1.2) skew(10deg) translate(5px, 5px);
-moz-transform: rotate(30deg) scale(1.2) skew(10deg) translate(5px, 5px);
-ms-transform: rotate(30deg) scale(1.2) skew(10deg) translate(5px, 5px);
-o-transform: rotate(30deg) scale(1.2) skew(10deg) translate(5px, 5px);
}
var el = document.getElementById("complex-transform");
var st = window.getComputedStyle(el, null);
var tr = st.getPropertyValue("-webkit-transform") ||
st.getPropertyValue("-moz-transform") ||
st.getPropertyValue("-ms-transform") ||
st.getPropertyValue("-o-transform") ||
st.getPropertyValue("transform") ||
"fail...";
// With rotate(30deg)...
// matrix(0.866025, 0.5, -0.5, 0.866025, 0px, 0px)
console.log('Matrix: ' + tr);
// rotation matrix - http://en.wikipedia.org/wiki/Rotation_matrix
var values = tr.split('(')[1];
values = values.split(')')[0];
values = values.split(',');
var a = values[0];
var b = values[1];
var c = values[2];
var d = values[3];
var scale = Math.sqrt(a*a + b*b);
// arc sin, convert from radians to degrees, round
// DO NOT USE: see update below
var sin = b/scale;
var angle = Math.round(Math.asin(sin) * (180/Math.PI));
// works!
console.log('Rotate: ' + angle + 'deg');
大家都知道,在数学的象限里面。sin(30) = sin(150)。所以得出的角度不可靠。
不知道大家还记不记得这张图。只有利用tan。
最后改进,这样才能更精确的计算出角度。
var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
至于源码,大家自己去访问博客原址。
原文的评论下面,还有很多精文。很不错。在此就不多说废话了。
自己的话:
其实我感觉tan也不可靠。270。的时候 返回的是-90。这样的问题,在stackoverflow上面也有解决 但是 他在0。 360。时候是。是用判断解决问题。不是利用公式 这里再放一个好公式。当然,也是借鉴别人的!
var radians = Math.atan2(b, a);
if ( radians < 0 ) {
radians += (2 * Math.PI);
}
var angle = Math.round( radians * (180/Math.PI));
第一次翻译外文,不足之处,请多包涵!