CSS 计数器的妙用:数字递增动效
持续进步的同学都关注了“1024译站” CSS 计数器是由 CSS 维护的变量,这些变量可根据 CSS 规则增加从而跟踪使用次数。我们可以利用这个特性,根据文档位置来调整内容表现,比如显示列表编号。 最近在公司官网就用到了这个特性: image.png 因为这里的序号只是个装饰,并不强调先后顺序。比起使用真实 DOM 元素显示序号,CSS 计数器更加简洁灵活,万一内容顺序需要调整,序号也不受影响。 有时候我们会看到某些 Dashboard 界面有数字快速滚动的效果,比如招行 App 的账户余额。这种效果怎么实现呢?本文会介绍几种方法。 JavaScript 方案 最简单的莫过于用setInterval定时器了,定期修改 DOM 内容就行。不过为了实现更平顺的动画效果,更推荐使用requestAnimationFrame: functionanimateValue(obj,start,end,duration){letstartTimestamp=null;conststep=(timestamp)=>{if(!startTimestamp)startTimestamp=timestamp;constprogress=Math.min((timestamp-startTimestamp)/duration,1);obj.innerHTML=Math.floor(progress*(end-start)+start);if(progress<1){window.requestAnimationFrame(step);}};window.requestAnimationFrame(step);}constobj=document.getElementById("value");animateValue(obj,100,0,5000); js.gif CSS @keyframes 结合 margin 这个思路比较有意思,原理是把数字排成一行,通过动画移动元素位置来显示不同位置的数字: <divclass="counter"><divclass="numbers"><div>0</div><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div></div></div> .counter{width:100px;overflow:hidden;}.numbers{width:auto;display:flex;animation:countNumber4sinfinitealternate;animation-timing-function:steps(10);}.numbersdiv{text-align:center;flex:00100px;}@keyframescountNumber{0%{margin-left:0px;}100%{margin-left:-1000px;}} keyframe.gif CSS 计数器入门版 CSS 计数器使用到以下几个属性: counter-reset - 创建或者重置计数器 counter-increment - 递增变量 content - 插入生成的内容 counter() 或 counters() 函数 - 将计数器的值添加到元素 要使用 CSS 计数器,得先用 counter-reset 创建。结合 CSS 动画@keyframes,在动画的不同阶段设置不同的递增值,就能实现这个效果: <div></div> div::after{content:counter(count);animation:counter3slinearinfinitealternate;counter-reset:count0;}@keyframescounter{0%{counter-increment:count0;}10%{counter-increment:count1;}20%{counter-increment:count2;}30%{counter-increment:count3;}40%{counter-increment:count4;}50%{counter-increment:count5;}60%{counter-increment:count6;}70%{counter-increment:count7;}80%{counter-increment:count8;}90%{counter-increment:count9;}100%{counter-increment:count10;}} CSS 计数器高配版 更进一步,如果敢用最新特性,其实有更秀的操作,那就是给 CSS 变量设置动画。这个技巧的核心就是设置 CSS 自定义属性为整数类型,这样就能像其他拥有整数类型值的 CSS 属性一样,可用于transition中了。 @property--num{syntax:'<integer>';initial-value:0;inherits:false;}div{transition:--num1s;counter-reset:numvar(--num);}div:hover{--num:10000;}div::after{content:counter(num);} 不过需要注意的是,目前只有 Chrome (或者 Chromium 内核的浏览器比如 Edge 和 Opera)支持@property语法,因此兼容性是个问题。如果你的页面只针对 Chrome(比如 Electron 应用),那就可以放心使用。否则还是用前面的保守方案吧。 小数也能玩动画 前面说的变量都要求是整数,那能不能让小数也支持这种动画呢?答案是可以的。 可以把小数转成整数。步骤原理是: 注册一个整型的 CSS 变量(即--number),指定初始值initial-value。 用calc将值取整:--integer: calc(var(--number)) @property--integer{syntax:"<integer>";initial-value:0;inherits:false;}--number:1234.5678;--integer:calc(var(--number));/*1235*/ 如果只需要提取整数部分,可以这样:--integer: max(var(--number) - 0.5, 0),连calc()都不需要了。类似方法可以提取小数部分。 /*@property--integer*/--number:1234.5678;--integer:max(var(--number)-0.5,0);/*1234*/ 完整代码: <div></div> @property--percent{syntax:"<number>";initial-value:0;inherits:false;}@property--temp{syntax:"<number>";initial-value:0;inherits:false;}@property--v1{syntax:"<integer>";initial-value:0;inherits:false;}@property--v2{syntax:"<integer>";initial-value:0;inherits:false;}div{font:80040pxmonospace;padding:2rem;transition:--percent1s;--temp:calc(var(--percent)*100);--v1:max(var(--temp)-0.5,0);--v2:max((var(--temp)-var(--v1))*100-0.5,0);counter-reset:v1var(--v1)v2var(--v2);}div::before{content:counter(v1)"."counter(v2,decimal-leading-zero)"%";} constgenNumber=()=>{document.querySelector("div").style.setProperty("--percent",Math.random());};setInterval(genNumber,2000);setTimeout(genNumber); decimal.gif 顺手点“在看”,每天早下班;转发加关注,共奔小康路~ 本文分享自微信公众号 - 1024译站(trans1024)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。