如何在JavaScript中读取单个变换值?

时间:2010-08-07 23:27:43

标签: javascript 3d webkit css3 transform

去年在3D transforms上发布的Webkit博客文章解释了可以在-webkit-transform属性中使用的各种转换'函数'。例如:

#myDiv {
  -webkit-transform: scale(1.1) rotateY(7deg) translateZ(-1px);
}

我的问题:如何在JavaScript中访问个别值?当你读取元素的webkitTransform属性时,你只需要一个包含16个值的matrix3d()函数,就像这样......

matrix3d(0.958684, 0.000000, .....)

有没有办法只读取单个转换事物的值,比如rotateY()?或者我必须从matrix3d()字符串中读取它,以及如何?

11 个答案:

答案 0 :(得分:13)

// Suppose the transformed element is called "cover".
var element = document.getElementById('cover');
computedStyle = window.getComputedStyle(element, null); // "null" means this is not a pesudo style.
// You can retrieve the CSS3 matrix string by the following method.
var matrix = computedStyle.getPropertyValue('transform')
    || computedStyle.getPropertyValue('-moz-transform')
    || computedStyle.getPropertyValue('-webkit-transform')
    || computedStyle.getPropertyValue('-ms-transform')
    || computedStyle.getPropertyValue('-o-transform');

// Parse this string to obtain different attributes of the matrix.
// This regexp matches anything looks like this: anything(1, 2, 3, 4, 5, 6);
// Hence it matches both matrix strings:
// 2d: matrix(1,2,3,4,5,6)
// 3d: matrix3d(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
var matrixPattern = /^\w*\((((\d+)|(\d*\.\d+)),\s*)*((\d+)|(\d*\.\d+))\)/i;
var matrixValue = [];
if (matrixPattern.test(matrix)) { // When it satisfy the pattern.
    var matrixCopy = matrix.replace(/^\w*\(/, '').replace(')', '');
    console.log(matrixCopy);
    matrixValue = matrixCopy.split(/\s*,\s*/);
}

希望这有帮助! 请注意,除了普通的DOM API和本机Javascript RegExp函数之外,我没有使用其他库。因此,这应该普遍适用于跨浏览器和应用程序。

答案 1 :(得分:3)

我认为,正如syockit所说,迭代样式表是唯一的方法,你可以使用webkitMatchesSelector来发现符合你元素的规则:

var theRules = new Array();
var theStylesheet = document.styleSheets;
if (document.styleSheets[0].cssRules)
        theRules = document.styleSheets[0].cssRules
else if (document.styleSheets[0].rules)
        theRules = document.styleSheets[0].rules

var elem = document.getElementById("myDiv");

for (var i=0; i < theRules.length; i++) {
    if (elem.webkitMatchesSelector(theRules[i].selectorText)) {
        var theStyles = theRules[i].style;
        var j = theStyles.cssText.indexOf('-webkit-transform:');
        if (j>-1) {
            var s = theStyles.cssText.substring(j,theStyles.cssText.length).indexOf(';'); 
            document.getElementById("output").innerHTML=theStyles.cssText.substring(j+18,s);
        }
    }
}

这假设标记是这样的,我添加了一些额外的规则和值,以确保我提取正确的值。如果您有多个样式表,那么您需要调整第一部分以迭代所有样式表,如果-webkit-transform出现在多个规则中,您可能必须处理特异性:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Get style</title>
    <style>
    div {
        margin: 2em;
        padding: 2em;
    }
    #myDiv {
        -webkit-transform: scale(1.1) rotateY(7deg) translateZ(-1px);
        border: 1px solid;
    }
    </style>
</head>
<body>
    <div id="myDiv">
        Just testing.
    </div>
    <div id="output">
    </div>
</body>
</html>

答案 2 :(得分:3)

今天早上我遇到了这个问题。似乎JavaScript无法读取元素的style.webkitTransform属性,直到它在元素的style属性中显式设置(在HTML中内联或在程序上通过JavaScript)。听起来像kludgy,如果你需要JS能够读取CSS转换属性,那么当DOM准备就绪时,最好用JavaScript定义它们的初始值。

示例,使用jQuery:

$(document).ready(function(){
    $('.transform').css('webkitTransform', 'translateX(0)');
});

从现在开始,您将能够读取元素的变换字符串并通过它解析所需的值。

答案 3 :(得分:3)

旧但有趣的问题,以前没有回应尝试回答它。

不幸的是,对于一般情况没有双线解决方案,我们不知道需要逆向设计哪种变换步骤(旋转,平移等);越容易。

在最近的基于webkit的浏览器中,可以简单地查询先前分配的属性:

var element = document.querySelector('div.slipping');
element.style.webkitTransform 
  -> "translate(-464px, 0px)"

让我们继续假设需要使用计算出的样式。例如,如果元素处于CSS转换或CSS动画的中间,即当前转换不是直接设置的转换,则需要出现。

