canvas动画 (一)

1,037 阅读1分钟

1、加速度运动

这里主要是利用加速度、速度、时间、距离之间的关系

<template>
	<div id="app">
		<canvas id="canvas"></canvas>
	</div>
</template>

<script>
	export default {
  name: "App",
  mounted() {
    const eleCvas = document.getElementById("canvas");
    const cxt = eleCvas.getContext("2d");
    //初始化变量,也就是初始化圆的X轴坐标为0
    let x = 0;
    let v = 0;
    let v1 = 0;
    const a = 200;
    const t = 1/60;
    //动画循环
    (function frame() {
      window.requestAnimationFrame(frame);
      //每次动画循环都先清空画布,再重绘新的图形
      cxt.clearRect(0, 0, eleCvas.width, eleCvas.height);
      //绘制圆
      cxt.beginPath();
      cxt.arc(x, 70, 20, 0, (360 * Math.PI) / 180, true);
      cxt.closePath();
      cxt.fillStyle = "red";
      cxt.fill();
      //变量递增 假设60fps 一次1/60
      // v=v0+at 当前速度公式
      // s=v0t+2at^2 运行距离
      v1 = v + a * t;
      x =  x +  v * t + 2 * a * t * t;
      v = v1;
    })();
  }
};
</script>

<style>
	#app {
		text-align: center;
	}
	canvas {
		border: 1px solid red;
	}
</style>

将上面的加速度方向变为向左,并给一定的初速度,变成了一个减速运动,再通过临界点速度为零时静止,就可以表示个摩擦减速运动;将上面 cxt.arc(x, 70, 20, 0, (360 * Math.PI) / 180, true);中的x和70换位置就可以变成垂直加速运动

【扩展】动效循环说明

setTimeout 和 setInterval并非是专为连续循环产生的 API,所以可能无法达到流畅的动画表现,故用 requestAnimationFrame

优缺点对比

  • setTimeOut(fn,time) 和setInterval(fn,time)
    优点:动画的时间间隔可以自定义。
    缺点:隐藏浏览器标签后,会依旧运行,造成资源浪费。不能按时执行,与浏览器刷新频率不同步。

  • requestAnimationFrame(fn)
    优点:性能更优良。隐藏浏览器标签后,便不会运行。与浏览器刷新频率同步。
    缺点:动画的时间间隔无法自定义

2、圆周动动

这里的关键在于运用三角函数sin,cos,js对应Math.sin(radian)Math.cos(radian)

<template>
  <div id="app">
    <canvas id="canvas"></canvas>
  </div>
</template>

<script>
export default {
  name: "App",
  mounted() {
    const eleCvas = document.getElementById("canvas");
    const cxt = eleCvas.getContext("2d");
    // 红球半径
    const r1 = 10;
    let x1; y1;

    // 红球轨迹圆心和半径
    const x = 150;
    const y = 75;
    const r = 60;
    // 每帧运行弧度
    const interval = 0.02;
    // 初始弧度
    let currentAngle = 0;
    //动画循环
    cxt.fillStyle="red";
    (function frame() {
      window.requestAnimationFrame(frame);
      //每次动画循环都先清空画布,再重绘新的图形
      cxt.clearRect(0, 0, eleCvas.width, eleCvas.height);
      //绘制圆 
      cxt.beginPath();
      cxt.arc(x, y, r, 0, (360 * Math.PI) / 180, false);
      cxt.closePath();
      cxt.stroke();
      cxt.beginPath();
      currentAngle += interval;
      x1 = x + Math.cos(currentAngle) * r;
      y1 = y + Math.sin(currentAngle) * r;
      cxt.arc(x1, y1, r1, 0, (360 * Math.PI) / 180, false);
      cxt.closePath();
      cxt.fill();
    })();
  }
};
</script>

<style>
#app {
  text-align: center;
}
canvas {
  border: 1px solid red;
}
</style>

去掉大圆就是一个小球匀速圆周运动,将小球的圆心y坐标不变就是一个左右来回直线运动,x坐标不变就是一个上下来回直线运动; 还可用setinterval做时钟

相关