最近项目中要做一个领积分的效果,根据老板的描述,这个效果类似于支付宝蚂蚁森林里的领取能量。整体效果是就是在树周围飘着几个积分元素,上下滑动,类似星星闪烁,点击领取后,沿着树中心的位置滑动并消失,树上的能量递增,最后膨胀,变大一点。

1. 整体思路

首先想到基本轮廓是一个地球,周围半圆范围内围绕着好几个闪烁的小星星,然后同时坠落到地球上。用到css定位,border-radius画圆,animation动画,点击动作触发新的动画,积分递增效果类似于countUp.js,但是这里不用这个插件,手动实现。

1.1 半圆围绕效果

这个涉及到数学知识,根据角度得到弧度(弧度=角度*圆周率/180),进而换算成坐标,使积分元素围绕在总积分周围。关键代码如下:

this.integral.forEach(i => {
// 角度转化为弧度
let angle = Math.PI / 180 * this.getRandomArbitrary(90, 270)
// 根据弧度获取坐标
i.x = xAxis + 100 * Math.sin(angle)
i.y = 100 + 100 * Math.cos(angle)
// 贝塞尔函数
i.timing = this.timeFun[parseInt(this.getRandomArbitrary(0, 3))]
})

注意getRandomArbitrary()函数的功能是获取随机数,如下:

// 求两个数之间的随机数
getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}

timeFunc是一个贝塞尔函数名称集合,为了实现积分闪烁的效果(上下滑动),定义在data里:

timeFun: ['ease', 'ease-in', 'ease-in-out', 'ease-out'], // 贝塞尔函数实现闪烁效果

1.2 积分闪烁(上下滑动)

用css动画animation实现积分上下滑动,这里能想到的方式是transform: translateY(5px),就是在y轴上移动一定的距离,并且动画循环播放。代码如下:

.foo {
display: flex;
font-size: 10px;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
position: fixed;
top:;
left:;
animation-name: slideDown;
/*默认贝塞尔函数*/
animation-timing-function: ease-out;
/*动画时间*/
animation-duration: 1500ms;
/*动画循环播放*/
animation-iteration-count: infinite;
-moz-box-shadow: -5px -5px 10px 3px rgb(277, 102, 63) inset;
-webkit-box-shadow: -5px -5px 10px 3px rgb(277, 102, 63) inset;
box-shadow: -5px -5px 10px 3px rgb(277, 102, 63) inset;
} /*小积分上下闪烁*/
@keyframes slideDown {
from {
transform: translateY(0);
}
50% {
transform: translateY(5px);
background-color: rgb(255, 234, 170);
}
to {
transform: translateY(0);
background: rgb(255, 202, 168);
}
}

注意,我这里除了让积分上下移动,还让让它背景色跟着变化。上下移动的步调不能一致,不然看起来很呆板,所以要使用随机数函数在贝塞尔函数中随机选取一个,让积分小球上下滑动看起来是参差不齐的。关键代码如下:

/*html*/
<div :class="integralClass"
v-for="item in integral"
:data-angle="item.angle"
:style="{ left: item.x + 'px', top: item.y + 'px', animationTimingFunction: item.timing}">{{item.value}}
</div>
/*js*/
// data中定义
timeFun: ['ease', 'ease-in', 'ease-in-out', 'ease-out'], // 贝塞尔函数实现闪烁效果 // 随机获取贝塞尔函数
i.timing = this.timeFun[parseInt(this.getRandomArbitrary(0, 3))]

1.3 总积分递增效果

点击领取之后积分,总积分要累加起来,这个类似countUp.js的效果,但是这里不能为了这一个功能引用这个插件。项目是使用vue.js,很容易就想到修改data的响应式属性让数字变化,关键是如何让这个变化不是一下就变过来,而是渐进的。我这里思路是Promise+setTimeout,每隔一定时间修改一次data属性,这样看起来就不是突然变化的。

为了使动画效果看起来平滑,用总时间(1500毫秒)除以小积分个数,得到一个类似动画关键帧的值,这个值作为变化的次数,然后每隔一定时间执行一次。所有动画时间都设置成1500毫秒,这样整体效果一致。

关键代码如下:

this.integralClass.fooClear = true
this.totalClass.totalAdd = true
this.totalText = `${this.totalIntegral}积分`
let count = this.integral.length, timeoutID = null, tasks = [], totalTime = parseInt(1500 / count)
const output = (i) => new Promise((resolve) => {
timeoutID = setTimeout(() => {
// 积分递增
this.totalIntegral += this.integral[i].value
// 修改响应式属性
this.totalText = `${this.totalIntegral}积分`
resolve();
}, totalTime * i);
})
for (var i = 0; i < 5; i++) {
tasks.push(output(i));
}
Promise.all(tasks).then(() => {
clearTimeout(timeoutID)
})

