最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue中使用create-keyframe-animation與動(dòng)畫鉤子完成復(fù)雜動(dòng)畫

 更新時(shí)間:2019年04月09日 09:11:29   作者:Edon-  
這篇文章主要介紹了Vue中使用create-keyframe-animation與動(dòng)畫鉤子完成復(fù)雜動(dòng)畫,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

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

 

如何實(shí)現(xiàn)這個(gè)動(dòng)畫?

 效果分析

點(diǎn)`start`的時(shí)候,我們把整個(gè)動(dòng)畫拆分為兩種效果(過渡和動(dòng)畫)。

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

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

上面的效果是【過渡】加【動(dòng)畫】同時(shí)使用完成的

  • 對(duì)于第一種【過渡】,我們用vue中transition標(biāo)簽,加設(shè)置v-enter、v-leave-to、v-enter-active、v-leave-enter即可完成
  • 對(duì)于第二種【動(dòng)畫】,我們就要用keyframe來完成了。

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

vue中模板節(jié)點(diǎn)

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

結(jié)構(gòu)很簡(jiǎn)單,基本就是 兩個(gè)大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變量改變的時(shí)候,就會(huì)觸發(fā)【過渡】

這里我們完成第二種動(dòng)畫

首先安裝插件npm i create-keyframe-animation 這個(gè)插件是用js寫css的keyframe動(dòng)畫用的,至于為什么keyframe不在css里面寫呢?那是因?yàn)槠聊淮笮〔灰粯樱瑫?huì)導(dǎo)致需要移動(dòng)的px不一樣,所以要?jiǎng)討B(tài)計(jì)算。

給 <transition> 添加動(dòng)畫鉤子

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

計(jì)算偏移量(中心點(diǎn)到中心的偏移,圖中紅線距離)

 

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

 

這里x為什么是負(fù)的,y是正的呢?

因?yàn)?瀏覽器的坐標(biāo)系的中心點(diǎn)是在左上角 的,如圖

那么動(dòng)畫從 cd中心到左下角,X偏移為負(fù),y偏移為正

然后用animations插件執(zhí)行動(dòng)畫鉤子

 // enter是指當(dāng) cd從隱藏到顯示的動(dòng)畫,
 enter(el, done) {
  const {x, y, scale} = this._getPosAndScale()

  let animation = {
  // 第0幀的時(shí)候,先讓圖片縮小,顯示在右下角
  0: {
   transform: `translate3d(${x}px, ${y}px, 0) scale(${scale})`
  },
  // 60%的時(shí)候,讓圖片回到cd中心,變大
  60: {
   transform: `translate3d(0 ,0 , 0) scale(1.1)`
  },
  // 變回原來的尺寸,會(huì)有一個(gè)回彈的效果
  100: {
   transform: `translate3d(0 ,0 , 0) scale(1)`
  }
  }
  // 動(dòng)畫的一些配置
  animations.registerAnimation({
  name: 'move',
  animation,
  presets: {
   duration: 400,
   easing: 'linear'
  }
  })
//運(yùn)行動(dòng)畫
 animations.runAnimation(this.$refs.cdWrapper, 'move', done)
 },
 afterEnter(){
 //運(yùn)行完動(dòng)畫之后,注銷掉動(dòng)畫
  animations.unregisterAnimation('move')
  this.$refs.cdWrapper.style.animation = ''
 },
 // leave是指 cd從顯示到隱藏的動(dòng)畫
 leave(el, done) {
  this.$refs.cdWrapper.style.transition = 'all 0.4s'
  const {x, y, scale} = this._getPosAndScale()
  // 這里我們只要直接移動(dòng)變小就可以了
  this.$refs.cdWrapper.style['transform'] = `translate3d(${x}px,${y}px,0) scale(${scale})`
   
 // 監(jiān)聽transitionend 事件在 CSS 完成過渡后觸發(fā)done回調(diào)  
 this.$refs.cdWrapper.addEventListener('transitionend', () => {
  done()
  })
 },
 afterLeave() {
  this.$refs.cdWrapper.style.transition = ''
  this.$refs.cdWrapper.style['transform'] = ''
 }

寫到這里,我們就把剛開始的效果給寫完啦!

但在寫js的keyframe的時(shí)候

