Как смешивать свойства преобразования css3 без переопределения (в режиме реального времени)?
Есть ли способ скомбинировать (смешивать) свойства преобразования CSS без переопределения? Например, я хочу повернуть и масштабировать.
http://jsfiddle.net/hyzhak/bmyN3/
HTML
<div class="item rotate-90 tiny-size">
Hello World!
</div>
CSS
.rotate-90 {
-webkit-transform: rotate(90deg);
}
.tiny-size {
-webkit-transform: scale(0.25, 0.25);
}
PS
У меня просто много элементов и множество простых классов для преобразования вида элементов. И я просто хочу настроить их просмотр, добавив и удалив некоторые классы. Сочетание всех классов не работает, потому что это будет сотни комбинаций.
Также я хочу сделать это в реальном времени.
Число преобразований может быть приблизительно 5, и каждый из них может содержать около 10 состояний - так что просто опишите все их комбинации руками, дайте приблизительно
10*10*10*10*10 = 100000 cases
Это плохое решение.
Ответы
Ответ 1
Здесь попытка решить проблему с Javascript: http://jsfiddle.net/eGDP7/
Я использую атрибут data в html для перечисления классов с преобразованиями, которые мы хотим применить:
<div class="compoundtransform" data-transformations="scaletrans2, rotatetrans1">Test subject</div>
Я повторяю классы и узнаю, какие правила они представляют:
function getCSSRulesForClass( selector ) {
var sheets = document.styleSheets;
var cssRules = [];
for (var i = 0; i<sheets.length; ++i) {
var sheet = sheets[i];
if( !sheet.cssRules ) { continue; }
for (var j = 0; j < sheet.cssRules.length; ++j ) {
var rule = sheet.cssRules[j];
if (rule.selectorText && rule.selectorText.split(',').indexOf(selector) !== -1) {
var styles = rule.style;
for( var k = 0; k<styles.length; ++k ) {
var style = styles[k];
cssRules.push( {
property: style,
value: styles[style]
} );
}
}
}
}
return cssRules;
}
Я нахожу любые преобразования и применяю преобразования к матрице:
function convertTransformToMatrix( source, transformValue ) {
var values = transformValue.split(") "); // split into array if multiple values
var matrix = cloneObject( source );
for ( var i = 0; i<values.length; ++i ) {
var value = values[i];
if( isRotate( value ) ) {
var rotationValue = cssRotationToRadians( value );
var cosValue = Math.cos( rotationValue );
var sinValue = Math.sin( rotationValue );
var a = matrix.a;
var b = matrix.b;
var c = matrix.c;
var d = matrix.d;
var tx = matrix.tx;
var ty = matrix.ty;
matrix.a = a*cosValue - b*sinValue;
matrix.b = a*sinValue + b*cosValue;
matrix.c = c*cosValue - d*sinValue;
matrix.d = c*sinValue + d*cosValue;
matrix.tx = tx*cosValue - ty*sinValue;
matrix.ty = tx*sinValue + ty*cosValue;
} else if ( isScale( value ) ) {
var scale = cssScaleToObject( value );
matrix.a *= scale.x;
matrix.b *= scale.y;
matrix.c *= scale.x;
matrix.d *= scale.y;
matrix.tx *= scale.x;
matrix.ty *= scale.y;
} else if ( isTranslate( value ) ) {
var translate = cssTranslateToObject( value );
matrix.tx += translate.x;
matrix.ty += translate.y;
}
}
return matrix;
}
И, наконец, применим эту матрицу к node как к преобразованию.
В настоящее время
- Код немного грязный
- Разбор CSS ограничен масштабом (x, y), translate (x, y) и вращается со значениями степени или радиана
- И он будет работать только с префиксом поставщика webkit
Я мог бы привести его в порядок и превратить в полезную утилиту, если она будет полезной для всех.
Ответ 2
Хм... насколько я знаю, вам нужно было бы создать новый класс и объединить их таким образом (разделенный пробелом):
-webkit-transform: rotate(90deg) scale(0.25, 0.25);
Ответ 3
Как мне обойти эту проблему, нужно добавить класс оболочки вокруг той, которую я хочу. Например, у меня есть оболочка, которая имеет свою позицию, установленную через javascript, а затем внутренняя, на которую влияет анимация css - как на свойство transform.
Я знаю, что добавление узлов DOM не является идеальным, но оно обходит решение script -havy и позволяет браузеру оптимизировать анимации и переходы, как обычно.
Ответ 4
В настоящее время нет способа сделать это, он принимает только одну команду для transform
за раз и не может добавлять или вычитать, как вам хотелось бы. Таким образом, вам придется добавлять или удалять класс в зависимости от того, что является первым и вторым типом, и написать пользовательский transform
для этого элемента
Использование языка препроцессора CSS, такого как SASS или LESS, облегчает объединение переходов, следующее позволяет объединить любое число transition
в один, но требует, чтобы было сказано, какие из них добавить (это SCSS)
.item {
width:500px;
height:500px;
font-size:150px;
background:blue;
}
$firstTransform: rotate(90deg);
$secondTransform: scale(0.25, 0.25);
@mixin transform($transform...) {
-webkit-transform: $transform;
-moz-transform: $transform;
-ms-transform: $transform;
-o-transform: $transform;
transform: $transform;
}
.rotate-90 {
@include transform($firstTransform);
}
.tiny-size {
@include transform($secondTransform);
}
.both {
@include transform($firstTransform $secondTransform);
}
Демо
Действительно, единственным способом сделать это в настоящее время будет использование javascript, по существу добавляющий класс с преобразованием, сохраняющий переменную этого класса, преобразует, удаляет класс и делает то же самое с другим классом, а затем объединяет две матрицы преобразований класса. РЕДАКТИРОВАТЬ: Подробнее об этом подходе см. ответ на javascript.
Ответ 5
Вместо поворота и масштабирования вы можете использовать матричную функцию.
transform: matrix(a, b, c, d, tx, ty);
В приведенном примере я считаю, что следующее приведет к желаемому результату:
transform: matrix(0,-0.25,0.25,0,0,0);
Для объяснения матричных расчетов:
И некоторые полезные инструменты существуют для вычисления этих матриц как CSS, например:
Ответ 6
Одна вещь, которую вы могли бы сделать, это получить стиль вычисленного преобразования в JS и объединить значение вторичного преобразования:
HTML
<div class="rotate-scale"></div>
CSS
.rotate-scale {
transform: rotate(90deg);
}
JS
var el = document.querySelector('.rotate-scale'),
// rotation will get the transform value declared in css
rotation = window.getComputedStyle(el).getPropertyValue('transform');
el.style.transform = rotation + 'scale(0.25, 0.25)';