1.4 小积分消失,总积分膨胀效果

最后一步就是,小积分沿着总积分的方向运动并消失,总积分膨胀一下。

小积分运动并消失,x轴坐标移动到总积分的x轴坐标,y轴移动到总积分的y轴坐标,其实就是坐标点变得和总积分一样,这样看起来就是沿着中心的方向运动一样。当所有小积分的坐标运动到这里时候,就可以删除data数据了。关键css如下:

.fooClear {
animation-name: clearAway;
animation-timing-function: ease-in-out;
animation-iteration-count:;
animation-fill-mode: forwards;
-webkit-animation-duration: 1500ms;
-moz-animation-duration: 1500ms;
-o-animation-duration: 1500ms;
animation-duration: 1500ms;
} /*清除小的积分*/
@keyframes clearAway {
to {
top: 150px;
left: 207px;
opacity:;
visibility: hidden;
width:;
height:;
}
}

总积分膨胀,我这里的实现思路是transform: scale(1.5, 1.5);就是在原来基础上变大一点,最后再回到原本大小transform: scale(1, 1);,关键css如下:

.totalAdd {
animation-name: totalScale;
animation-timing-function: ease-in-out;
/*动画只播放一次*/
animation-iteration-count:;
/*动画停留在最后一个关键帧*/
animation-fill-mode: forwards;
-webkit-animation-duration: 1500ms;
-moz-animation-duration: 1500ms;
-o-animation-duration: 1500ms;
animation-duration: 1500ms;
} @keyframes totalScale {
50% {
transform: scale(1.15, 1.15);
-ms-transform: scale(1.15, 1.15);
-moz-transform: scale(1.15, 1.15);
-webkit-transform: scale(1.15, 1.15);
-o-transform: scale(1.15, 1.15);
}
to {
transform: scale(1, 1);
-ms-transform: scale(1, 1);
-moz-transform: scale(1, 1);
-webkit-transform: scale(1, 1);
-o-transform: scale(1, 1);
}
}

至此,整个动画的逻辑就理清了,先写个demo,代码我已经放在github上了,积分动画

效果如下:

2. 在项目中落地

最后在项目中,涉及到一个ajax请求,就是领取积分,只需要把动画放在这个ajax请求成功回调里就大功告成了。js关键代码如下:

// 一键领取积分
aKeyReceive() {
if (this.unreceivedIntegral.length === 0) {
return bottomTip("暂无未领积分")
}
if (this.userInfo.memberAKeyGet) {
let param = {
memberId: this.userInfo.memberId,
integralIds: this.unreceivedIntegral.map(u => u.id).join(","),
integralValue: this.unreceivedIntegral.reduce((acc, curr, index, arr) => { return acc + curr.value }, 0)
}
this.$refs.resLoading.show(true)
api.getAllChangeStatus(param).then(res => {
let data = res.data
if (data.success) {
this.getRecordIntegralList()
this.playIntegralAnim()
} else {
bottomTip(data.message)
}
}).finally(() => {
this.$refs.resLoading.show(false)
})
} else {
this.$refs.refPopTip.show()
}
},
// 领取积分的动画
playIntegralAnim() {
this.integralClass.fooClear = true
this.totalClass.totalAdd = true
this.totalText = `${this.statisticsData.useValue}积分`
let count = this.unreceivedIntegral.length, timeoutID = null, tasks = [], totalTime = parseInt(1500 / count)
const output = (i) => new Promise((resolve) => {
timeoutID = setTimeout(() => {
this.statisticsData.useValue += this.unreceivedIntegral[i].value
this.totalText = `${this.statisticsData.useValue}积分`
resolve();
}, totalTime * i);
})
for (let i = 0; i < count; i++) {
tasks.push(output(i));
}
Promise.all(tasks).then(() => {
clearTimeout(timeoutID)
})
}

最后项目上线后的效果如下:

注意,这里页面闪一下是的原因是ajax请求里有一个loading状态,其实如果服务端完全可靠的话,可有可无。

最后各位看官如果有类似需求,不妨借鉴一下,有更好的思路也提出来我参考一下。

