написать впереди
Фреймворк Омиофициально выпущен→ оми-преобразование.
Made css3 transform super easy. Made 60 FPS easy.
Являясь решением Omi для разработки специальных эффектов движения на основе компонентов, оно позволяет быстро и легко поддерживать настройки CSS3 Transform в проектах Omi. css3transform был крещен большим количеством проектов.Как решение для мобильных веб-спецэффектов, он широко используется в WeChat, мобильном племени интересов QQ, Riji, группе QQ, районе QQ и других проектах.ИсправлятьЗа счет свойств DOM это обеспечивает чрезвычайно удобную программируемость.
ты можешь пройтиcss3transform официальная домашняя страницаПознакомьтесь с ним быстро.
Все примеры на официальном сайте выше — это нативный js, а у css3transform также есть версия для реакции Вы также можете использовать css3transform декларативным образом в реакции:
render() {
return (
<Transform
translateX={100}
scaleX={0.5}
originX={0.5}>
<div>你要运动的 DOM</div>
</Transform>
)
}
Суть не в этом, а в оми-трансформации.
Освойте оми-трансформацию за 3 минуты
Установить через нпм
npm install omi-transform
использовать
import { render, WeElement, define } from "omi"
import "omi-transform"
define("my-app", class extends WeElement {
static observe = true
install() {
this.data.rotateZ = 30
this.linkRef = (e) => {
this.animDiv = e
}
}
installed() {
setInterval(() => {
//slow
//this.data.rotateZ += 2
//fast
this.animDiv.rotateZ += 2
//sync for update call of any scenario
this.data.rotateZ = this.animDiv.rotateZ
}, 16)
}
render(props, data) {
return (
<css3-transform rotateZ={data.rotateZ} translateX={0} perspective={0} >
<div ref={this.linkRef}>
omi-transform
</div>
</css3-transform>
)
}
})
render(<my-app />, "body")
- Используйте DOM, который нужно переместить
<css3-transform></css3-transform>
пакет - Разметка в DOM, которая должна использовать css3transform
ref
Используется для прямого управления DOM - В функции компонента вы можете использовать this.refs.animDiv для чтения или установки свойства преобразования css.
- this.refs.xxxПоддерживает "translateX", "translateY", "translateZ", "scaleX", "scaleY", "scaleZ", "rotateX", "rotateY", "rotateZ", "skewX", "skewY", "originX", " originY", "originZ", "perspective" эти свойства устанавливаются и считываются
- перспектива представляет собой расстояние перспективной проекции
DOM в компоненте может обновляться из-за другой логики в процессе перемещения. Это может быть взаимодействие с пользователем или обратный вызов для возврата данных. Поэтому особенно важно сохранить состояние DOM до и после обновления, иначе возникнут мерцания, скачки или другие логические ошибки отображения.
Вы видите, что приведенный выше код не различается, пока DOM находится в движении? Компоненты не обновляются? Если компонент обновится, состояние всех перемещений потеряется? Как Оми решает эту проблему? Приведенный выше код уже дает ответ:
использовать
this.data.rotateZ
для синхронизации состояния движущегося DOM для предотвращения случайных обновлений (update
)
Поддерживаемые свойства
Property | Describe |
---|---|
translateX | translateX |
translateY | translateY |
translateZ | translateZ |
scaleX | scaleX |
scaleY | scaleY |
scaleZ | scaleZ |
rotateX | rotateX |
rotateY | rotateY |
rotateZ | rotateZ |
skewX | skewX |
skewY | skewY |
originX | the basic x point of rotation |
originY | the basic y point of rotation |
originZ | the basic z point of rotation |
perspective | Perspective projection distance |
Вы можете получить или установить.
Сравнение производительности
Поскольку версия реакции будет иметь процесс сравнения, а затем процесс применения различия к dom, изменение состояния не заменит весь innerHTML, поэтому он по-прежнему очень дешев для рендеринга браузера, но процесс сравнения в js занимает много времени. все равно нужно зайти в profiles One, если это занимает много времени, если не запускать в вебворкере, то все равно будет зависать в потоке UI, что приведет к лагу, лагу анимации, потере кадров, задержке взаимодействия, и т.п. Поэтому необходимо взглянуть на потребление времени ЦП.
Следующие данные представляют собой сравнение omi-transform и react-transform с использованием профилей Chrome двумя способами.
Сначала посмотрите на общее сравнение времени:
реагировать-преобразование:
оми-преобразование:
- React потратил примерно 8739 секунд на процессорное время.1686ms
- Режим Omi занимает примерно 9254 мс процессорного времени в секундах.700ms
Без профилей вы можете себе представить, что реакция будет медленнее, потому что изменение состояния должно пройти жизненный цикл реакции, но вы можете видеть, что время реакции все еще находится в приемлемом диапазоне, не слишком медленное, чтобы быть неприемлемый.
Метод Omi точно такой же, как и традиционный нативный js. Поскольку процесс перемещения не выполняет DOM Diff, непосредственно управляйте DOM!!
Оми самосравнение
//slow
this.data.rotateZ += 2
//fast
this.animDiv.rotateZ += 2
this.data.rotateZ = this.animDiv.rotateZ
В основном сравните эффективность выполнения двух вышеуказанных блоков кода, откройте производительность Google Chrome, чтобы запустить ее примерно на 10 секунд, и откройте сводное сравнение:
Slow | Fast |
---|---|
Видно, что оба метода omi имеют высокую производительность и много времени простоя в пределах 10 секунд, но fast действительно быстрее и скриптинг занимает меньше времени. Но почему преимущество неочевидно? Поскольку структура DOM проста, если структура DOM более сложна, быстрый способ прямого манипулирования DOM отбросит большую часть медленного способа! Проверьте это ниже:
Структура DOM первого рендера изменена, чтобы быть сложной:
Откройте производительность Google Chrome, чтобы запустить его примерно на 10 секунд, и откройте сводное сравнение:
Slow | Fast |
---|---|
Вы можете видеть, что Scripting Time открыл брешь!
Сравните данные до и после:
DOM-структура | Slow | Fast |
---|---|---|
Простой | ||
сложный |
Видно, что между двумя временами быстрого и двумя временами медленного нет большой разницы. Так в чем же принцип Fast kernel css3transform?
css3transform
Установить
npm install css3transform
API
Transform(domElement, [notPerspective])
Вызвав приведенную выше строку кода, вы можете установить или прочитать «translateX», «translateY», «translateZ», «scaleX», «scaleY», «scaleZ», «rotateX», «rotateY», «rotateZ» элемента domElement. , "skewX", "skewY", "originX", "originY", "originZ"!
Дорога к простоте.
использовать позу
Transform(domElement)//or Transform(domElement, true);
//set
domElement.translateX = 100
domElement.scaleX = 0.5
domElement.originX = 50
//get
console.log(domElement.translateX)
Проблемы с традиционным программированием на CSS3
В прошлом мы обычно использовали animate.css, метод анимации zepto/jQuery или tween.js+css3 для программирования интерактивных спецэффектов. Подводя итог, можно выделить три недостатка:
- Не интуитивный
- косвенный
- неудобно
Не интуитивный
Посмотрите на картинку ниже:
Результаты эффекта порядка, не интуитивно понятны. Так почему этот результат? Окончательная матрица может быть коррелирована новой WebKitcssmatrix (Transform_str).
Это также прямо показывает, что матрица не подчиняется закону перестановочности.A*B != B*A
косвенный
цепто поза:
$("#some_element").animate({
opacity: 0.25, left: '50px',
color: '#abcdef',
rotateZ: '45deg', translate3d: '0,10px,0'
}, 500, 'ease-out')
translate3d: '0,10px,0' очень неудобно и не может управляться поэтапно. Не говоря уже о программировании с некоторыми библиотеками движения или времени. Может быть, вы возразите, что «облегчение» не может обеспечить смягчение? Но если мне нужно, чтобы x, y и z соответствовали разным функциям плавности, эта форма строкового программирования будет трудоемкой~~ Здесь также важно отметить, что порядок в zepto также влияет на результат. Потому что он также пишется как строка и назначается элементу dom.
поза tween.js
var position = { x: 100, y: 100, rotation: 0 },
target = document.getElementById('target')
new TWEEN.Tween(position)
.to({ x: 700, y: 200, rotation: 359 }, 2000)
.delay(1000)
.easing(TWEEN.Easing.Elastic.InOut)
.onUpdate(function update() {
var t_str= 'translateX(' + position.x + 'px) translateY(' + position.y + 'px) rotate(' + Math.floor(position.rotation) + 'deg)'
element.style.transform = element.style.msTransform = element.style.OTransform = element.style.MozTransform = element.style.webkitTransform = t_str
});
Способ использования строк утомительно смотреть. Не говоря уже о том, насколько мучительным является процесс написания.
animate.css поза:
@keyframes pulse {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
animate.css инкапсулирует множество анимаций по ключевым кадрам, и разработчикам нужно заботиться только о добавлении или удалении связанных классов анимации. В какой-то степени это обеспечивает отличный переход к интерактивным эффектам, но есть и недостатки:
- Программируемость недостаточно высока
- Подходит для простых сценариев
- Только
end
обратный звонок, нетchange
Перезвоните
неудобно
Опорная точка точки вращения при преобразовании по умолчанию находится в центре, но иногда система находится не в центре.Наш традиционный подход состоит в том, чтобы использовать преобразование-происхождение для установки опорной точки.
Обратите внимание, что это еще одно свойство transform-origin, а не transform. Но что, если требуется источник преобразования движения? Эта конструкция устарела? Существуют ли какие-либо сценарии, требующие источника движения? Это часто используется в геймдизайне, об этом позже будет сказано отдельно, дело в том, что есть сцены, в которых нужно переместить начало координат для достижения определенного эффекта.
резюме
Исходя из вышеперечисленных неудобств, есть css3transform!
- css3transform Сверхлегкая js-библиотека, ориентированная на чтение и настройку преобразований CSS3, значительно улучшающая программируемость преобразований CSS3.
- css3transform очень абстрактен и не привязан к какой-либо структуре времени и движения, поэтому его можно легко использовать с любой средой времени и движения.
- css3transform использует matrix3d в качестве конечного вывода для объекта dom, аппаратное ускорение без потери программируемости
- css3transform имеет очень простой в использовании API, простой в использовании за одну минуту и встроенный в реальные проекты за две минуты.
- css3transform расширяет возможности самого преобразования, делая его происхождение более удобным.
настоящий бой
Вы можете легко создать описанный выше эффект качания с помощью tweenjs createjs:
var element = document.querySelector("#test")
Transform(element)
element.originY = 100
element.skewX = -20
var Tween = createjs.Tween,
sineInOutEase = createjs.Ease.sineInOut
Tween.get(element, {loop: true}).to({scaleY: .8}, 450, sineInOutEase).to({scaleY: 1}, 450, sineInOutEase)
Tween.get(element, {loop: true}).to({skewX: 20}, 900, sineInOutEase).to({skewX: -20}, 900, sineInOutEase)
Приведенный выше код очень компактен. Вот небольшое пояснение:
- Начальный skewX элемента равен -20, чтобы не отставать от масштаба.
- элемент originY 100, в нижний центр в качестве ориентира для пингвина
Как видите, потому что CSS3Transform сильно абстрактна, его можно легко использовать с TweenJS без какого-либо давления.
принцип
css3transform может не только смешивать преобразования CSS3 с элементами DOM, но и любыми объектными литералами.Вы также можете использовать css3transform как инструмент, который предоставляет некоторые базовые математические возможности.
Здесь нужно особое внимание, можно продолжать использовать предыдущие позы, а вот еще три использованные позы.
Грамматика 1
Transform(obj, [notPerspective]);
Как видите, больше ничего не меняется. Просто первый параметр может передавать не только элементы DOM, но и любые литералы объектов и т.д.
Не продавайте, сначала посмотрите на позу использования
var element = document.querySelector("#test"),
obj = {}
Transform(obj)
obj.rotateZ = 90
element.style.transform = element.style.msTransform = element.style.OTransform = element.style.MozTransform = element.style.webkitTransform = obj.transform
Видите ли, вы можете передавать не только элементы DOM, но и литералы объектов. Вы можете распечатать obj.transform, выше выбрано 90 градусов, поэтому генерируемая матрица:
perspective(500px) matrix3d(0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1)
Вы также можете отключить перспективную проекцию, например:
var element = document.querySelector("#test"),
obj = {}
//关闭透视投影
Transform(obj, true)
obj.rotateZ = 90
element.style.transform = element.style.msTransform = element.style.OTransform = element.style.MozTransform = element.style.webkitTransform = obj.transform
Результирующая матрица:
matrix3d(0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1)
Так что насчет позы движения? совпадение здесьtween.jsПример выглядит следующим образом:
var element = document.querySelector("#test"),
obj = { translateX: 0, translateY: 0 }
Transform(obj);
var tween = new TWEEN.Tween(obj)
.to({ translateX: 100, translateY: 100 }, 1000)
.onUpdate(function () {
element.style.transform = element.style.msTransform = element.style.OTransform = element.style.MozTransform = element.style.webkitTransform = obj.transform
})
.start()
requestAnimationFrame(animate)
function animate(time) {
requestAnimationFrame(animate)
TWEEN.update(time)
}
А что, если использовать традиционную позу?
var element = document.querySelector("#test")
Transform(element)
var tween = new TWEEN.Tween({ translateX: element.translateX, translateY: element.translateY })
.to({ translateX: 100, translateY: 100 }, 1000)
.onUpdate(function () {
element.translateX = this.translateX
element.translateY = this.translateY
})
.start()
requestAnimationFrame(animate)
function animate(time) {
requestAnimationFrame(animate)
TWEEN.update(time)
}
Здесь, потому что TWEEN.Tween будет проходить по всем свойствам и устанавливать начальные значения, такие как код в tween:
// Set all starting values present on the target object
for (var field in object) {
_valuesStart[field] = parseFloat(object[field], 10)
}
Таким образом, вы не можете напрямую поместить новый TWEEN.Tween(element). Потому что перед запуском программа действительно может полностью собрать все необходимые атрибуты, и этого достаточно для тренировки. Мы можем сами обернуть анимацию, чтобы поддержать этот простой способ. Такие как:
var Tween = function (obj) {
this.obj = obj
return this
}
Tween.prototype = {
to: function (targets, duration, easing) {
this.duration = duration
this.targets = targets
return this
},
start: function () {
this.startTime = new Date()
this._beginTick()
},
_beginTick: function () {
var _startValues = {},
targets = this.targets
for (var key in targets) {
if (targets.hasOwnProperty(key)) {
_startValues[key] = this.obj[key]
}
}
var self = this
this._interval = setInterval(function () {
var dt = new Date() - self.startTime
for (var key in targets) {
if (targets.hasOwnProperty(key)) {
if (dt >= self.duration) {
clearInterval(self._interval)
} else {
var p = dt / self.duration;
var dv = targets[key] - self.obj[key]
self.obj[key] += dv * p
}
}
}
}, 15)
}
}
Здесь, чтобы упростить использование setInterval в цикле, конечно, его можно заменить другими методами. Теперь вы можете использовать его так:
var element = document.querySelector("#test")
Transform(element)
var tween = new Tween(element)
.to({ translateX: 100, translateY: 100 }, 1000)
.start();
Конечно это немного не по теме. Это просто сравнение разницы между прямым монтированием DOM и монтированием сторонних объектов. Сторонние маунты чем-то напоминают боевой скот. Конечно.., это еще не конец, не то что выше. Это также может полностью использовать css3transform как вычислительный инструмент.
Грамматика 2
Transform.getMatrix3D(option)
поза
var matrix3d = Transform.getMatrix3D({
translateX: 0,
translateY: 100,
scaleX:2
})
console.log(matrix3d)
Распечатав его, вы получите следующие значения:
Делайте что хотите с этим значением. Глядя на исходный код css3transform, вы можете получить свойства, поддерживаемые Transform.getMatrix3D:
Transform.getMatrix3D = function (option) {
var defaultOption = {
translateX: 0,
translateY: 0,
translateZ: 0,
rotateX: 0,
rotateY: 0,
rotateZ: 0,
skewX: 0,
skewY: 0,
originX: 0,
originY: 0,
originZ: 0,
scaleX: 1,
scaleY: 1,
scaleZ: 1
};
for (var key in option) {
...
...
...
}
Грамматика 3
Transform.getMatrix2D(option)
Не только 3D-матрица, css3transform также обеспечивает поддержку служебных функций 2D.
поза
var matrix2d = Transform.getMatrix2D({
translateX: 0,
translateY: 100,
scaleX:2
});
console.log(matrix2d);
Распечатав его, вы получите следующие значения:
- Горизонтальный зум
- B Горизонтальный рисунок
- c Вертикальное растяжение
- г Вертикальное масштабирование
- TX горизонтальное смещение
- вертикальное смещение
Итак, какой смысл в получении этого Matrix2D?
- Масштаб: масштаб (sx, sy) эквивалентен матрице (sx, 0, 0, sy, 0, 0);
- Перевод: translate(tx, ty) эквивалентен matrix(1, 0, 0, 1, tx, ty);
- Вращение: rotate(deg) эквивалентно matrix(cos(deg), sin(deg), -sin(deg), cos(deg), 0, 0);
- Растяжение: skew(degx, degy) эквивалентно matrix(1, tan(degy), tan(degx), 1, 0, 0);
Глядя на исходный код css3transform, вы можете получить свойства, поддерживаемые Transform.getMatrix2D:
Transform.getMatrix2D = function(option){
var defaultOption = {
translateX: 0,
translateY: 0,
rotation: 0,
skewX: 0,
skewY: 0,
originX: 0,
originY: 0,
scaleX: 1,
scaleY: 1
};
...
...
...
}
предметы особого внимания
Transform.getMatrix2D и Transform.getMatrix3D поддерживают функцию происхождения, пожалуйста, попрощайтесь с transform-origin Transform.getMatrix2D и Transform.getMatrix3D не используют традиционный Math.tan для реализации show, а вместо этого используют половину вращения
Например, 2d перекос:
Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX)
Ранее студенты из Tencent IEG спрашивали, зачем использовать половинное вращение вместо Math.tan? Причина проста, Math.tan очень сильно искажает, и есть бесконечные значения, которые заставляют искажение охватывать весь экран.
Половины оборота нет.
Полезен ли getMatrix2D?
При использовании для Dom Transformation его можно использовать для браузеров, которые не поддерживают CSS3 3D Transforms.
Например, мы можем легко преобразовать некоторые свойства преобразования в свойства CSS3 и присвоить их DOM:
var matrix = Transform.getMatrix2D({
rotation: 30,
scaleX: 0.5,
scaleY: 0.5,
translateX: 100
});
ele.style.transform = ele.style.msTransform = ele.style.OTransform = ele.style.MozTransform = ele.style.webkitTransform = "matrix(" + [matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty].join(",") + ")"
Для холста и преобразования SVG
Какой? Можно ли его также использовать для Canvas и SVG?Да, например, нарисовать изображение на Canvas, которое повернуто на 30 градусов, масштабировано в 0,5 раза и переведено (200 200):
var canvas = document.getElementById("ourCanvas"),
ctx = canvas.getContext("2d"),
img = new Image(),
rotation = 30 * Math.PI / 180
img.onload = function () {
ctx.sava();
ctx.setTransform(
0.5 * Math.cos(rotation), 0.5 * Math.sin(rotation),
-0.5 * Math.sin(rotation), 0.5 * Math.cos(rotation),
200, 200
)
ctx.drawImage(img, 0, 0)
ctx.restore()
};
img.src = "asset/img/test.png"
Это наша традиционная поза. После использования Transform.getMatrix2D стало вот так:
var canvas = document.getElementById("ourCanvas"),
ctx = canvas.getContext("2d"),
img = new Image()
var matrix = Transform.getMatrix2D({
rotation: 30,
scaleX: 0.5,
scaleY: 0.5,
translateX: 200,
translateY: 200
});
img.onload = function () {
ctx.sava();
ctx.setTransform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
ctx.drawImage(img, 0, 0);
ctx.restore();
}
img.src = "asset/img/test.png"
Как видите, разработчикам не нужно самим собирать матрицу. Частицы SVG больше не используются в качестве примеров, которые аналогичны примерам, используемым для DOM, Я думаю, что каждый может сделать это быстро.