文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

js实现一个逐步递增的数字动画

2024-04-02 19:55

关注

背景

可视化大屏项目使用最多的组件就是数字组件,展示数据的一个变化,为了提高视觉效果,需要给数字增加一个滚动效果,实现一个数字到另一个数字逐步递增的滚动动画。

先上一个思维导图:

实现类似滚轮的效果,容器固定,数字向上滚动

先列举所有的可能的值形成一个纵向的列表,然后固定一个容器,匀速更改数字的偏移值。

下面来介绍一下这种方案的实现,元素值从0到9一共十个值,每个数字占纵向列表的10%,所以纵向偏移值依次为为0%  —> -90%

实现:


<ul>
  <li>
    <span>0123456789</span>
  </li>
</ul>

ul{
  margin-top: 200px;
}
ul li{
  margin:0 auto;
  width: 20px;
  height: 30px;
  text-align: center;
  border:2px solid rgba(221,221,221,1);
  border-radius:4px;
}
ul li span{
  position: absolute;
  color: #fff;
  top: 30%;
  left: 50%;
  transform: translate(-50%,0);
  transition: transform 500ms ease-in-out;
  writing-mode: vertical-rl;
  text-orientation: upright;
  letter-spacing: 17px;
}

let spanDom = document.querySelector('span')
let start = 0
setInterval(() =>{
  start++
  if(start>9){
    start = 0
  }
  spanDom.style.transform = `translate(-50%,-${start*10}%)`
}, 1000)

上述代码存在一个问题,当我们从9到0的时候,容器偏移从-90%直接到了0%。 但是由于设定了固定的过渡动画时间,就会出现一个向反方向滚动的情况,为了解决这个问题,可以参考无缝滚动的思路


<ul>
  <li>
    <span>01234567890</span>
  </li>
</ul>

let spanDom = document.querySelector('span')
let start = 0
var timer = setInterval(fn, 1000);
function fn() {
  start++
  clearInterval(timer)
  timer = setInterval(fn,start >10 ? 0 : 1000);
  if(start>10){
    spanDom.style.transition = `none`
    start = 0
  }else{
    spanDom.style.transition = `transform 500ms ease-in-out`
  }
  spanDom.style.transform = `translate(-50%,-${start/11*100}%)`
}

利用两个元素实现滚动

仔细看动图的效果,事实上在在视口只有两个元素,一个值之前的值,一个为当前的值,滚动偏移值只需设置translateY(-100%)

具体思路:

下面是调整后的代码结构:


 <div className={styles.slider}>
   {[prev, cur].map((item, index) => (
      <span key={index} className={`${styles['slider-text']} ${playing && styles['slider-ani']} ${(prev === 0 && cur === 0 && index ===0) && styles['slider-hide']}`}>
        {item}
      </span>
    ))}
  </div>

const { value} = props
const [prev, setPrev] = useState(0)
const [cur, setCur] = useState(0)
const [playing, setPlaying] = useState(false)

  const play = (pre, current) => {
    setPrev(pre)
    setCur(current)
    setPlaying(false)
    setTimeout(() => {
      setPlaying(true)
    }, 20)
  }

  useEffect(() => {
    if (!Number.isNaN(value)) {
      play(cur, value)
    } else {
      setPrev(value)
      setCur(value)
    }
  }, [value])


.slider {
  display: flex;
  flex-direction: column;
  height: 36px;
  margin-top: 24%;
  overflow: hidden;
  text-align: left;
}

.slider-text {
  display: block;
  height: 100%;
  transform: translateY(0%);
}

.slider-ani {
  transform: translateY(-100%);
  transition: transform 1s ease;
}
.slider-hide {
  opacity: 0;
}

实现多个滚轮的向上滚动的数字组件

利用H5的requestAnimationFrame()API实现数字逐步递增的动画效果

实现一个数字的逐渐递增的滚动动画,并且要在指定时间内完成。要看到流畅的动画效果,就需要在更新元素状态时以一定的频率进行,JS动画都是通过在很短的时间内不停的渲染/绘制元素做到的,所以计时器一直都是Javascript动画的核心技术,关键就是刷新的间隔时间,刷新时间需要尽量短,这样动画效果才能显得更加流畅,不卡顿;同时刷新间隔又不能太短,需要确保浏览器有能力渲染动画 。
大多数电脑显示器的刷新频率是 60Hz,即每秒重绘 60次。因此平滑动画的最佳循环间隔是通常是 1000ms/60,约等于16.6ms

计时器对比

requestAnimationFrame实现滚动动画思路

动画开始,记录开始动画的时间 startTimeRef.current


const startTimeRef = useRef(Date.now());
const [t, setT] = useState(Date.now());

之后每一帧动画,记录从开始动画经过了多长时间,计算出当前帧的所到达的数字应该是多少,即currentValue


useEffect(() => {
    const rafFunc = () => {
      const now = Date.now();
      const t = now - startTimeRef.current;
      if (t >= period) {
        setT(period);
      } else {
        setT(t);
        requestAnimationFrame(rafFunc);
      }
    };
    let raf;
    if (autoScroll) {
      raf = requestAnimationFrame(rafFunc);
      startTimeRef.current = Date.now();
    } else {
      raf && cancelAnimationFrame(raf);
    }
    return () => raf && cancelAnimationFrame(raf);
}, [period, autoScroll]);

const currentValue = useMemo(() => ((to - from) / period) * t + from, [t, period, from, to]);

针对当前每个数字位上的数字进行比较,如果有变化,进行偏移量的变化,偏移量体现在当前数字位上的数字与下一位数字之间的差值,这个变化每一帧都串起来形成了滚动动画

成果展示

到此这篇关于js实现一个逐步递增的数字动画的文章就介绍到这了,更多相关js 逐步递增数字动画内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