使用css动画实现领积分效果的更多相关文章

  1. CSS动画:旋转卡片效果

    <!DOCTYPE html> <html> <head> <title>demo</title> </head> <bo ...

  2. css动画之旋转翻牌效果

    1.我们先设置两个盒子大小,颜色等等,然后定位重叠在一起,最后再进行动画设置 例子如下: <style> .box { height: 300px; width: 300px; posit ...

  3. 15个来自 CodePen 的酷炫 CSS 动画效果【下篇】

    CodePen 是一个在线的前端代码编辑和展示网站,能够编写代码并即时预览效果.你在上面可以在线分享自己的 Web 作品,也可以欣赏到世界各地的优秀开发者在网页中实现的各种令人惊奇的效果. 今天这篇文 ...

  4. 赞!15个来自 CodePen 的酷炫 CSS 动画效果

    CodePen 是一个在线的前端代码编辑和展示网站,能够编写代码并即时预览效果.你在上面可以在线分享自己的 Web 作品,也可以欣赏到世界各地的优秀开发者在网页中实现的各种令人惊奇的效果. 今天这篇文 ...

  5. CSS动画效果的回调

    用纯JS实现动画效果代码量大,计算复杂.因此现在前端页面的动画效果一般都采用CSS来实现. CSS动画实现简单高效,但是在处理动画,控制动画过程上却缺少一些有效手段. 例如我们想在动画效果完成时调用回 ...

  6. CSS动画总结与呼吸灯效果

    首先,先介绍一下主要用到的css属性:animation,text-shadow. text-shadow就不再介绍了,上一篇已经详细介绍了用法.这里先介绍一下animation属性. 1.anima ...

  7. CSS动画效果之animation

    Y(^o^)Y css动画大乱弹之animation. 概述 什么是animation呢?在回答这个问题之前,先要说明什么叫做@keyframe(关键帧).@keyframe算是一个动画模板.在其中, ...

  8. CSS动画效果

    CSS变形效果 Transform translate:平移 translate(x,y) translateX(x) translateY(y)相对于元素原始位置平移. scale:缩放 大于1放大 ...

  9. web前端学习(三)css学习笔记部分(5)-- CSS动画--页面特效、HTML与CSS3简单页面效果实例

    CSS动画--页面特效部分内容目前仅仅观看了解内容,记录简单笔记,之后工作了进行内容的补充 7.  CSS动画--页面特效 7.1  2D.3D转换 7.1.1  通过CSS3转换,我们能够对元素进行 ...

随机推荐

  1. 关于OSS不再维护的一些讨论

    FUSE for macOS 将不再维护 Fuse 是一款针对Mac OS的文件系统所开发的一款开源软件. 用于MacOS的FUSE软件包提供了多个API,用于为OS X 10.9至macOS 10. ...

  2. SpringBoot2整合Shiro报错 UnavailableSecurityManagerException: No SecurityManager accessible to the calling code 【已解决】

    SpringBoot集成Shiro报错 UnavailableSecurityManagerException: No SecurityManager accessible to the callin ...

  3. 源码分析 Sentinel 之 Dubbo 适配原理

    目录 1.源码分析 SentinelDubboConsumerFilter 2.源码分析 SentienlDubboProviderFilters 3.Sentienl Dubbo FallBack ...

  4. CentOS7采用tar.gz包方式安装Mysql5.7

    软件:VMware Linux版本:CentOS 7 一.安装mysql(采用tar.gz包安装Mysql5.7) 1.安装开发工具包 [root@localhost ~]# yum groups m ...

  5. asp:textbox 的 TextMode:password

    1.  用于输入或显示密码的文本框,设置属性TextMode为Password <asp:TextBox ID="txt_Password" runat="serv ...

  6. File 关键词

    getParent() 获取父路径 getAbsoluteFile 获取绝对路径 length()  获得文件的字节数 getName() 获取路径中最后部分的名字 getPath() 获取整体路径. ...

  7. 大数据软件安装之Hadoop(Apache)(数据存储及计算)

    大数据软件安装之Hadoop(Apache)(数据存储及计算) 一.生产环境准备 1.修改主机名 vim /etc/sysconfig/network 2.修改静态ip vim /etc/udev/r ...

  8. CVE-2019-17564:Apache Dubbo反序列化漏洞复现

    0x00 漏洞背景 ①iiDubbo是一款高性能.轻量1级的开源java Rpc分布式服务框架. ②核心功能: ◉ 面向接口的远程过程调用 ◉ 集群容错和负载均衡 ◉ 服务自动注册与发现 ③特点: ◉ ...

  9. vue one

    目录 复习 Vue框架 Vue的优点 Vue的使用 vue完成简单的事件 vue操作简单样式 小结 指令 文本指令 事件指令 属性指令 条件指令 复习 """ 1.BBS ...

  10. 图-搜索-DFS-51. N皇后

    2020-03-15 19:49:59 问题描述: n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 上图为 8 皇后问题的一种解法. 给定一个整数 n ...