save()保存当前Canvas画布状态并放在栈的最上面,可以使用restore()方法依次取出。
注意:栈是先入后出,每次restore()取出的画布状态都是最近save()的画布状态
保存的画布状态有以下这些:
当前矩阵变换。参见transform()等。
当前剪裁区域。参见clip()。
当前虚线设置。参见setLineDash()。
以及下面这些属性的值:strokeStyle,fillStyle,globalAlpha,lineWidth,lineCap,lineJoin,miterLimit,lineDashOffset,shadowOffsetX,shadowOffsetY,shadowBlur,shadowColor,globalCompositeOperation,font,textAlign,textBaseline。
例子-时钟
例子参考 https://juejin.cn/post/6986785259966857247
效果图
这里每次restore()取出的都是画布起始点移到了(300, 300)的一个画布状态
ctx.translate(300, 300); //设置中心点,此时(300, 300)成了坐标(0,0)
let canvas = document.getElementById('clock')
canvas.width = 600;
canvas.height = 600;
if(canvas.getContext) {
let ctx = canvas.getContext('2d')
drawClock(ctx)
}
function drawClock(ctx) {
setInterval(() => {
ctx.save()
console.log(ctx.canvas);
ctx.clearRect(0, 0, 600, 600)
ctx.translate(300, 300); //设置中心点,此时(300, 300)成了坐标(0,0)
ctx.save()
//画大圆
ctx.beginPath()
ctx.arc(0, 0, 100, 0, 2*Math.PI)
ctx.stroke()
ctx.closePath()
//画小圆
ctx.beginPath()
ctx.arc(0, 0, 5, 0, 2*Math.PI)
ctx.stroke()
ctx.closePath()
//获取当前时分秒
let time = new Date()
let hour = time.getHours()%12
let min = time.getMinutes()
let sec = time.getSeconds()
//时针
//顺时针旋转坐标x,y轴
ctx.rotate(2*Math.PI/12*hour + 2 * Math.PI / 12 * (min / 60) - Math.PI / 2)
ctx.beginPath()
// moveTo设置画线起点
ctx.moveTo(-10, 0)
// lineTo设置画线经过点
ctx.lineTo(40, 0)
// 设置线宽
ctx.lineWidth = 10
ctx.stroke()
ctx.closePath()
ctx.restore()
ctx.save()
// 分针
ctx.rotate(2 * Math.PI / 60 * min + 2 * Math.PI / 60 * (sec / 60) - Math.PI / 2)
ctx.beginPath()
ctx.moveTo(-10, 0)
ctx.lineTo(60, 0)
ctx.lineWidth = 5
ctx.strokeStyle = 'blue'
ctx.stroke()
ctx.closePath()
ctx.restore()
ctx.save()
//秒针
ctx.rotate(2 * Math.PI / 60 * sec - Math.PI / 2)
ctx.beginPath()
ctx.moveTo(-10, 0)
ctx.lineTo(80, 0)
ctx.strokeStyle = 'red'
ctx.stroke()
ctx.closePath()
ctx.restore()
ctx.save()
// 绘制刻度,也是跟绘制时分秒针一样,只不过刻度是死的
ctx.lineWidth = 1
for(let i = 0; i<60; i++) {
ctx.rotate(2*Math.PI/60)
ctx.beginPath()
ctx.moveTo(90, 0)
ctx.lineTo(100, 0)
ctx.stroke()
ctx.closePath()
}
ctx.restore()
ctx.save()
ctx.lineWidth = 4
for (let i = 0; i < 12; i++) {
ctx.rotate(2 * Math.PI / 12)
ctx.beginPath()
ctx.moveTo(85, 0)
ctx.lineTo(100, 0)
// ctx.strokeStyle = 'red'
ctx.stroke()
ctx.closePath()
}
ctx.restore()
ctx.restore()
}, 1000)
},