理解 Canvas的save和restore
理解 Canvas的save和restore
save()和restore()方法只会在有效范围内生效,它是绘制状态的存储器,并不是画布内容的存储器。它是基于状态记录的。
- save:用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。
- restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响。
较为细致解释
save()和restore()方法只会在有效范围内生效,它是绘制状态的存储器,并不是画布内容的存储器。它是基于状态记录的。 Canvas Context维持着绘制状态的堆栈。区分绘制状态:
- 当前矩阵变换例如:平移translate(),缩放scale(),以及旋转rotate()等
- 剪切区域clip()
- 以下属性值:
- strokeStyle,fillStyle,globalAlpha,lineWidth,lineCap,lineJoin,miterLimit,shadowOffsetX,shadowOffsetY,shadowBlur,shadowColor,globalCompositeOperation,font,textAlign,textBaseline。
- 路径和位图不是绘图状态的一部分,使用save()和restore()不会生效。路径是持久的,只能使用beginPath()方法重置,位图是画布的属性,而非上下文。
- context.save()将当前状态压入堆栈。context.restore()弹出堆栈上的顶级状态,将上下文恢复到该状态。
实际代码应用
let processNum = 0
const process = () => {
if (processNum < this.state.score) {
processNum++
}
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 600, 240)
let x = 300
let y = 170
ctx.beginPath();
ctx.arc(x, y, 122, Math.PI + Math.asin(10/66), 2 * Math.PI - Math.asin(10/66));
ctx.strokeStyle = "rgba(0, 0, 0, 0.05)";
ctx.lineWidth = 60;
ctx.lineCap = "round";
ctx.stroke();
ctx.beginPath();
let angle = processNum / 100 * (Math.PI - 2 * Math.asin(10/66)) + Math.PI + Math.asin(10/66)
ctx.arc(x, y, 122, Math.PI + Math.asin(10/66), angle);
// 渐变
var gradient=ctx.createLinearGradient(0,0,400,0);
gradient.addColorStop("0.5","rgba(85, 255, 234, 1)");
gradient.addColorStop("1","rgba(38, 123, 255, 1)");
ctx.strokeStyle = gradient;
ctx.lineWidth = 60;
ctx.lineCap = "round";
ctx.stroke();
ctx.save()
ctx.translate(178, 160)
ctx.rotate(5*Math.PI/180);
ctx.font = `bold 20px DINAlternate-Bold,DINAlternate`
ctx.fillStyle = '#FFFFFF'
ctx.fillText(0, 0,0)
ctx.restore()
ctx.save()
ctx.translate(422, 160)
ctx.rotate(-10*Math.PI/180);
ctx.font = `bold 20px DINAlternate-Bold,DINAlternate`
ctx.fillStyle = '#FFFFFF'
ctx.fillText(100, 0,0)
ctx.restore()
ctx.save()
ctx.font = `bold 100px DINAlternate-Bold,DINAlternate`
ctx.fillStyle = '#3AA7FF'
ctx.textAlign = 'center'
ctx.fillText(this.state.score, 300, 240)
// ctx.restore()
// ctx.save()
if (processNum < 100) {
requestAnimationFrame(process)
}
}
process()
canvas 在高清屏绘制模糊问题
常规绘制大概参考 解决 canvas 在高清屏中绘制模糊的问题 就可以了
但我在这个是通过 antd 引入的高清屏设置,所以通过上述方案在模拟器中正常,但在移动端显示不太正常,大量错位产生。
解决方案
统一按2倍屏幕设置canvas宽高:
<canvas width="640" height="800" style="width:320px; height:400px"></canvas>
canvas中字体、位移、半径等都是二倍即可。
写在最后
其实大部分时间都是浪费在一个冒泡泡的动画上:
然鹅我并没有写好,交给了UI去写GIF了。
但大部分代码也写好了,主要考虑效果不尽如意
本来也想在这加上那段动画效果来着,毕竟又花了一晚上学习了以下初中圆的知识[滑稽],可惜回撤找不着了