00:00
大家好,我是yangyang.今天给大家上面视频中GIF动图的效果的实现.
效果素材要求
素材是类似雪碧图的方式,图上有n帧形状

实现方法

合适的做法,是将所有的动画帧合并成一张图,通过改变background-position的值来实现动画帧切换。因此,逐帧动画也被称为“精灵动画(sprite animation)”。
通过css3动画
width: 32px; height: 32px;:设置元素的宽度和高度为 32 像素(可以根据实际图片帧的大小设置)
设置动画效果,bear 是动画名称,1s 表明动画持续时间为 1 秒,steps(4, end) 表明动画采用 4 步,每一步切换到最后一帧,infinite 表明动画无限循环播放。
定义动画的最后一帧,设置背景图片位置为 0, -800px,表明在 Y 轴上向上移动 800 像素.
.marker-animate-gif {
width: 32px;
height: 32px;
background-size: 32px 800px;
cursor: pointer;
overflow: visible;
opacity: 1;
margin: 0 auto;
visibility: visible;
pointer-events: auto;
animation: bear 1s steps(4, end) infinite;
& ~ .marker-title {
margin: 0 auto;
}
// 0% 20% 40% 80% 100%
// 0 ~ 20
// 20 ~ 40
// 40 ~ 80
// 80 ~ 100
@keyframes bear {
100% {
background-position: 0, -800px;
}
}
通过requestAnimationFrame循环调用实现

- constructor(width, sleep = 0.2, size = 21):接受三个参数,分别是图标的宽度、每帧动画间隔的时间(默认为 0.2 秒)、动画的总帧数(默认为 21)。
- begin():开始播放动画的方法。它第一查询所有具有 .marker-animate-gif 类的元素,然后调用 animate() 方法开始动画播放。
- animate(timestamp):动画播放函数,接受一个时间戳参数。它通过计算时间戳的差值来控制动画的播放速度。如果已经过了指定的时间间隔或是第一帧,就会更新每个动画元素的背景位置以实现动画效果。最后,通过调用 requestAnimationFrame() 方法循环调用自身,实现动画的持续播放
export default class AnimateIcon {
constructor(width, sleep = 0.2, size = 21) {
// const gifItems = this.gifItems()
// this.icons = gifItems.filter(item => iconKeys.include(item.key))
this.sleep = sleep
this.width = width
this.size = size
this.timer = null
this.start = undefined
}
begin() {
const elements = document.querySelectorAll('.marker-animate-gif')
if (!elements.length) {
return false
}
this.frame = 0
this.timer = requestAnimationFrame(this.animate.bind(this))
}
animate(timestamp) {
if (this.start === undefined) {
this.start = timestamp
}
const elapsed = timestamp - this.start
if (elapsed > 1000 * this.sleep || this.frame === 0) {
const elements = document.querySelectorAll('.marker-animate-gif')
elements.forEach(element => {
const width = element.clientWidth
// const maxPos = width * this.size
let yPos = 0
if (this.frame >= this.size) {
this.frame = 0
}
yPos = (this.frame) * width // yPos >= maxPos ? maxPos :
element.style.backgroundPosition = `0 -${yPos}px`
this.frame++
})
this.start = undefined
}
requestAnimationFrame(this.animate.bind(this))
}
}
通过setInterval实现
setInterval实现更为简单
function spotGifAnimate(size = 50, step =21) {
if (SpotIconCurrFrame < step) {
SpotIconCurrFrame++;
} else {
SpotIconCurrFrame = 0;
}
$(".marker-animate-gif").css("background-position", - size * SpotIconCurrFrame + 'px');
}
timer = setInterval(spotGifAnimate, 40)
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...


