国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Vue中使用create-keyframe-animation與動畫鉤子完成復雜動畫

2019-11-19 11:51:20
字體:
來源:轉載
供稿:網友

本篇文章主要介紹了 Vue中使用create-keyframe-animation與動畫鉤子完成復雜動畫,分享給大家

 

如何實現這個動畫?

 效果分析

點`start`的時候,我們把整個動畫拆分為兩種效果(過渡和動畫)。

1. 中間cd消失,下方播放條顯示,這是屬于`過渡`

2. `過渡`開始的同時,cd同時移動、放大、縮小到左下方播放條 ,這屬于`動畫`

上面的效果是【過渡】加【動畫】同時使用完成的

  • 對于第一種【過渡】,我們用vue中transition標簽,加設置v-enter、v-leave-to、v-enter-active、v-leave-enter即可完成
  • 對于第二種【動畫】,我們就要用keyframe來完成了。

這里我們先完成第一種過渡

vue中模板節點

<template> <div class="index"> <transition>  <div class="cd-box" ref="cdWrapper" v-show="fullScreen"> // CD圖片 (動畫的時候圖片初始位置)  <img src="../assets/bj.png" alt="" class="bg">  </div> </transition> <button @click="switchMode" style="position:absolute;top:0;left:10px;">start</button> <transition> // 下面播放狀態框  <div class="mini-player-box" v-show="!fullScreen"> // 狀態看里面的圖片 (動畫的時候圖片結束位置)  <div class="mini-img">   <img src="../assets/bj.png" alt="" >  </div>  </div> </transition> </div></template>

結構很簡單,基本就是 兩個大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不一樣,所以要動態計算。

給 <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} },

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

所有源碼

<template> <div class="index"> <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> <button @click="switchMode" style="position:absolute;top:0;left:10px;">start</button> <transition>  <div class="mini-box" v-show="!fullScreen">  <div class="mini-img">   <img src="../assets/bj.png" alt="" >  </div>  </div> </transition> </div></template><script>/* 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'] = '' } }}</script><style lang="stylus" scoped>.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%</style>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 天水市| 大石桥市| 红桥区| 登封市| 集贤县| 牡丹江市| 汕头市| 东至县| 屏南县| 广饶县| 分宜县| 宝鸡市| 衢州市| 定西市| 鹿泉市| 安阳县| 德化县| 肥东县| 交口县| 盐山县| 青铜峡市| 喀喇| 平湖市| 蓬安县| 大荔县| 宜兴市| 拉萨市| 马公市| 临邑县| 同德县| 龙井市| 老河口市| 依兰县| 旺苍县| 马关县| 夏邑县| 绥阳县| 河曲县| 碌曲县| 正蓝旗| 宝丰县|