介绍
Vue 一个长图点击爱心特效 模仿gif的效果
# 特效的小效果
- 前几天访问别人的网站的时候 发现了一个很有趣的爱心特效
- 默认是红色爱心 点击后 会有一个很有趣的特效 这种效果是如何实现的?
# 实现思路
- 这种效果可以用那种长条图片来实现 就跟胶片一样 从左往右的逐帧播放 就能实现这个特效 类似的还有从上到下等等
- 就是这种长条图 通过前端css 动画 来实现播放效果 就可以和上面的gif效果一样啦
- 我们可以绑定
@click
点击事件 设置状态位 并且设置函数防抖 防止多次点击重置动画 - 这种动画学名叫做 序列帧动画
# 实现代码
- 用Vue3来实现效果
第一步 在template上设置爱心
- 这里我们用到了Vue的动态类名 默认的时候是爱心初始样式 点击变更状态位的时候 再给其添加css的动画效果
<template>
<div
:class="['loveBox', 'loveRed', loveState ? 'loveBoxAdm' : '']"
@click="loveThis"
/>
</template>
第二步 在sass中设置我们的爱心特效样式
- 通过
background-size
设置背景图的尺寸 让其能装下整条序列帧图片 并且设置宽度 让图片保持大小 - 通过
background-position
设置背景图的位置 通过animation
动画并设置动画帧数steps() (opens new window) 动画帧数从0%
按帧数滚动到100%
实现完整的序列帧动画效果
// 设置爱心小盒子
.loveBox {
height: 100%;
width: 50px;
margin: 0 auto;
background-image: url('https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/heart.3c55287.png');
background-repeat: no-repeat;
background-size: 2900%;
cursor: pointer;
}
// 把长条爱心背景图定格到最后
.loveRed {
background-position: 100%;
}
// 设置点击后的动画效果
.loveBoxAdm {
animation: sprite5 1s steps(28) forwards;
}
// 设置动画 从第一帧到最后一帧
@keyframes sprite5 {
0% {
background-position: 0%;
}
100% {
background-position: 100%;
}
}
第三步 点击爱心后 进行交互 播放爱心特效
- 通过交互 我们获取到绑定的点击事件 改变播放状态位 设置函数防抖 让其播放完毕后才能点击 这样就不会出现频繁点击重置动画
<script lang="ts" setup>
import { reactive, toRefs } from 'vue'
const data = reactive({
// 点击爱心状态
loveState: false,
// 爱心防抖
States: false
})
// 点击爱心
const loveThis = () => {
if (data.States) return
data.States = true
setTimeout(() => {
data.States = false
data.loveState = !data.loveState
}, 1000)
data.loveState = !data.loveState
}
// 解构导出
const { loveState } = toRefs(data)
</script>
- 完整代码
<template>
<div
:class="['loveBox', 'loveRed', loveState ? 'loveBoxAdm' : '']"
@click="loveThis"
/>
</template>
<script lang="ts" setup>
import { reactive, toRefs } from 'vue'
const data = reactive({
// 点击爱心状态
loveState: false,
// 爱心防抖
States: false
})
// 点击爱心
const loveThis = () => {
if (data.States) return
data.States = true
setTimeout(() => {
data.States = false
data.loveState = !data.loveState
}, 1000)
data.loveState = !data.loveState
}
// 解构导出
const { loveState } = toRefs(data)
</script>
<script lang="ts">
export default {
name: 'LoveClick'
}
</script>
<style lang="scss" scoped>
// 设置爱心小盒子
.loveBox {
height: 100%;
width: 50px;
margin: 0 auto;
background-image: url('https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/heart.3c55287.png');
background-repeat: no-repeat;
background-size: 2900%;
cursor: pointer;
}
// 把长条爱心背景图定格到最后
.loveRed {
background-position: 100%;
}
// 设置点击后的动画效果
.loveBoxAdm {
animation: sprite5 1s steps(28) forwards;
}
// 设置动画 从第一帧到最后一帧
@keyframes sprite5 {
0% {
background-position: 0%;
}
100% {
background-position: 100%;
}
}
</style>