文章目录
一、canvas动画
1.1 canvas绘图都是通过javascript 去操控的,如要实现一些交互性动画是相当容易的。那canvas是如何做一些基本动画的?
◼ canvas可能最大的限制就是图像一旦绘制出来,它就是一直保持那样了。
◼ 如需要执行动画,不得不对画布上所有图形进行一帧一帧的重绘(比如在1秒绘60帧就可绘出流畅的动画了)。
◼ 为了实现动画,我们需要一些可以定时执行重绘的方法。然而在canvas中有三种方法可以实现:分别为 setinterval 、 settimeout 和 requestanimationframe 三种方法来定期执行指定函数进行重绘。
1.2 canvas 画出一帧动画的基本步骤(如要画出流畅动画,1s 需绘60帧):
◼ 第一步:用 clearrect 方法清空 canvas ,除非接下来要画的内容会完全充满 canvas(例如背景图),否则你需要清空所有。
◼ 第二步:保存 canvas 状态,如果加了 canvas 状态的设置(样式,变形之类的),又想在每画一帧之时都是原始状态的话,
你需要先保存一下。
◼ 第三步:绘制动画图形(animated shapes) ,即绘制动画中的一帧。
◼ 第四步:恢复 canvas 状态,如果已经保存了 canvas 的状态,可以先恢复它,然后重绘下一帧。
二、canvas-绘制秒针-setinterval实现
2.1 settimout定时器的缺陷
◼ settimeout定时器不是非常精准的,因为settimeout的回调函数是放到了宏任务中等待执行。
◼ 如果微任务中一直有未处理完成的任务,那么settimeout的回调函数就有可能不会在指定时间内触发回调。
◼ 如果想要更加平稳和更加精准的定时执行某个任务的话,可以使用requestanimationframe函数。
<!doctype html>
<html lang="zh-ch">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
padding: 100px;
margin: auto;
background-image: url(../images/grid.png);
}
canvas {
background-color: rgba(255, 0, 0, 0.1);
}
</style>
</head>
<body>
<!-- 如果不给宽高 默认宽300px 高150px -->
<canvas id="box" width="300" height="300">
您的浏览器不兼容canvas,请升级浏览器
</canvas>
<script>
// 这个函数就是动画的一帧
function draw(ctx, count) {
// 清空画布
ctx.clearrect(0, 0, 300, 300)
ctx.save()
// 绘图
ctx.translate(100, 100)
// math.pi * 2 圆
// math.pi * 2 / 60 把圆分为60份
ctx.rotate(math.pi * 2 / 60 * count)
ctx.linewidth = 6
ctx.linecap = 'round'
ctx.strokestyle = 'green'
ctx.beginpath()
ctx.moveto(0, 0)
ctx.lineto(0, -80)
ctx.stroke()
ctx.restore()
}
window.onload = function() {
const canvasel = document.getelementbyid('box')
if (!canvasel.getcontext) return
let ctx = canvasel.getcontext('2d')
let count = 0
draw(ctx, count)
setinterval(() => {
count++
if (count >= 60) {
count = 0
}
draw(ctx, count)
}, 1000);
}
</script>
</body>
</html>
三、canvas-绘制秒针–requestanimationframe实现
3.1 requestanimationframe函数
◼ 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用该函数的回调函数来更新动画。
◼ 该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
◼ 若想在浏览器下次重绘之前继续更新下一帧动画,那么在回调函数自身内必须再次调用 requestanimationframe()
◼ 通常每秒钟回调函数执行 60 次左右,也有可能会被降低。
<!doctype html>
<html lang="zh-ch">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
padding: 100px;
margin: auto;
background-image: url(../images/grid.png);
}
canvas {
background-color: rgba(255, 0, 0, 0.1);
}
</style>
</head>
<body>
<!-- 如果不给宽高 默认宽300px 高150px -->
<canvas id="box" width="300" height="300">
您的浏览器不兼容canvas,请升级浏览器
</canvas>
<script>
// 这个函数就是动画的一帧
function draw(ctx) {
let second = new date().getseconds()
ctx.clearrect(0, 0, 300, 300)
ctx.save()
ctx.translate(100, 100)
ctx.rotate(math.pi * 2 / 60 * second)
ctx.linewidth = 6
ctx.linecap = 'round'
ctx.strokestyle = 'green'
ctx.beginpath()
ctx.moveto(0, 0)
ctx.lineto(0, -80)
ctx.stroke()
ctx.restore()
requestanimationframe(() => {
draw(ctx)
})
}
window.onload = function() {
const canvasel = document.getelementbyid('box')
if (!canvasel.getcontext) return
let ctx = canvasel.getcontext('2d')
requestanimationframe(() => {
draw(ctx)
})
}
</script>
</body>
</html>
发表评论