基于iconfont实现BI大屏的CountUp组件
素材准备
- iconfont内数字Icon 十个
实现原理
注意看下面灵魂画手的示意图,整个countUp容器,从左到右排列着每个数字容器,设置超出部分隐藏,然后每个数字容器从上到下排列好每一个数字,从0到9,从0到9我们可以想到什么? 我们注意到,数字一共10
个, 整个容器高度100%
,如果我们根据当前位置所在的数字,进行对应的平移操作,再加上transition
过渡效果,不就可以实现countUp效果了吗?
具体实现
- 页面结构
- 字符输入控件 提供一个输入控件,可以自定义想要自增的数值
<input
type="number"
onKeypress="return (/[\d]/.test(String.fromCharCode(event.keyCode)))"}"
oninput="if(value.length>10)value=value.slice(0,10)"
id="text"
>
添加change事件,更新我们要展示的number,至于事件里做了什么,我们下面再说
$('#text').change(function () {
number = $(this).val()
countUpAnimate(color)
if (t) {
clearInterval(t)
t = setInterval(function () {
number++
countUpAnimate(color)
}, 1500)
}
})
- 颜色选择控件 提供一个颜色选择控件,可以自定义想要展示的颜色
<input id="color" type="color">
添加change事件,更新我们要展示的颜色,至于事件里做了什么,我们同样下面再说
$('#color').change(function () {
color = $(this).val()
countUpAnimate(color)
if (t) {
clearInterval(t)
t = setInterval(function () {
number++
countUpAnimate(color)
}, 1500)
}
})
- 根据上面提供的结构,构造初始化的数组容器
<div id="countup">
</div>
// 容器
#countup {
width: 50vw;
height: 60px;
border-radius: 8px;
color: #20777a;
padding: 5px;
display: flex;
justify-content: space-around;
align-items: center;
position: absolute;
top: 350px;
left: 0;
right: 0;
margin: auto;
}
/*滚动数字设置*/
每个数字容器
.number-item {
width: 100%;
height: 100%;
overflow: hidden;
}
.number-item>div {
transition: transform 1s ease-in-out;
}
.number-item>div>div{
height: 60px;
line-height: 60px;
font-size: 30px;
text-align: center;
}
// 存放所有数字的容器
let numberStr = `
<div class="box">
<div class="iconfont icon-shuzi0 fs30"></div>
<div class="iconfont icon-shuzi1 fs30"></div>
<div class="iconfont icon-shuzi2 fs30"></div>
<div class="iconfont icon-shuzi3 fs30"></div>
<div class="iconfont icon-shuzi4 fs30"></div>
<div class="iconfont icon-shuzi5 fs30"></div>
<div class="iconfont icon-shuzi6 fs30"></div>
<div class="iconfont icon-shuzi7 fs30"></div>
<div class="iconfont icon-shuzi8 fs30"></div>
<div class="iconfont icon-shuzi9 fs30"></div>
</div>
`
// 初始化的数字集
let arr = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
// 动态创建dom
arr.map(v => {
let div = $('<div>')
div.addClass('number-item')
div.html(numberStr)
$('#countup').append(div)
})
- 对获取到的数字进行补位,补足10位
function countUpAnimate() {
// 总长为10个数字,不足十个数字的长度
toAmountNum(number)
}
// 处理数字
function toAmountNum(num) {
num = num.toString()
let data
// 把数字转为字符串变成字符串,补零
if (num.length < 10) {
num = '0' + num // 如未满十位数,添加"0"补位
toAmountNum(num) // 递归添加"0"补位
} else if (num.length === 10) {
data = num.split('') // 将其便变成数据,渲染至滚动数组
// 渲染的方法
setNumberTransform(data)
} else {
num = num.slice(0, 10) //超过10位的直接截取
number = num
data = num.split('') // 将其便变成数据,渲染至滚动数组
setNumberTransform(data)
}
}
- 根据数字设置平移的大小,实现动画 只需要设置平移Y轴对应的百分比,就能准确显示对应的数字
// 设置文字滚动
function setNumberTransform(data) {
// 每个数字容器
let children = $('#countup .box')
let len = 10 - number.toString().length
for (let i = 0; i < 10; i++) {
$(children[i]).css('color', color)
}
for (let i = 0; i < len; i++) {
$(children[i]).css('color', '#20777a')
}
// 结合CSS 对数字字符进行滚动,显示数量,
for (let index = 0; index < children.length; index++) {
const elem = children[index]
elem.style.transform = `translate(0, -${data[index] * 10}%)`
}
}
- 模拟数据自增,实现动画
countUpAnimate(color)
let t = setInterval(function () {
number++
countUpAnimate(color)
}, 1500)
这个动画就是经典的数学与css的结合,我们只需要建立属性-数字
间的这种关联关系,就不难写出优秀的动画
转载自:https://juejin.cn/post/7155437931123965989