JavaScript学习日记 : Day30 - JavaScript动画

setInterval

使用setInterval每秒做多次的细微变化(css改变),当次数够多画面就会流畅许多:

let delay = 1000 / 次数
let timer = setInterval(() => {
    if(停止条件) clearInterval(timer);
    else 改变css
})
let start = Date.now();

  let timer = setInterval(function () {
    let timePassed = Date.now() - start;

    target.style.left = timePassed / 5 + "px";

    if (timePassed > 3000) clearInterval(timer); // 3秒後停止,
  }, 20);

open in codesandbox

requestAnimationFrame优化

setTimeout与setInterval来制作动画时,当更新的频率过高的时候是有可能导致效能低落的,因为浏览器本身有自己的FPS更新效率,如果我们设置的频率高於浏览器的,可能导致耗电还有效能的问题。

requestAnimationFrame用法与setTimeout与setInterval差不多,一样传入一个callback,不需传入秒数,会自动以浏览器的更新频率,requestAnimationFrame(callback)会回传一个唯一的requestID,可以透过呼叫 cancelAnimationFrame(requestID) 取消此动画。

let elem = document.getElementById("animate"); 
let left = 0;
let bound = false;

requestAnimationFrame(Move);

function Move() {
  if(left === 0 || left === 350) {
    bound = !bound;
  }
  (bound) ? left++ : left--;
  elem.style.left = left + 'px'; 
  window.requestAnimationFrame(Move);
}

open in codesandbox

进阶例子

基於requestAnimationFrame可以创建一个通用的动画function:

  1. duration : 动画持续的时间
  2. timing : 返回一个0~1的数字,可以在这边让动画移动有不一样的变化
  3. draw : 取得timing完成进度後,进行目标元素的移动
function animate({timing, draw, duration}) {

  let start = performance.now();

  requestAnimationFrame(function animate(time) {
    // timeFraction 从 0 增加到 1
    let timeFraction = (time - start) / duration;
    if (timeFraction > 1) timeFraction = 1;

    // 计算当前动画状态
    let progress = timing(timeFraction);

    draw(progress); // 绘制

    if (timeFraction < 1) {
      requestAnimationFrame(animate);
    }

  });
}
  • 例子一 : 等速
brick.onclick = function() {
  animate({
    duration: 2000,
    timing: function(timeFraction) {
      return timeFraction;
    },
    draw: function(progress) {
      brick.style.left = progress*500  + 'px';
    }
  });
};

open in codesandbox

以下例子只需改变timing input即可:

  • 例子二 : 次方
function quad(timeFraction) {
  return Math.pow(timeFraction, 2)
}
  • 例子三 : 圆弧
function circ(timeFraction) {
  return 1 - Math.sin(Math.acos(timeFraction));
}

<<:  【Day 27】Google Apps Script - API Blueprint 篇 - Apiary 建立专案与版本控制

>>:  【第二八天 - Flutter 开发套件之旅(上)】

在 Lubuntu 18.04 上安装 CodeBlocks IDE 17.12

写程序,弄个 IDE 真的会方便不少,如果您是要在 ubuntu 20.04 上面使用 Code::...

Day 26 - HBuilderX 与 Native.js API 读取图片

Day 26 - HBuilderX 与 Native.js API 读取图片 在 Day 25 -...

30天零负担轻松学会制作APP介面及设计【DAY 26】

大家好,我是YIYI,今天我要来检讨一下目前的问题~ 问题 第一个部分是页面,我认为可以再增加一些页...

Day12. Class Method 与 MetaClass 的观念

昨天提到的实体方法,是为了创建的物件提供方法使用,而与实体方法相对的另一个方法叫类别方法,是类别本身...

{DAY 2} 如何处理一笔数据?(上)

大家一定都听过数据分析 让我们先来看一笔实际的数据 点开kaggle上随意一笔csv档 (资料来源:...