欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

js實現(xiàn)一個逐步遞增的數(shù)字動畫

 更新時間:2021年12月07日 09:33:19   作者:我就是胖虎  
可視化大屏項目使用最多的組件就是數(shù)字組件,本文主要介紹了js實現(xiàn)一個逐步遞增的數(shù)字動畫,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

背景

可視化大屏項目使用最多的組件就是數(shù)字組件,展示數(shù)據(jù)的一個變化,為了提高視覺效果,需要給數(shù)字增加一個滾動效果,實現(xiàn)一個數(shù)字到另一個數(shù)字逐步遞增的滾動動畫。

先上一個思維導圖:

實現(xiàn)類似滾輪的效果,容器固定,數(shù)字向上滾動

先列舉所有的可能的值形成一個縱向的列表,然后固定一個容器,勻速更改數(shù)字的偏移值。

下面來介紹一下這種方案的實現(xiàn),元素值從0到9一共十個值,每個數(shù)字占縱向列表的10%,所以縱向偏移值依次為為0%? —> -90%

實現(xiàn):

<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%。 但是由于設定了固定的過渡動畫時間,就會出現(xiàn)一個向反方向滾動的情況,為了解決這個問題,可以參考無縫滾動的思路

  • 在9后面復制一份0,
  • 當縱向列表滾動到9的時候,繼續(xù)滾動到復制的0
  • 滾動到復制的0的時候,把列表的偏移位置改為0,并且控制動畫時間為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}%)`
}

利用兩個元素實現(xiàn)滾動

仔細看動圖的效果,事實上在在視口只有兩個元素,一個值之前的值,一個為當前的值,滾動偏移值只需設置translateY(-100%)

具體思路:

  • 聲明兩個變量,分別存放之前的值prev,以及變化后的值cur;聲明一個變量play作為這兩個值的滾動動畫的開關(guān)
  • 使用useEffect監(jiān)聽監(jiān)聽傳入的值:如果是有效的數(shù)字,那么把沒有變化前的值賦值給prev,把當前傳入的值賦值給cur,并且設置paly為true開啟滾動動畫

下面是調(diào)整后的代碼結(jié)構(gòu):

 <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;
}

實現(xiàn)多個滾輪的向上滾動的數(shù)字組件

利用H5的requestAnimationFrame()API實現(xiàn)數(shù)字逐步遞增的動畫效果

實現(xiàn)一個數(shù)字的逐漸遞增的滾動動畫,并且要在指定時間內(nèi)完成。要看到流暢的動畫效果,就需要在更新元素狀態(tài)時以一定的頻率進行,JS動畫都是通過在很短的時間內(nèi)不停的渲染/繪制元素做到的,所以計時器一直都是Javascript動畫的核心技術(shù),關(guān)鍵就是刷新的間隔時間,刷新時間需要盡量短,這樣動畫效果才能顯得更加流暢,不卡頓;同時刷新間隔又不能太短,需要確保瀏覽器有能力渲染動畫 。
大多數(shù)電腦顯示器的刷新頻率是 60Hz,即每秒重繪 60次。因此平滑動畫的最佳循環(huán)間隔是通常是 1000ms/60,約等于16.6ms

計時器對比

  • 與 setTimeout 和 setInterval 不同,requestAnimationFrame 不需要程序員自己設置時間間隔。setTimeout 和 setInterval 的問題是精確度低。它們的內(nèi)在運行機制決定了時間間隔參數(shù)實際上只是指定了把動畫代碼添加到瀏覽器 UI 線程隊列中以等待執(zhí)行的時間。如果隊列前面已經(jīng)加入了其他任務,那動畫代碼就要等前面的任務完成后再執(zhí)行。
  • requestAnimationFrame 采用系統(tǒng)時間間隔,它會要求瀏覽器根據(jù)自己的頻率進行一次重繪,保持最佳繪制效率,不會因為間隔時間過短,造成過度繪制,增加開銷;也不會因為間隔時間太長,使用動畫卡頓不流暢,讓各種網(wǎng)頁動畫效果能夠有一個統(tǒng)一的刷新機制,從而節(jié)省系統(tǒng)資源,提高系統(tǒng)性能,改善視覺效果。
  • requestAnimationFrame 會把每一幀中的所有 DOM 操作集中起來,在一次重繪或回流中就完成,并且重繪或回流的時間間隔緊緊跟隨瀏覽器的刷新頻率。
  • requestAnimationFrame 對于隱藏或不可見元素,將不會進行重繪或回流,就意味著使用更少的 CPU、GPU 和內(nèi)存使用量。
  • requestAnimationFrame 是由瀏覽器專門為動畫提供的API,在運行時瀏覽器會自動優(yōu)化方法的調(diào)用,并且如果頁面不是激活狀態(tài)下的話,動畫會自動暫停,有效節(jié)省了CPU開銷。

requestAnimationFrame實現(xiàn)滾動動畫思路

動畫開始,記錄開始動畫的時間 startTimeRef.current

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

之后每一幀動畫,記錄從開始動畫經(jīng)過了多長時間,計算出當前幀的所到達的數(shù)字應該是多少,即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]);

針對當前每個數(shù)字位上的數(shù)字進行比較,如果有變化,進行偏移量的變化,偏移量體現(xiàn)在當前數(shù)字位上的數(shù)字與下一位數(shù)字之間的差值,這個變化每一幀都串起來形成了滾動動畫

成果展示

到此這篇關(guān)于js實現(xiàn)一個逐步遞增的數(shù)字動畫的文章就介紹到這了,更多相關(guān)js 逐步遞增數(shù)字動畫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論