getComputedStyle返回的矩阵描述符字符串确实可以通过正则表达式进行解析,但并非上述所有版本都是可靠的,并且它们太不透明。一个简单的方法来分解字符串,除非它是一个非常紧密的循环以保证单遍正则表达式,是这样的:

var matrixString = window.getComputedStyle(element).webkitTransform;
var matrix = matrixString
             .split('(')[1]
             .split(')')[0]
             .split(',')
             .map(parseFloat);

但另一种方法是简单地使用这个,这在以前没有提到过:

var cssMatrix = new WebKitCSSMatrix(matrixString);

后一种方法的好处是你也得到了一个4x4矩阵,这是affine transformations的标准表示,缺点是它当然是特定于WebKit的。如果您继续使用问题中六个值的元组,则定义为in this part of the CSS standard

然后转换,例如轮换需要进行逆向工程。 CSS可以直接支持许多简单的转换,例如平移,缩放,旋转,倾斜和透视。如果只应用其中一个,那么您只需要恢复computing the transform matrix的过程。

另一种方法是查找或翻译在JS中为您执行此操作的代码,例如: the same documentSection 7.1 of the CSS standard包含此类带注释的算法。好处是unmatrix方法能够在某些限制下返回“原子”变换,即使应用了多个变换(平移,旋转等)。由于不可能保证对一般情况的转换步骤的成功逆向工程,因此考虑可能应用的转换类型以及是否已经避免退化或其他麻烦的情况是有用的。即您需要根据自己的问题构建解决方案。

具体来说,所有2D CSS变换的矩阵版本都是documented here as well,低于CSS 2D变换向量中六个值的含义。

另一个警告是,在几何操作方面存在影响视觉结果的其他因素,例如transform-origin

答案 4 :(得分:2)

link from Apple Dev Reference可能会更清楚地说明这个问题:

  

webkitTransform属性是   列表的字符串表示   变换操作。通常这个   列表包含单个矩阵   变换操作。对于3D   变换,价值是   “matrix3d(...)”具有16个值   4x4之间的均匀矩阵   括弧。对于2D变换,   value是一个“matrix(...)”字符串   包含6个向量值。

答案 5 :(得分:1)

由于您只从计算样式中获取最终矩阵值,因此可能必须检查元素的内联样式或样式表规则。如果element.style.webkitTransform没有给你任何东西,你可以遍历文档的样式表,看看哪个匹配你的元素。然后你可以正则表达webkitTransform属性来获取/设置值。

答案 6 :(得分:1)

您可以使用正则表达式获取属性值的地图:

如果变量transformstyle包含样式值

  //get all transform declarations
 (transformstyle.match(/([\w]+)\(([^\)]+)\)/g)||[]) 
      //make pairs of prop and value         
     .map(function(it){return it.replace(/\)$/,"").split(/\(/)})
     //convert to key-value map/object         
     .reduce(function(m,it){return m[it[0]]=it[1],m},{})

为:

var transformstyle="-webkit-transform: scale(1.1) rotateY(7deg) translateZ(-1px)"

你会得到:

{scale: "1.1", rotateY: "7deg", translateZ: "-1px"}

答案 7 :(得分:1)

仅仅因为我没有看到任何有效的Javascript one Line解决方案转换矩阵代码,这是我的。快速简便:

首先获取矩阵中的所有变换值:

var yourDivsCssValues= window.getComputedStyle(yourDiv, null);
transformValues = testDivCSS.getPropertyValue('transform');

将transform-y提取为整数:

var transformValueY = parseInt((yourVariable1.replace (/,/g, "")).split(" ")[5]);

将transform-x提取为整数:

var transformValuetX = parseInt((yourVariable2.replace (/,/g, "")).split(" ")[4]);

访问旋转值非常困难,但如果你想这样做,有一个很好的指南: https://css-tricks.com/get-value-of-css-rotation-through-javascript/

答案 8 :(得分:0)

我想到了一种可能性。如果您准备在JavaScript中解析字符串,请使用

data=document.getElementById("myDiv").getAttribute("-webkit-transform");

然后解释data

答案 9 :(得分:0)

从复杂的变换值中提取单个值的简便方法:

function parseComplexStyleProperty( str ){
   var regex = /(\w+)\((.+?)\)/g,
       transform = {},
       match;

   while( match = regex.exec(str) )
       transform[match[1]] = match[2];
  
   return transform;
}

//////////////////////////////////////////

var dummyString = "translateX(-50%) scale(1.2)",
    transformObj = parseComplexStyleProperty(dummyString);

console.log(transformObj);

答案 10 :(得分:0)

如果你想要完整的转换,你确实可以使用getComputedStyle(element).transform

但无论如何,只需使用 DOMMatrix 构造函数:new DOMMatrix(element.style.transform)。大功告成。