Commit 66f7abd5 authored by wu.hui's avatar wu.hui

feat: 简单版数字滚动动画

parent 03558732
......@@ -45,21 +45,10 @@
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
margin-left: 10px;
}
.stat-bar .stat-item .scroll-num {
width: 39px;
height: 50px;
line-height: 50px;
text-align: center;
margin: 0 10px;
font-size: 41px;
color: #01fff6;
font-family: 'DigifaceWide';
border-radius: 3px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAyCAYAAADfuMIdAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAABAxJREFUeJzFmb2rXFUUxdc+X9e8JEQyEf8AE00nIoigRQqtrCyiEsEyWog2dnba+h9YCHZiEaIggjam0comIJJU4gck4T1DwvuYmXvPdu1z7515/gPZb/hx7rx5MIu1197n3PsC7EdVcE0fx4+6wA96xg37ftNhevgTmrhrOMurAa/Iv3hVHrph3286TE8T95126Ll+8u4Rnr8a3TEd/ajLnOtw9++K3VX8H+VkwuJCcWH3jqBiJ2BJlYe7ETs7acP5ix1OPlmwfy+4sDyYMpchWK0jDg5SQ7oCrQm3/gj482Fy4f4/1PNAAigH6xxPl5IM7Jwpp+7txVMlJS9wqAm9hIA13evv52GJxokTKQ8y5CGsixeoq3xMXI6aUmrUPuvyMCsL7gVEEgYT11FcXWfd0UYdUFRKVlE3cLTOCEcxIDJzskqcydlgcbkOFJjcQJids7IuKWhFQUalcwhkcAPDstCwaJtFQMl0LufGquco6Tuo+CFabLxZ/AJ0yAm1GD33higpR5bYC55E2BRhck6HPGcuVZmcgyMhY91HG8IUV6k2FEN1mDLnB6dHQe7C6Nw6ZO3RGYDwD3g9+EH32BCzc7WnoNpA5RHKTipx8KOyY/uB4pSTLooFsDSAYqM5sGu8gEaaNCS6ZqdhTuYwdAbf88Nq+4Yf1q2pTJmrWiKDaGjQrmXOEVSas1qmMXPm3PRBUOaOTYHqyGbOWeboHH8xYSKFJfZj7NYax8wpysZSDsHQHNTHvOCRyQZxslMJtbBbtxO6tNXc9MLKGu1U0pyrJYg0eNtjZWVj0EkntmW1zNE5pVuGzblKgW0Qe2Hiap3K2joUIzpuYa7YaVhkagjL3HHltLaKusGzuWUv2h1/NBtrkIbUmoWhFJ48vaAmMjvHslojGFTtm7dt5uKYuWBq55rrNn9uUE9MYbPxb3cIO8+xe3ntRStrc85e0hQ3S7XqdO3ZsZweUSZxlRs/N1ytc1m94X1r61ZtTzc3ZRVFFr537dbWsTGMO4S0Z025YUJ1Wr2wIQzLnPDFBuBSZO7WWagXm7KGuawb1xLX5OoclEdgCWPmlG/mMI7qi29ZmznByjrNudk5Cm3uqR8qtk7d2t5sLLXHEklF3DjunD253n5orrljDs6ZE7NSraRZqFporSe0iyclmZ2TyCUZY94kulLH563z3VfchFGOXXshJrK2st7F4ly/Ud2Ettnnx2IxYP9gL+AAP+OFF/+qi3MrYBbmV9J69okezz53B7/cuBnwhuyhdJ/2H3x0c/XypTurCxf31089/eg5/8z+6qVLu/17H97C7duf599/ezD+v/U1uYF4+gpev/wZrr7/tb71zjf65tvfPlIuX7nOCn6Jn77/OH/1xa/MnPwHoi9Z08sHR4EAAAAASUVORK5CYII=') no-repeat 0 0;
background-size: cover;
overflow: hidden;
margin-right: 4px;
}
.stat-bar .stat-item .dot {
background-color: #01fff6;
......
......@@ -31,24 +31,29 @@
<div class="stat-bar">
<div class="stat-bar-inner">
<div class="stat-item">
<div class="tit">累计用电量</div>
<div class="tit">绿色建材应用比例</div>
<div class="scroll-box"></div>
<div class="suffix">万kWh</div>
<div class="suffix">%</div>
</div>
<div class="stat-item">
<div class="tit">累计发电量</div>
<div class="tit">绿容率</div>
<div class="scroll-box"></div>
<div class="suffix">万kWh</div>
<div class="suffix">%</div>
</div>
<div class="stat-item">
<div class="tit">累计碳排放量</div>
<div class="tit">电气化率</div>
<div class="scroll-box"></div>
<div class="suffix">万t</div>
<div class="suffix">%</div>
</div>
<div class="stat-item">
<div class="tit">累计减碳</div>
<div class="tit">光伏发电</div>
<div class="scroll-box"></div>
<div class="suffix">万t</div>
<div class="suffix">万kWh</div>
</div>
<div class="stat-item">
<div class="tit">绿电交易量</div>
<div class="scroll-box"></div>
<div class="suffix">万kWh</div>
</div>
</div>
<svg width="0" height="0">
......
......@@ -151,8 +151,8 @@ const echart6Data = {
// 顶部滚动数字数据
const scrollNumData = {
beforeNumArr: ["000.00", "000.0", "0000", "00000"],
afterNumArr: ["003.45", "846.0", "0065", "36465"],
beforeNumArr: [0, 0, 0, 0],
afterNumArr: [3.45, 846.0, 68, 36465],
}
// 中间球体数据
......@@ -230,164 +230,33 @@ const lineChartOption = (xData, yData, interval) => {
}
}
// 创建多组数字
function createMultiSrollNum(numArr) {
const scrollBox = document.getElementsByClassName('scroll-box')
for (let i = 0; i < scrollBox.length; i++) {
const scrollNode = scrollBox[i]
const childNumArr = numArr[i].split('')
const docFrag = document.createDocumentFragment()
childNumArr.forEach((num, i) => {
docFrag.appendChild(createSrollNum(num))
})
scrollNode.appendChild(docFrag)
}
}
// 创建单个数字
function createSrollNum(num) {
const scrollNumNode = document.createElement('div')
if (num === '.') {
scrollNumNode.className = 'dot'
} else {
scrollNumNode.className = 'scroll-num'
scrollNumNode.innerHTML = '<ul><li>' + num + '</li></ul>'
}
return scrollNumNode
}
function getIntervalNumArr(start, end, reduce) {
const arr = []
if (reduce) {
for (let i = end; i > start; i--) {
arr.push(i)
}
} else {
for (let i = start; i < end; i++) {
arr.push(i)
}
}
return arr
}
function repeatArr(a, m) {
let j = []
for (let i = 0; i < m; i++) {
j = j.concat(a)
}
return j
}
// 创建多组数字动画
function addMultiDigitAnimate(beforeNumArr, afterNumArr) {
TWEEN.removeAll()
const scrollBox = document.getElementsByClassName('scroll-box')
const arr = []
for (let i = 0; i < scrollBox.length; i++) {
const scrollNode = scrollBox[i]
const beforeNum = beforeNumArr[i]
const afterNum = afterNumArr[i]
const isUp = Number(afterNum) - Number(beforeNum) >= 0
const beforeChildNumArr = beforeNum.split('')
const afterChildNumArr = afterNum.split('')
const scrollNum = scrollNode.childNodes
let delay = 0
const staticDuration = 6000
let zeroBeforeIndex = 0 // 是否以0开头 标志位
let zeroAfterIndex = 0 // 是否以0开头 标志位
let someNumberIndex = 0 // 前面有几位数字相同
let stopSomeNumber = false // 停止计算前面有几位数字相同
const digitIndex = beforeChildNumArr.findIndex((ele) => ele === '.') // 小数点
for (let j = 0; j < beforeChildNumArr.length; j++) {
if (beforeChildNumArr[j] === '.') {
continue
}
const num = +beforeChildNumArr[j]
const num2 = +afterChildNumArr[j]
// 算beforeNum前面的0
let zeroBeforeFlag = false
if (num === 0 && zeroBeforeIndex === j) {
if ((digitIndex > -1 && j < digitIndex - 1) || digitIndex === -1) {
zeroBeforeFlag = true
zeroBeforeIndex++
}
}
// 算afterNum前面的0
let zeroAfterFlag = false
if (num2 === 0 && zeroAfterIndex === j) {
if ((digitIndex > -1 && j < digitIndex - 1) || digitIndex === -1) {
zeroAfterFlag = true
zeroAfterIndex++
}
}
// 前面有几位数字相同
if (num === num2 && !stopSomeNumber) {
someNumberIndex++
} else {
stopSomeNumber = true
}
let numberArr
let repeatNum
if (isUp) {
if (num2 > num) {
numberArr = getIntervalNumArr(num, num2)
repeatNum = getIntervalNumArr(num2, 10).concat(getIntervalNumArr(0, num2))
} else {
numberArr = getIntervalNumArr(num2, num, true)
repeatNum = getIntervalNumArr(0, num2, true).concat([0]).concat(getIntervalNumArr(num2, 9, true))
}
numberArr = numberArr.concat(repeatArr(repeatNum, j - someNumberIndex))
numberArr.push(num2)
} else {
if (num2 < num) {
numberArr = getIntervalNumArr(num2, num, true)
repeatNum = getIntervalNumArr(0, num2, true).concat([0]).concat(getIntervalNumArr(num2, 9, true))
} else {
numberArr = getIntervalNumArr(num, num2)
repeatNum = getIntervalNumArr(num2, 10).concat(getIntervalNumArr(0, num2))
}
numberArr = numberArr.concat(repeatArr(repeatNum, j - someNumberIndex))
numberArr.push(num2)
numberArr.reverse()
}
const ulNode = scrollNum[j].childNodes[0]
ulNode.innerHTML = numberArr.map((ele) => '<li>' + ele + '</li>').join('')
const last = (1 / numberArr.length - 1) * 100
const start = isUp ? 0 : last
const lastDelay = delay + staticDuration * 0.03
const opacityBefore = zeroBeforeFlag ? 0 : 1
arr.push({
start,
end: isUp ? last : 0,
delay,
opacityBefore,
opacityAfter: zeroAfterFlag ? 0 : 1,
duration: staticDuration - lastDelay,
ulNode,
})
delay = lastDelay
ulNode.setAttribute('style', 'transform: translateY(' + start + '%);opacity:' + opacityBefore)
}
const demical = i < 3 ? 2 : 0
arr.push({
start: beforeNum,
end: afterNum,
delay: 0.2,
duration: 3000,
demical,
node: scrollBox[i],
})
}
arr.forEach((sObject) => {
const { start, end, ulNode, delay, duration, opacityBefore, opacityAfter } = sObject
new TWEEN.Tween({ y: start, opacity: opacityBefore })
.to({ y: end, opacity: opacityAfter }, duration)
const { start, end, node, delay, duration, demical } = sObject
new TWEEN.Tween({ n: start })
.to({ n: end }, duration)
.delay(delay)
.easing(TWEEN.Easing.Quintic.Out)
.onUpdate((object) => {
ulNode.setAttribute('style', 'transform: translateY(' + object.y + '%);opacity:' + object.opacity)
node.innerHTML = object.n.toFixed(demical)
})
.start()
})
......@@ -395,19 +264,6 @@ function addMultiDigitAnimate(beforeNumArr, afterNumArr) {
animate()
}
function createRandom() {
const arr = []
for (let i = 0; i < 4; i++) {
let str = ''
for (let j = 0; j < 5; j++) {
const num = Math.floor(Math.random() * 10) + ''
str += num
}
arr.push(str)
}
return arr
}
function animate(time) {
let id = requestAnimationFrame(animate)
var result = TWEEN.update(time)
......@@ -549,19 +405,12 @@ const rightLineChart = () => {
window.onload = () => {
/***********************************顶部数字滚动****************************************/
// 初始化
createMultiSrollNum(scrollNumData.beforeNumArr)
// 添加动画
addMultiDigitAnimate(scrollNumData.beforeNumArr, scrollNumData.afterNumArr)
addMultiDigitAnimate([45.256, 53.4, 45.6, 3564, 899], [52.65, 86.65, 2.53, 5767, 899])
setTimeout(() => {
addMultiDigitAnimate([52.65, 86.65, 2.53, 5767, 899], [45.256, 53.4, 45.6, 3564, 899])
}, 5000)
// 测试,点击第一列数字
// document.getElementsByClassName('scroll-box')[0].onclick = function () {
// const numArr = createRandom()
// beforeNumArr = afterNumArr
// afterNumArr = numArr
// addMultiDigitAnimate(beforeNumArr, afterNumArr)
// }
/***********************************左侧chart线条****************************************/
leftLineChart()
......
......@@ -31,25 +31,12 @@
}
.scroll-box {
display: flex;
margin-left: 10px;
// min-width: 215px;
}
.scroll-num {
width: 39px;
height: 50px;
line-height: 50px;
text-align: center;
margin: 0 10px;
font-size: 41px;
color: #01fff6;
font-family: 'DigifaceWide';
border-radius: 3px;
//background: url('../images/digital-bg.png') no-repeat 0 0;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAyCAYAAADfuMIdAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAABAxJREFUeJzFmb2rXFUUxdc+X9e8JEQyEf8AE00nIoigRQqtrCyiEsEyWog2dnba+h9YCHZiEaIggjam0comIJJU4gck4T1DwvuYmXvPdu1z7515/gPZb/hx7rx5MIu1197n3PsC7EdVcE0fx4+6wA96xg37ftNhevgTmrhrOMurAa/Iv3hVHrph3286TE8T95126Ll+8u4Rnr8a3TEd/ajLnOtw9++K3VX8H+VkwuJCcWH3jqBiJ2BJlYe7ETs7acP5ix1OPlmwfy+4sDyYMpchWK0jDg5SQ7oCrQm3/gj482Fy4f4/1PNAAigH6xxPl5IM7Jwpp+7txVMlJS9wqAm9hIA13evv52GJxokTKQ8y5CGsixeoq3xMXI6aUmrUPuvyMCsL7gVEEgYT11FcXWfd0UYdUFRKVlE3cLTOCEcxIDJzskqcydlgcbkOFJjcQJids7IuKWhFQUalcwhkcAPDstCwaJtFQMl0LufGquco6Tuo+CFabLxZ/AJ0yAm1GD33higpR5bYC55E2BRhck6HPGcuVZmcgyMhY91HG8IUV6k2FEN1mDLnB6dHQe7C6Nw6ZO3RGYDwD3g9+EH32BCzc7WnoNpA5RHKTipx8KOyY/uB4pSTLooFsDSAYqM5sGu8gEaaNCS6ZqdhTuYwdAbf88Nq+4Yf1q2pTJmrWiKDaGjQrmXOEVSas1qmMXPm3PRBUOaOTYHqyGbOWeboHH8xYSKFJfZj7NYax8wpysZSDsHQHNTHvOCRyQZxslMJtbBbtxO6tNXc9MLKGu1U0pyrJYg0eNtjZWVj0EkntmW1zNE5pVuGzblKgW0Qe2Hiap3K2joUIzpuYa7YaVhkagjL3HHltLaKusGzuWUv2h1/NBtrkIbUmoWhFJ48vaAmMjvHslojGFTtm7dt5uKYuWBq55rrNn9uUE9MYbPxb3cIO8+xe3ntRStrc85e0hQ3S7XqdO3ZsZweUSZxlRs/N1ytc1m94X1r61ZtTzc3ZRVFFr537dbWsTGMO4S0Z025YUJ1Wr2wIQzLnPDFBuBSZO7WWagXm7KGuawb1xLX5OoclEdgCWPmlG/mMI7qi29ZmznByjrNudk5Cm3uqR8qtk7d2t5sLLXHEklF3DjunD253n5orrljDs6ZE7NSraRZqFporSe0iyclmZ2TyCUZY94kulLH563z3VfchFGOXXshJrK2st7F4ly/Ud2Ettnnx2IxYP9gL+AAP+OFF/+qi3MrYBbmV9J69okezz53B7/cuBnwhuyhdJ/2H3x0c/XypTurCxf31089/eg5/8z+6qVLu/17H97C7duf599/ezD+v/U1uYF4+gpev/wZrr7/tb71zjf65tvfPlIuX7nOCn6Jn77/OH/1xa/MnPwHoi9Z08sHR4EAAAAASUVORK5CYII=')
no-repeat 0 0;
background-size: cover;
overflow: hidden;
margin-right: 4px;
}
.dot {
background-color: #01fff6;
width: 6px;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment