Как читать отдельные значения преобразования в JavaScript?

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

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

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

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

Есть ли способ просто прочитать значение отдельной вещи преобразования, например rotateY()? Или мне нужно прочитать его из строки matrix3d ​​() и как?

Ответы

Ответ 1

// 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 JavaScript. Следовательно, это должно работать с универсальными браузерами и приложениями.

Ответ 2

Я думаю, как говорит 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>

Ответ 3

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

Пример, используя jQuery:

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

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

Ответ 4

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

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

В последних браузерах на основе 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, которая является стандартным представлением для аффинных преобразований, и Недостатком является то, что он, конечно, специфичен для WebKit. Если вы продолжаете работать с кортежем из шести значений, как в вопросе, он определяет в этой части стандарта CSS.

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

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

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

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

Просто потому, что я не видел никаких рабочих решений 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

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

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

затем интерпретировать data.

Ответ 9

вы можете использовать regex для получения карты значения свойства:

если переменная 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"}

Ответ 10

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

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