我們還可以加上rotate,讓動(dòng)畫效果有一個(gè)回彈效果

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 完成過渡后觸發(fā)
  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>

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue el-upload 上傳文件格式校驗(yàn)方法

    vue el-upload 上傳文件格式校驗(yàn)方法

    這篇文章主要介紹了vue el-upload 上傳文件格式校驗(yàn)方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-11-11
  • vue+element-ui集成隨機(jī)驗(yàn)證碼+用戶名+密碼的form表單驗(yàn)證功能

    vue+element-ui集成隨機(jī)驗(yàn)證碼+用戶名+密碼的form表單驗(yàn)證功能

    在登入頁面,我們往往需要通過輸入驗(yàn)證碼才能進(jìn)行登入,那我們下面就詳講一下在vue項(xiàng)目中如何配合element-ui實(shí)現(xiàn)這個(gè)功能,需要的朋友可以參考下
    2018-08-08
  • Vue3中Pinia的基本使用筆記

    Vue3中Pinia的基本使用筆記

    Pinia是一個(gè)全新的Vue狀態(tài)管理庫,是Vuex的代替者,尤雨溪強(qiáng)勢(shì)推薦,下面這篇文章主要給大家介紹了關(guān)于Vue3中Pinia的基本使用,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • 解決vue項(xiàng)目跳轉(zhuǎn)同樣的頁面不刷新的問題思路詳解

    解決vue項(xiàng)目跳轉(zhuǎn)同樣的頁面不刷新的問題思路詳解

    做公司官網(wǎng)項(xiàng)目的時(shí)候遇到的場(chǎng)景,頂部導(dǎo)航欄分類商品跳轉(zhuǎn)到分類詳情,然后在分類詳情再次點(diǎn)擊頂部導(dǎo)航欄里另外的分類商品,跳到同樣的頁面數(shù)據(jù)不刷新,下面小編給大家分享解決方式,關(guān)于vue跳轉(zhuǎn)不刷新問題感興趣的朋友一起看看吧
    2023-09-09
  • vue項(xiàng)目之?dāng)?shù)量占比進(jìn)度條實(shí)現(xiàn)方式

    vue項(xiàng)目之?dāng)?shù)量占比進(jìn)度條實(shí)現(xiàn)方式

    這篇文章主要介紹了vue項(xiàng)目之?dāng)?shù)量占比進(jìn)度條實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 一步步帶你用vite簡(jiǎn)單搭建ts+vue3全家桶

    一步步帶你用vite簡(jiǎn)單搭建ts+vue3全家桶

    Vue3與TS的聯(lián)合是大趨勢(shì),下面這篇文章主要給大家介紹了關(guān)于用vite簡(jiǎn)單搭建ts+vue3全家桶的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • vue頁面切換到滾動(dòng)頁面顯示頂部的實(shí)例

    vue頁面切換到滾動(dòng)頁面顯示頂部的實(shí)例

    下面小編就為大家分享一篇vue頁面切換到滾動(dòng)頁面顯示頂部的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue中的dom節(jié)點(diǎn)和window對(duì)象

    vue中的dom節(jié)點(diǎn)和window對(duì)象

    這篇文章主要介紹了vue中的dom節(jié)點(diǎn)和window對(duì)象,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue項(xiàng)目中使用addRoutes出現(xiàn)問題的解決方法

    Vue項(xiàng)目中使用addRoutes出現(xiàn)問題的解決方法

    大家應(yīng)該都知道可以通過vue-router官方提供的一個(gè)api-->addRoutes可以實(shí)現(xiàn)路由添加的功能,事實(shí)上就也就實(shí)現(xiàn)了用戶權(quán)限,這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中使用addRoutes出現(xiàn)問題的解決方法,需要的朋友可以參考下
    2021-08-08
  • 使用vscode快速建立vue模板過程詳解

    使用vscode快速建立vue模板過程詳解

    這篇文章主要介紹了使用vscode快速建立vue模板過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10

最新評(píng)論

元谋县| 宁南县| 兴国县| 龙胜| 长子县| 丰台区| 泽库县| 元氏县| 黔江区| 红河县| 抚顺市| 黄浦区| 濉溪县| 达拉特旗| 新竹县| 松阳县| 横山县| 阿巴嘎旗| 和平区| 抚宁县| 剑川县| 辽源市| 台南县| 花莲市| 新乐市| 特克斯县| 南涧| 泸溪县| 江山市| 河曲县| 大悟县| 玛纳斯县| 社旗县| 积石山| 郓城县| 古交市| 安丘市| 丰镇市| 太康县| 临武县| 方城县|