js 创建keyframe_Vue中使用create-keyframe-animation与动画钩子完成复杂动画

本篇文章主要介绍了 Vue中使用create-keyframe-animation与动画钩子完成复杂动画,分享给大家

如何实现这个动画?

效果分析

点`start`的时候,我们把整个动画拆分为两种效果(过渡和动画)。

1. 中间cd消失,下方播放条显示,这是属于`过渡`

2. `过渡`开始的同时,cd同时移动、放大、缩小到左下方播放条 ,这属于`动画`

上面的效果是【过渡】加【动画】同时使用完成的

对于第一种【过渡】,我们用vue中transition标签,加设置v-enter、v-leave-to、v-enter-active、v-leave-enter即可完成

对于第二种【动画】,我们就要用keyframe来完成了。

这里我们先完成第一种过渡

vue中模板节点

// CD图片 (动画的时候图片初始位置)

start

// 下面播放状态框

// 状态看里面的图片 (动画的时候图片结束位置)

结构很简单,基本就是 两个大div ,然后把div的布局按效果图那些布置。

css部分(省略布局部分)

.cd-box

&.v-enter-active, &.v-leave-active

transition: all 0.4s

&.v-enter, &.v-leave-to

opacity: 0

.mini-player-box

&.v-enter-active, &.v-leave-active

transition: all 0.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不一样,所以要动态计算。

给 添加动画钩子

@enter="enter"

@after-enter="afterEnter"

@leave="leave"

@after-leave="afterLeave"

>

计算偏移量(中心点到中心的偏移,图中红线距离)

// 获得偏移量,以及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}

},

x,y的数值代表什么?见图

这里x为什么是负的,y是正的呢?

因为 浏览器的坐标系的中心点是在左上角 的,如图

那么动画从 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)`

}

}

所有源码

@enter="enter"

@after-enter="afterEnter"

@leave="leave"

@after-leave="afterLeave"

>

start

/* eslint-disable */

import animations from 'create-keyframe-animation'

export default {

components: {},

props: {},

data() {

return {

fullScreen: true

}

},

computed: {},

watch: {},

created() {},

mounted() {

// const {x, y, scale} = this._getPosAndScale()

console.log(this._getPosAndScale())

console.log(animations)

},

methods: {

switchMode() {

this.fullScreen = !this.fullScreen

},

_getPosAndScale() {

const targetWidth = 40

const paddingLeft = 20

const paddingBottom = 20

const paddingTop = 0

const width = 300

const scale = targetWidth / width

const x = -(window.innerWidth / 2 - paddingLeft)

const y = window.innerHeight - paddingTop - paddingBottom - width / 2

return {x ,y , scale}

},

enter(el, done) {

const {x, y, scale} = this._getPosAndScale()

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)`

}

}

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(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})`

// this.$refs.cdWrapper.style['transform'] = 'rotate(360deg)'

// transitionend 事件在 CSS 完成过渡后触发

this.$refs.cdWrapper.addEventListener('transitionend', () => {

done()

})

},

afterLeave() {

this.$refs.cdWrapper.style.transition = ''

this.$refs.cdWrapper.style['transform'] = ''

}

}

}

.index

background: #eee

width: 100%

height: 100%

display : flex

flex-direction: column

justify-content : space-between

align-items: center

.cd-box

display : flex

justify-content : center

align-items : center

width: 300px

height: 300px

background: #eee

border-radius: 50%

&.v-enter-active, &.v-leave-active

transition: all 0.4s

&.v-enter, &.v-leave-to

opacity: 0

.bg

width: 300px

height: 300px

border-radius: 50%

.mini-box

position: absolute

bottom: 0

right: 0

left: 0

display : flex

align-items center

border: 1px solid #555

width: 100%

height: 40px

box-sizing : border-box

&.v-enter-active, &.v-leave-active

transition: all 0.4s

&.v-enter, &.v-leave-to

transform: translate3d(0, 40px, 0)

opacity: 0

.mini-img

height: 40px

width: 40px

box-sizing : border-box

img

height: 100%

width: 100%

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值