<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.bootcss.com/vue/2.5.20/vue.min.js"></script>
<style>
.ball {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<input type="button" value="快到碗里来" @click="flag=!flag">
<!-- 1. 使用 transition 元素把 小球包裹起来 -->
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div class="ball" v-show="flag"></div>
</transition>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
flag: false
},
methods: {
// 注意: 动画钩子函数的第一个参数:el,表示 要执行动画的那个DOM元素,是个原生的 JS DOM对象
// 大家可以认为 , el 是通过 document.getElementById('') 方式获取到的原生JS DOM对象
beforeEnter(el){
// beforeEnter 表示动画入场之前,此时,动画尚未开始,可以 在 beforeEnter 中,设置元素开始动画之前的起始样式
// 设置小球开始动画之前的,起始位置
el.style.transform = "translate(0, 0)"
},
enter(el, done){
// 这句话,没有实际的作用,但是,如果不写,出不来动画效果;
// 可以认为 el.offsetWidth 会强制动画刷新
el.offsetWidth
// enter 表示动画 开始之后的样式,这里,可以设置小球完成动画之后的,结束状态
el.style.transform = "translate(150px, 450px)"
el.style.transition = 'all 1s ease'
// 这里的 done, 其实就是 afterEnter 这个函数,也就是说:done 是 afterEnter 函数的引用
done()
},
afterEnter(el){
// 动画完成之后,会调用 afterEnter
// console.log('ok')
this.flag = !this.flag
}
}
});
</script>
</body>
</html>
上面的小球动画有个问题,就是小球最后都会移动到150px,450px这个位置.这两个位置最好是计算出来的值,不管分辨率多少的显示屏,都应该移动到相同的位置.
怎么样来实现这样功能呢?
- 首先我们要获得小球的初始坐标
const ballPosition = this.$refs.ball.getBoundingClientRect();
//通过给小球dom加上refs,这样就可以通过this.$refs
//获取小球dom,然后通过getBoundingClientRect方法获取小球的坐标.
- 然后获得小球终点位置的坐标
const badgePosition = document
.getElementById("badge")
.getBoundingClientRect();
//因为终点位置的元素不一定和小球在同一个组件中,
//所以我们无法通过this.$refs获得,但是我可以给终点元素加上id,
//这样全局都可以通过js原生语法获得
- 计算小球移动的路径
const xDist = badgePosition.left - ballPosition.left;
const yDist = badgePosition.top - ballPosition.top;
- 小球移动的动画
//这里使用es6模板字符串语法
el.style.transform = `translate(${xDist}px, ${yDist}px)`;
el.style.transition = "all 1s cubic-bezier(0.4,-0.3,1,.69)";
完整代码如下
enter(el, done) {
el.offsetWidth;
const ballPosition = this.$refs.ball.getBoundingClientRect();
const badgePosition = document
.getElementById("badge")
.getBoundingClientRect();
const xDist = badgePosition.left - ballPosition.left;
const yDist = badgePosition.top - ballPosition.top;
el.style.transform = `translate(${xDist}px, ${yDist}px)`;
el.style.transition = "all 1s cubic-bezier(0.4,-0.3,1,.69)";
done();
},
afterEnter(el) {
this.ballFlag = !this.ballFlag;//通过标志位设置小球的显示与隐藏
},
getSelectedCount(count) {
this.selectedCount = count;
}
网友评论