如何实现这个动画?
效果分析
点`start`的时候,我们把整个动画拆分为两种效果(过渡和动画)。
1. 中间cd消失,下方播放条显示,这是属于`过渡`
2. `过渡`开始的同时,cd同时移动、放大、缩小到左下方播放条 ,这属于`动画`
上面的效果是【过渡】加【动画】同时使用完成的
对于第一种【过渡】,我们用vue中transition标签,加设置v-enter、v-leave-to、v-enter-active、v-leave-enter即可完成
对于第二种【动画】,我们就要用keyframe来完成了。
这里我们先完成第一种过渡
vue中模板节点
<template>
<divclass="index">
<transition>
<divclass="cd-box"ref="cdWrapper"v-show="fullScreen">
// CD图片 (动画的时候图片初始位置)
<imgsrc="../assets/bj.png"alt=""class="bg">
</div>
</transition>
<button@click="switchMode"style="position:absolute;top:0;left:10px;">start</button>
<transition>
// 下面播放状态框
<divclass="mini-player-box"v-show="!fullScreen">
// 状态看里面的图片 (动画的时候图片结束位置)
<divclass="mini-img">
<imgsrc="../assets/bj.png"alt="">
</div>
</div>
</transition>
</div>
</template>
结构很简单,基本就是 两个大div ,然后把div的布局按效果图那些布置。
css部分(省略布局部分)
.cd-box
&.v-enter-active, &.v-leave-active
transition: all0.4s
&.v-enter, &.v-leave-to
opacity: 0
.mini-player-box
&.v-enter-active, &.v-leave-active
transition: all0.4s
&.v-enter, &.v-leave-to
transform: translate3d(0, 40px, 0)
opacity: 0
这样在fullScreen变量改变的时候,就会触发【过渡】
这里我们完成第二种动画
首先安装插件 , npm i create-keyframe-animation 这个插件是用js写css的keyframe动画用的,至于为什么keyframe不在css里面写呢?那是因为屏幕大小不一样,会导致需要移动的px不一样,所以要动态计算。
给 <transition> 添加动画钩子
<transition >
@enter="enter"
@after-enter="afterEnter"
@leave="leave"
@after-leave="afterLeave"
>
<div class="cd-box"ref="cdWrapper"v-show="fullScreen">
<img src="../assets/bj.png"alt=""class="bg">
</div>
</transition>
// 获得偏移量,以及scale
_getPosAndScale() {
// 左下角图片的宽度
const targetWidth = 40
// cd宽度
const width = 300
const scale = targetWidth / width
// 这里的 x,y要算,过程省略,无非就是加加减减,这的x,y都是算出来了的
const x = -167.5
const y = 497
return{x ,y , scale}
},
那么动画从 cd中心到左下角,X偏移为负,y偏移为正
然后用animations插件执行动画钩子
// enter是指当 cd从隐藏到显示的动画,
enter(el, done) {
const {x, y, scale} = this._getPosAndScale()
let animation = {
// 第0帧的时候,先让图片缩小,显示在右下角
0: {
transform: `translate3d(${x}px, ${y}px, 0) scale(${scale})`
},
// 60%的时候,让图片回到cd中心,变大
60: {
transform: `translate3d(0 ,0 , 0) scale(1.1)`
},
// 变回原来的尺寸,会有一个回弹的效果
100: {
transform: `translate3d(0 ,0 , 0) scale(1)`
}
}
// 动画的一些配置
animations.registerAnimation({
name: 'move',
animation,
presets: {
duration: 400,
easing: 'linear'
}
})
//运行动画
animations.runAnimation(this.$refs.cdWrapper, 'move', done)
},
afterEnter(){
//运行完动画之后,注销掉动画
animations.unregisterAnimation('move')
this.$refs.cdWrapper.style.animation = ''
},
// leave是指 cd从显示到隐藏的动画
leave(el, done) {
this.$refs.cdWrapper.style.transition = 'all 0.4s'
const {x, y, scale} = this._getPosAndScale()
// 这里我们只要直接移动变小就可以了
this.$refs.cdWrapper.style['transform'] = `translate3d(${x}px,${y}px,0) scale(${scale})`
// 监听transitionend 事件在 CSS 完成过渡后触发done回调
this.$refs.cdWrapper.addEventListener('transitionend', () => {
done()
})
},
afterLeave() {
this.$refs.cdWrapper.style.transition = ''
this.$refs.cdWrapper.style['transform'] = ''
}
写到这里,我们就把刚开始的效果给写完啦!
但在写js的keyframe的时候
我们还可以加上rotate,让动画效果有一个回弹效果
let animation = {
0: {
transform: `translate3d(${x}px, ${y}px, 0) scale(${scale}) rotate(0deg)`
},
60: {
transform: `translate3d(0 ,0 , 0) scale(1.1) rotate(365deg)`
},
100: {
transform: `translate3d(0 ,0 , 0) scale(1) rotate(360deg)`
}
}