中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2021-08-10 13:23:39 來源:億速云 閱讀:239 作者:小新 欄目:web開發

這篇文章主要介紹了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中模板節點

<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" >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>

計算偏移量(中心點到中心的偏移,圖中紅線距離)

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

// 獲得偏移量,以及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的數值代表什么?見圖

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

這里x為什么是負的,y是正的呢?

因為 瀏覽器的坐標系的中心點是在左上角 的,如圖

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

那么動畫從 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" >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>

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Vue中如何使用create-keyframe-animation與動畫鉤子完成復雜動畫”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

vue
AI

瓮安县| 建平县| 兴隆县| 甘孜县| 子长县| 武隆县| 余庆县| 灵山县| 岳阳市| 东阿县| 高唐县| 双江| 瓮安县| 禹城市| 莫力| 内乡县| 柞水县| 安义县| 叙永县| 日喀则市| 洮南市| 陇南市| 乐亭县| 茌平县| 安陆市| 灵川县| 西充县| 荣昌县| 襄樊市| 灌南县| 建德市| 元氏县| 玉门市| 沈丘县| 宣武区| 淳化县| 滨州市| 张家川| 石嘴山市| 双柏县| 南汇区|