How can I animate the drawing of text on a web page?

前端 未结 4 1410
情深已故
情深已故 2020-12-02 03:08

I want to have a web page which has one centered word.

I want this word to be drawn with an animation, such that the page \"writes\" the word out the same way that

4条回答
  •  庸人自扰
    2020-12-02 03:52

    Following many tests, here is some notes. The goal is to display fast text data in the least blocking way, on DOM heavy pages requiring users interactions.

    There is of course many ways to achieve the same thing. On this example, the differences might not be obvious, it really apply to complex interfaces.

    Slowest: innerHTML and inline styling. The DOM is recalculated at each iterations. The browser is working hard to keep the train. It will fails quickly, causing memory leaks and freezes:

    setInterval(function(){
      out.innerHTML = `${Math.random() * 1000}`
    },1)

    Way better: Using textContent, requestAnimationFrame and the web animation api. This goes way smoother, it's obvious on DOM heavy pages. The user interactions won't blocks the repaints. Some repaints might be skipped, to keep the interface well responsive.

    let job
    const paint = () => {
      job = requestAnimationFrame(paint)
      out.textContent = Math.random() * 1000
      out.animate([{top: ~~(Math.random() * 220)+"px"},{top:0}],{duration: 1,iterations: 1})
    }
    
    /* Start looping -----------------------------------------*/
    requestAnimationFrame(paint)
    #out{
    position: fixed}

    On the above example, the DOM is still being recalculated for the text overflow.. We can see the debugger blinking hard. This really matter on cascading elements! This can still slows down javascript and user scrollings.

    Full power: It's possible to use css alone to refresh the data with the css content rule and css variables. The text won't then be selectable.

    let job
    const paint = () => {
      job = requestAnimationFrame(paint)
      out.setAttribute('data-before', Math.random() * 1000)
      out.animate([{top: ~~(Math.random() * 220)+"px"},{top:0}],{duration: 1,iterations: 1})
    }
    
    /* Start looping -----------------------------------------*/
    requestAnimationFrame(paint)
    #out{
      position: fixed
      
      }
    #out:before {
       content: attr(data-before)
     }

    My tests showns great improvements, the javascript engine is skipping quickly on other tasks. Sometimes it can starts a bit slower than the above example. But beside that,this doesn't blocks users scrolls, and the debugger is also liking, no more jumpings.

提交回复
热议问题