Как читать отдельные значения преобразования в JavaScript? - PullRequest
16 голосов
/ 08 августа 2010

В блоге Webkit с прошлого года 3D-преобразования объясняются различные «функции» преобразования, которые можно использовать в свойстве -webkit-transform.Например:

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

Мой вопрос: как вы получаете доступ к отдельным значениям в JavaScript?Когда вы читаете свойство webkitTransform элемента, вы просто получаете функцию matrix3d ​​() с 16 значениями в ней, например так:преобразовать вещь, как rotateY ()?Или я должен прочитать его из строки matrix3d ​​() и как?

Ответы [ 10 ]

13 голосов
/ 28 ноября 2012
// 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*/);
}

Надеюсь, это поможет!Обратите внимание, что я не использовал другую библиотеку, кроме простого API DOM и встроенной функции Javascript RegExp.Следовательно, это должно работать универсально для разных браузеров и приложений.

3 голосов
/ 24 мая 2015

Старый, но интересный вопрос и ни один предыдущий ответ не пытался ответить на него.

К сожалению, для общего случая не существует двухслойного решения, и мы не знаем о том, какое разнообразие шагов преобразования (поворот, преобразование и т. Д.) Необходимо реверсировать;чем меньше, тем проще.

В последних браузерах на основе 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);

Но другой способ - просто использовать это, которое не упоминалосьbefore:

var cssMatrix = new WebKitCSSMatrix(matrixString);

Преимущество последнего подхода состоит в том, что вы также получаете матрицу 4x4, которая является стандартным представлением для аффинных преобразований , и недостатком является то, чтоКонечно, WebKit специфичен.Если вы продолжите работать с кортежем из шести значений, как в вопросе, это определено в этой части стандарта CSS .

Затем преобразование, например вращение, должно быть выполнено в обратном порядке.Может быть много простых преобразований, непосредственно поддерживаемых CSS, например, перевод, масштабирование, поворот, наклон и перспектива.Если применяется только один из них, то вам просто нужно отменить процесс вычисления матрицы преобразования .

Альтернативой является поиск или перевод кода, который делает это за вас в JS, например, тот же документ или Раздел 7.1 стандарта CSS содержит такие аннотированные алгоритмы.Преимущество состоит в том, что подход unmatrix может с некоторыми ограничениями возвращать «атомные» преобразования, даже если применяется более одного из них (перевод, вращение и т. Д.).Поскольку невозможно гарантировать успешное обратное проектирование шагов преобразования для общего случая, полезно подумать о том, какие типы преобразований возможно применяются, и были ли предотвращены вырожденные или другие проблемные случаи.Т.е. вам нужно построить решение так, как вы считаете нужным для вашей проблемы.

В частности, матричные версии всех 2D CSS-преобразований задокументированы и здесь , ниже значения шести значений.в векторе 2D-преобразования CSS.

Еще одно предостережение заключается в том, что существуют другие вещи, которые влияют на визуальный результат с точки зрения геометрических операций, например, transform-origin .

3 голосов
/ 23 января 2012

Я столкнулся с этим вопросом сегодня утром.Похоже, что JavaScript не может прочитать свойство style.webkitTransform элемента, пока оно не будет явно задано в атрибуте style элемента (либо встроенного в HTML, либо процедурно через JavaScript).Как это ни круто звучит, если вам нужно, чтобы JS мог читать свойства CSS-преобразования, вам лучше определить их начальные значения с помощью JavaScript, когда DOM будет готов.

Пример с использованием jQuery:

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

С этого момента вы сможете читать строку преобразования элемента и анализировать ее на предмет необходимых значений.

3 голосов
/ 09 августа 2010

Я думаю, что, как говорит 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 голосов
/ 08 августа 2010

Эта ссылка от Apple Dev Reference может пролить больше света на тему:

Свойство webkitTransform является строковое представление списка трансформировать операции. Обычно это список содержит одну матрицу преобразовать операцию. Для 3D преобразования, значение "matrix3d ​​(...)" с 16 значениями однородная матрица 4x4 между скобки. Для 2D-преобразований значение является строкой "matrix (...)" содержащий 6 векторных значений.

1 голос
/ 13 апреля 2015

Только потому, что я не видел ни одного работающего решения 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-стоимость из-Css-Rotation-через-JavaScript /

1 голос
/ 08 декабря 2013

Вы можете использовать регулярное выражение, чтобы получить карту значения свойства:

, если переменная 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"}
1 голос
/ 08 августа 2010

Поскольку вы получаете только окончательное значение матрицы из вычисленного стиля, вам, возможно, придется проверить встроенный стиль элемента или правила таблицы стилей.Если element.style.webkitTransform ничего не дает, вы можете перебрать таблицы стилей документа и посмотреть, какой из них соответствует вашему элементу.Затем вы можете пересмотреть свойство webkitTransform, чтобы получить / установить значение.

0 голосов
/ 16 июля 2016

Простой способ извлечь отдельные значения из комплексного значения преобразования:

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);
0 голосов
/ 08 августа 2010

Я думал об одной возможности.Если вы готовы анализировать строки в JavaScript, используйте

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

, а затем интерпретируйте data.

...