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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3432446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 01:09:09  来源:igfitidea点击:

How to read individual transform values in JavaScript?

javascript3dwebkitcsstransform

提问by callum

Webkit's blog post from last year on 3D transformsexplains the various transform 'functions' that can be used in the -webkit-transform property. For example:

Webkit 去年关于3D 变换的博客文章解释了可以在 -webkit-transform 属性中使用的各种变换“函数”。例如:

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

My question: how do you access individual values in JavaScript? When you read the webkitTransform property of the element, you just get a matrix3d() function with 16 values in it, like this...

我的问题:如何访问 JavaScript 中的单个值?当您读取元素的 webkitTransform 属性时,您只会得到一个包含 16 个值的 matrix3d() 函数,就像这样...

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

Is there a way to just read the value of an individual transform thing, like rotateY()? Or do I have to read it from the matrix3d() string, and how?

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

回答by lixiang

// 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*/);
}

Hope this helps! Note that I did not use another library except plain DOM API and native Javascript RegExp function. Hence, this should work universally cross browsers and application.

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

回答by robertc

I think, as syockit says, iterating through the stylesheets is the only way to go, you can use webkitMatchesSelectorto discover rules which match your element:

我认为,正如 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);
        }
    }
}

This assumes markup something like this, I added some extra rules and values to make sure I was pulling out the right values. If you have more than one stylesheet then you need to adjust the first part to iterate through all the stylesheets too, and you'll probably have to deal with specificity if your -webkit-transformappears in more than one rule:

这假设标记是这样的,我添加了一些额外的规则和值以确保我提取了正确的值。如果您有多个样式表,那么您也需要调整第一部分以遍历所有样式表,如果您-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>

回答by Aaron

I ran into this issue this morning. It appears that JavaScript can't read an element's style.webkitTransformproperty until it's been explicitly set in the element's styleattribute (either inline in the HTML or procedurally via JavaScript). As kludgy as this sounds, if you need JS to be able to read CSS transform properties, you might be better off defining their initial values with JavaScript when the DOM is ready.

我今天早上遇到了这个问题。似乎 JavaScript 无法读取元素的style.webkitTransform属性,除非它在元素的style属性中被显式设置(在 HTML 中内联或通过 JavaScript 程序化)。尽管这听起来很笨拙,但如果您需要 JS 来读取 CSS 转换属性,则最好在 DOM 准备就绪时使用 JavaScript 定义它们的初始值。

Example, using jQuery:

示例,使用 jQuery:

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

From this point forward, you'll be able to read the element's transform string and parse through it for the needed values.

从现在开始,您将能够读取元素的转换字符串并解析它以获得所需的值。

回答by Robert Monfera

Old but interesting question and no previous response has attempted to answer it.

古老但有趣的问题,之前没有人试图回答它。

Unfortunately there's no two-liner solution for the general case and we don't know about what variety of transform steps (rotate, translate etc.) need to be reverse engineered; the fewer the easier.

不幸的是,对于一般情况没有两行解决方案,我们不知道需要对哪些变换步骤(旋转、平移等)进行逆向工程;越少越容易。

In recent webkit based browsers, one can simply query the previously assigned property:

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

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

Let's continue with the assumption that the computed style needs to be used. The need arises, for example, if the element is in the middle of a CSS transition or CSS animation, i.e. the current transformation is not one that was set directly.

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

The matrix descriptor string returned by getComputedStyle can indeed be parsed via a regex, but not all versions above are reliable, and they're too opaque. A straightforward way to break down the string, unless it's in a very tight loop to warrant a single-pass regex, is this:

getComputedStyle 返回的矩阵描述符字符串确实可以通过正则表达式解析,但并非以上所有版本都是可靠的,而且它们太不透明了。分解字符串的直接方法是:

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

But another way is to simply use this, which wasn't mentioned before:

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

var cssMatrix = new WebKitCSSMatrix(matrixString);

The benefit of the latter approach is that you get back a 4x4 matrix as well, which is the standard representation for affine transformations, and the drawback is that it's of course WebKit specific. Should you continue to work with the tuple of six values as in the question, it's defined in this part of the CSS standard.

