- PVSM.RU - https://www.pvsm.ru -
Когда погружаешься в документацию [1] о CSS3 transform: matrix3d, находишь короткое определение «Задает 3D трансформацию как матрицу 4х4.», сопровождаемое определением функции в виде:
matrix3d(m00, m01, m02, m03,
m10, m11, m12, m13,
m20, m21, m22, m23,
m30, m31, m31, m33)
И если не являешься Богом математики, скорее всего, внутри возникает беспокойство о недостатке документации, за которым следует вопрос, как создать по-настоящему крутую штуку? Описанный подход не претендует называться математическим или полным — я всего лишь пытаюсь заполнить маленькую брешь документации.
демо [2] | первоисточник [3]
Всякая комплексная трансформация может быть представленна тремя базовыми:
Поворот (rotate)
Масштабирование (scale)
Перемещение (translate)
Эти 3 базовых преобразования могут быть совмещены в одну огромную всеобъемлющую матрицу трансформации. Пока все просто, но как перейти от 3 базовых этапов к тому необузданному списку параметров, который нужен для matrix3d? Давайте начнем с самой простой матрицы в математике (чтобы упростить себе жизнь я использую Sylvester [4] для математических операций с матрицами).
Эта матрица не делает ничего! Nil! Null! Nada! Ни один пиксель не пострадал! Я разделил эту матрицу на 2 секции. Красная секция это область где описываются Поворот (Rotate) и Масштабирование (Scale). В желтой секции описывается cдвиг или перемещение (translate). Остальные параметры используются очень редко, за исключением понастоящему странных FX демок в LSD стиле.
Мы начнем созданием матрицы масштабирования, умножив единичную матрицу на коэффициент масштабирования.
scaleMatrix = indentityMatrix.multiply(s)
scaleMatrix = $M([
[s,0,0,0],
[0,s,0,0],
[0,0,s,0],
[0,0,0,s]
])
Так как мы не хотим трансформировать координаты перемещения (translate), давайте заменим последний параметр масштабирования на 1:
scaleMatrix = $M([
[s,0,0,0],
[0,s,0,0],
[0,0,s,0],
[0,0,0,1]
])
Поворот может осуществлятся вокруг оси X, Y, Z, давайте примем значение углов поворота как a, b, c. Соотвествующие матрицы, представляющие такую трансформацию:
rotationXMatrix = $M([
[1,0,0,0],
[0,Math.cos(a), Math.sin(-a), 0],
[0,Math.sin(a), Math.cos( a), 0],
[0,0,0,1]
])
rotationYMatrix = $M([
[Math.cos( b), 0, Math.sin(b),0],
[0,1,0,0],
[Math.sin(-b), 0, Math.cos(b), 0],
[0,0,0,1]
])
rotationZMatrix = $M([
[Math.cos( c), Math.sin(-c), 0, 0],
[Math.sin( c), Math.cos( c), 0, 0],
[0,0,1,0],
[0,0,0,1]
])
Каждая матрица описывает поворот вокруг одной оси.
translationMatrix = $M([
[1,0,0,0],
[0,1,0,0],
[0,0,1,0],
[tx,ty,tz,1]
])
Матрица перемещения не затрагивает большенство пикселей, но добавляет значения tx, ty и tz к результирующему вектору направления.
Да, математика может быть развлечением, а каждая из этих матриц может быть использованна в композиции. Итак, если нужно повернуть что-нибудь вокруг каждой оси и потом переместить это на несколько пикселей, просто перемножте эти матрицы. Вот и все:
tM = rotationXMatrix
.x(rotationYMatrix)
.x(rotationZMatrix)
.x(scaleMatrix)
.x(translationMatrix)
И в конце применим трансформацию к изображению:
s = «matrix3d(»
s += tM.e(1,1).toFixed(10) + "," + tM.e(1,2).toFixed(10) + "," + tM.e(1,3).toFixed(10) + "," + tM.e(1,4).toFixed(10) + ","
s += tM.e(2,1).toFixed(10) + "," + tM.e(2,2).toFixed(10) + "," + tM.e(2,3).toFixed(10) + "," + tM.e(2,4).toFixed(10) + ","
s += tM.e(3,1).toFixed(10) + "," + tM.e(3,2).toFixed(10) + "," + tM.e(3,3).toFixed(10) + "," + tM.e(3,4).toFixed(10) + ","
s += tM.e(4,1).toFixed(10) + "," + tM.e(4,2).toFixed(10) + "," + tM.e(4,3).toFixed(10) + "," + tM.e(4,4).toFixed(10)
s += ")"
document.getElementById('darth-vader').style['-webkit-transform'] = s
Первое — если погуглить линейную трансформацию и найти примеры таких матриц, можно удивится что матрицы немного отличаются. Дело в том, что CSS матрица транспонированная — вот так просто, выполните транспонирование матрицы и она должна работать.
Второе — CSS не поддерживает научную форму числа (например 123е-15) в качестве параметров — поэтому нужно использовать toFixed(numberOfDigits) чтобы нормализовать их.
Демо работает только в -webkit- браузерах, таких как Chrome или Safari. Исходный код написанн на coffeescript [5] который немного круче javascript — но скомплилированный код должен быть читабельным. Вы можете забрать весь урок и исходники на github [6].
Демо [2]
Оригинал статьи [3]
Facebook автора [7]
Twitter автора [8]
Потрясающая Javascript библиотека Sylvester [4]
Статья о линейных трансформациях на Wikipedia [9]
Автор: LegoMushroom
Источник [10]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/css3/25475
Ссылки в тексте:
[1] в документацию: http://dev.w3.org/csswg/css3-3d-transforms/#transform-property
[2] демо: http://codepen.io/sol0mka/pen/AobkI
[3] первоисточник: http://9elements.com/html5demos/matrix3d/
[4] Sylvester: http://sylvester.jcoglan.com/
[5] coffeescript : http://coffeescript.org/
[6] github: https://github.com/9elements/Matrix3d-Tutorial
[7] Facebook автора: http://www.facebook.com/9elements
[8] Twitter автора: https://twitter.com/9elements
[9] Статья о линейных трансформациях на Wikipedia: http://en.wikipedia.org/wiki/Linear_transformation#Examples_of_linear_transformation_matrices
[10] Источник: http://habrahabr.ru/post/166751/
Нажмите здесь для печати.