使用cube-ui的create-api,制作小球抛物线动画,动画结束后小球自动销毁。讲述先欠着,有时间再补,先上效果:
代码实现:
首先,ball 组件,需要两层,内层水平线性移动,外层垂直贝塞尔曲线运动,实现抛物线效果。
组件模板部分:
<template>
<transition name="ball"
@before-enter="beforeDrop"
@enter="dropping"
@after-enter="afterDrop"
>
<div class="ball" v-show="btnShow">
<div class="inner"></div>
</div>
</transition>
</template>
js部分:
export default {
name: 'Ball',
data () {
return {
btnShow: false,
startPos: {},
stopPos: {}
}
},
methods: {
// 对外接口
drop (startPos, stopPos) {
this.btnShow = !this.btnShow
this.startPos = startPos
this.stopPos = stopPos
},
beforeDrop (el) { // 过渡开始前,将小球设置到指定起始位置
const inner = el.getElementsByClassName('inner')[0] // 重置子元素位置,为下一次动画做准备
inner.style.transform = 'translate3d(0, 0, 0)'
el.style.transform = `translate3d( ${this.startPos.x}px, ${this.startPos.y}px, 0)`
},
dropping (el, done) { // 过渡,将小球移动到指定终点位置
this._reflow = el.offsetWidth // 触发重绘
const inner = el.getElementsByClassName('inner')[0]
el.style.transform = `translate3d(0, ${this.stopPos.y}px, 0)` // 外层
inner.style.transform = `translate3d(${this.stopPos.x}px, 0, 0)` // 内层
done()
},
afterDrop (el) {
this.btnShow = !this.btnShow // 动画结束后隐藏小球
// 对外发送动画结束信号
el.addEventListener('transitionend', () => {
this.$emit('transitionOver')
})
}
}
}
css部分:
.ball{
position: absolute;
left: 0;
top: 0;
z-index: 20;
transition: all 0.4s cubic-bezier(.32,-0.43,.89,.66);
.inner{
width: 20px;
height: 20px;
border-radius: 50%;
background-color: red;
transition: all 0.4s linear;
}
}
之后是调用部分:
模板部分:
<template>
<div class="balls-container">
<button @click="handleClick">click me</button>
<div class="pos posStart" ref="posStart"></div>
<div class="pos posStop" ref="posStop"></div>
</div>
</template>
js部分:
const BALL_LEN = 10
function createBalls () {
const balls = []
for (let i = 0; i < BALL_LEN; i++) {
balls.push({
hasBall: false
})
}
return balls
}
export default {
name: 'DropBalls',
data () {
return {
ballList: createBalls()
}
},
methods: {
handleClick () {
const elStratRect = this.$refs.posStart.getBoundingClientRect()
const elStopRect = this.$refs.posStop.getBoundingClientRect()
const startPos = { // 设置ball起始位置
x: elStratRect.left - 5,
y: elStratRect.top - 5
}
const stopPos = { // 设置ball结束位置
x: elStopRect.left - 5,
y: elStopRect.top - 5
}
for (let i = 0; i < this.ballList.length; i++) {
const ball = this.ballList[i]
if (!ball.hasBall) {
ball.compBall = this.$createBall() // 动态创建ball组件,并将其实例保存在ballList的元素属性中
ball.compBall.drop(startPos, stopPos) // 调用ball组件drop方法
ball.compBall.$on('transitionOver', () => { // 监听ball组件过渡结束事件
ball.compBall.remove() // 动画结束后清除DOM元素
delete ball.compBall // 删除compBall属性
ball.hasBall = false // 失去compBall属性的ball元素,将其hasBall属性重置为false,以供下次使用
})
ball.hasBall = true // ball添加compBall属性,保存ball组件实例后,将hasBall属性置为true
return // 保存本次点击事件创建的ball组件实例后,跳出循环
}
}
}
}
}
css部分:
.pos{
position: absolute;
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
}
.posStart{
left: 100px;
top:300px;
}
.posStop{
left:250px;
top:600px;
}
另外,ball组件需要到main.js中注册:
import { createAPI } from 'cube-ui'
import Ball from './components/ball.vue'
createAPI(Vue, Ball, ['transitionOver'])
Vue.config.productionTip = false
本文通过cube-ui的create-api,展示了如何利用Vue、CSS和JavaScript制作小球抛物线动画。动画由内外两层组成,内层水平移动,外层应用贝塞尔曲线实现抛物线轨迹。在动画结束后,小球会自动销毁。具体实现细节包括ball组件的模板、JS和CSS代码,以及组件在main.js中的全局注册。

4586

被折叠的 条评论
为什么被折叠?