后一种方法的好处是你也得到一个 4x4 矩阵,这是仿射变换的标准表示,缺点是它当然是 WebKit 特定的。如果您继续使用问题中的六个值的元组,它在 CSS 标准的这一部分中定义。

Then the transform, e.g. rotation needs to be reverse engineered. There can be many simple transforms directly supported by CSS, e.g. translate, scale, rotate, skew, and perspective. If only one of them is applied, then you just need to revert the process of computing the transform matrix.

然后需要对变换(例如旋转)进行逆向工程。CSS 可以直接支持许多简单的变换,例如平移、缩放、旋转、倾斜和透视。如果只应用其中之一,那么您只需要还原计算变换矩阵的过程。

An alternative is to find or translate code which does this for you in JS, e.g. the same documentor Section 7.1 of the CSS standardcontains such annotated algorithms. The benefit is that the unmatrixapproach is able to, with some limitations, return the 'atomic' transforms even if more than one of these (translate, rotate etc.) is applied. Since it's not possible to guarantee the successful reverse engineering of the transform steps for the general case, it's useful to think about what types of transforms are possibly applied, and whether degenerate or other troublesome cases have been avoided. I.e. you need to build the solution as you see fit for your problem.

另一种方法是在 JS 中查找或翻译为您执行此操作的代码,例如,相同的文档CSS 标准的第 7.1 节包含此类带注释的算法。好处是unmatrix方法能够在有一些限制的情况下返回“原子”变换,即使应用了多个(平移、旋转等)。由于无法保证一般情况下转换步骤的逆向工程成功,因此考虑可能应用哪些类型的转换以及是否避免了退化或其他麻烦的情况是很有用的。即您需要构建您认为适合您的问题的解决方案。

Specifically, the matrix versions of all 2D CSS transforms are documented here as well, below the meaning of the six values in the CSS 2D transform vector.

具体来说,所有 2D CSS 变换的矩阵版本也记录在此处,低于 CSS 2D 变换向量中六个值的含义。

Another caveat is that there are other things that influence the visual outcome in terms of geometric operations, for example, transform-origin.

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

回答by donohoe

This link from Apple Dev Referencemight shed more light on the subject:

来自 Apple Dev Reference 的这个链接可能会更清楚地说明这个问题:

The webkitTransform property is a string representation of a list of transform operations. Usually this list contains a single matrix transform operation. For 3D transforms, the value is "matrix3d(...)" with the 16 values of the 4x4 homogeneous matrix between the parentheses. For 2D transforms, the value is a "matrix(...)" string containing the 6 vector values.

webkitTransform 属性是转换操作列表的字符串表示形式。通常这个列表包含一个矩阵变换操作。对于 3D 变换,该值为“matrix3d(...)”,括号之间为 4x4 齐次矩阵的 16 个值。对于 2D 变换,该值是包含 6 个向量值的“matrix(...)”字符串。

回答by syockit

Since you only get the final matrix value from the computed style, you might have to check the element's inline style or stylesheet rules. If element.style.webkitTransformgives you nothing, you might to iterate through the document's stylesheets, and see which one matches your element. Then you can regex the webkitTransformproperty to get/set the value.

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

回答by user2044802

you can use regex to get a map of property-value:

您可以使用正则表达式来获取属性值的映射:

if variable transformstyle contains the style value

如果变量 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},{})

for:

为了:

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

you would get:

你会得到:

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

回答by user2044802

Just because I didn′t see any working Javascript one Line solutions to convert the matrix code, here is mine. Quick and easy:

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

First get all the transform Values in a matrix:

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

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

To extract transform-y as an Integer:

将 transform-y 提取为整数:

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

To extract transform-x as an Integer:

将 transform-x 提取为整数:

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

Accessing the rotation value is quite difficult, but there is a good guide, if you want to do it: https://css-tricks.com/get-value-of-css-rotation-through-javascript/

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

回答by kalyanji

I thought of one possibility. If you're prepared to parse strings in JavaScript, use

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

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

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

then interpret data.

然后解释data

回答by vsync

Easy way to extract individual values from a complex transform value:

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

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);