flip动画在做动画的时候,一般调用 dom.animate 这个API的时候,用到的动画和css不能同时出现,例如 animate
里面调用的时候要是用到 tranform:translate ,css中尽量不要写,否则可能动画会出现问题
flip做点击图片放大预览的时候,一定要弄清楚哪个元素为初始状态(first),哪个元素是结束状态(last),invert
翻转完之后给哪个元素添加动画,就给哪个元素上调用 animate ,同时 调用缩放动画的时候别忘记 设置 transform-origin: top left,因为缩放默认是中心点
flip 动画四步走:
- 计算元素运动的开始状态 first – dom.getBoundingClientRect()
- 计算元素运动结束状态 last – dom.getBoundingClientRect()
- invert 翻转
const X = first.left - last.left
const Y = first.top - last.top
const W = first.width / last.width
const H = first.height / last.height - 开始动画
const flipAnimates = 动画元素.animate([], {})
flipAnimates.addEventListener(‘finish’, () => {})
1、创建 FlipAnimate.js 动画库(面向对象编程)
使用的时候js文件不需要改,直接使用即可, 但是针对的只是当前元素的动画,在元素变化(例如点击元素放大的场景中, 因为点击元素放大涉及到first、last状态不是同一个元素)不能使用此库
/**
* 面向对象方式
* 封装flip动画库
* @param {*} _element_list 当前变化元素集合
* @param {*} _options 默认动画配置
*/
function FlipAnimate(_element_list, _options = {
duration: 600, easing: 'cubic-bezier(0.3, 1, 0.68, 1)'}) {
this.elements = Array.from(_element_list) // 当前的元素列表转换成数组
this.options = _options;
this.firstPosition = []; // 动画开始状态数组
this.lastPosition = []; // 动画结束状态数组
this.first()
}
// 播放动画
FlipAnimate.prototype.play = function() {
this.last()
this.invert()
}
// first 状态
FlipAnimate.prototype.first = function() {
this.firstPosition = this.getPosition()
}
// last 状态
FlipAnimate.prototype.last = function() {
this.lastPosition = this.getPosition()
}
// 翻转 invert
FlipAnimate.prototype.invert = function() {
const diffrencePosition = this.firstPosition.map((first, index) => {
const last = this.lastPosition[index]
return {
left: first.left - last.left,
top: first.top - last.top,
width: first.width / last.width,
height: first.height / last.height,
duration: Math.ceil((2 * index / this.firstPosition.length) * 1000)
}
})
// 执行动画
let animates;
this.elements.forEach((el, index) => {
const {
left, top, width, height, duration } = diffrencePosition[index]
animates = el.animate([
{
transform: `translate(${
left}px, ${
top}px) scale(${
width}, ${
height})` },
{
transform: `translate(0px, 0px) scale(1, 1)` }
], {
// duration: this.options.duration, // 统一动画时间
dura