背景
最近在做电商的h5项目,会有这个一个东西,商品列表添加到购物车的动画。emmm 作为一个优秀的前端工程师,说干就干
思路
拿到这个问题,正常的思维就是做一个动画,设置好位置,left,top,然后移动到购物车的位置就好了。
实现
好的,基本思路有了。写一个js文件,创建一个class,emmm名字就叫shoppingBall,我可真是个取名鬼才
class ShoppingBall{}
好,那我们来想想,这个ball需要什么属性,emmm 需要起始点坐标,终止点坐标,需要挂载的元素。我们记录下这些属性。
construtor(target,position,destination){
this.target = target[0]
this.position = position
this.destination = destination
}
接下来我们创建一个ball的dom元素,设置好高度宽度颜色,插入到我们的target元素中
createBall () {
this.node = document.createElement('div')
this.node.style.height = '10px'
this.node.style.width = '10px'
this.node.style.position = 'absolute'
this.node.style.borderRadius = '50%'
this.node.style.backgroundColor = '#00B058'
this.node.style.top = this.position.top + 'px'
this.node.style.zIndex = '2'
this.node.style.left = this.position.left + 'px'
this.target.appendChild(this.node)
this.move()
}
我们的开始移动元素:通过改变我们的ball的位置来实现这个动画,递归调用这个move方法
move () {
if (this.position.top > this.destination.top) {
this.target.removeChild(this.node)
return
}
this.position.top += 10
this.position.left += 10
requestAnimationFrame(() => {
this.node.style.top = this.position.top + 'px'
this.node.style.left = this.position.left + 'px'
this.move()
})
}
emmmmmm初版的代码已经写完了。不过效果好像不是很好,小球的走路线是斜着的,而且毫无美感。作为一个优秀的前端工程师是不允许自己的页面这么丑的。
优化
开始优化,加入时间的概念和加速度概念,让我们的小球走一个抛物线。增加了横向速度和纵向速度
this.xSpeed = (this.destination.left - this.position.left) / (this.duration * 10)
this.ySpeed = -10
然后更改我们的move方法:
move () {
if (this.position.top > this.destination.top) {
this.target.removeChild(this.node)
return
}
this.position.top += this.ySpeed + this.time
if (this.position.left > this.destination.left) {
this.position.left += this.xSpeed
}
requestAnimationFrame(() => {
this.node.style.top = this.position.top + 'px'
this.node.style.left = this.position.left + 'px'
this.time++
this.move()
})
}
看看效果
看着还行撒。再试试别的方法,诶 是不是有这么一个东西transition
transition
transition是在属性变化中起到过度的动画,好,我直接设置终点的坐标位置,然后设置transition,通过改变这个的bezier 曲线来去改变。我改一下这个创建ball的方法
if (this.heightPart) {
this.node.style.transition = `left 1.5s cubic-bezier(0,2.3, 1, 2.6),top 1.5s cubic-bezier(0,-0.1, 0.5, 0.5)`
} else {
this.node.style.transition = `left 1s cubic-bezier(0,1, 1, 1),top 1s cubic-bezier(0,-1, 0.5, 0.5)`
}
setTimeout(() => {
this.node.style.left = this.destination.left + 'px'
this.node.style.top = this.destination.top + 'px'
}, 100)
setTimeout(() => {
this.target.removeChild(this.node)
}, this.heightPart ? 1600 : 1000)
我区分了一下高位和低位,可以以不同的动画。来,展示
总结
刚做完,组长过来说 这是需求之外的东西,可以上,但是后期的bug全是我的。