对beginPath()了解不深,导致在canvas中绘制图形时样式覆盖

1,339 阅读2分钟

写本编文章,是因为在使用 canvas 绘制图形时,遇到了一个问题:在绘制图形时,后面设置的图形样式(颜色、线宽等)覆盖了前面绘制图形的样式。通过研究,发现是对 canvas 绘制路径时的相关方法beginPath()了解不深导致的,在此记录说明,希望能为遇到同样问题的童鞋解惑!

下面直接通过例举示例说明。

通过 fillRect() 绘制矩形

const canvas_a = document.getElementById('canvas_a');
const ctx_a = canvas_a.getContext('2d');

ctx_a.fillStyle = '#2DE0A5'; // 绿色
ctx_a.fillRect(10, 10, 80, 40);

ctx_a.fillStyle = '#03a9f4'; // 蓝色
ctx_a.fillRect(10, 60, 80, 40);

image.png

通过 rect() 绘制矩形(错误的写法)

const canvas_b = document.getElementById('canvas_b');
const ctx_b = canvas_b.getContext('2d');

ctx_b.fillStyle = '#2DE0A5';  // 绿色
ctx_b.rect(10, 10, 80, 40);
ctx_b.fill();

ctx_b.fillStyle = '#03a9f4';  // 蓝色
ctx_b.rect(10, 60, 80, 40);
ctx_b.fill(); 

image.png

发现」:绘制第二个矩形时设置的样式(蓝色)覆盖了第一个矩形的样式(绿色)

这里引用《红宝书》书中相关的话说明:

  • 矩形是唯一一个可以 直接 在 2D 绘图上下文中绘制的形状。与绘制矩形相关的方法有 3 个:fillRect()、strokeRect()和 clearRect()。

  • 要绘制路径,必须首先调用 beginPath() 方法以表示要开始绘制 新路径

  • rect() 方法与 strokeRect()fillRect()的区别在于,它创建的是一条路径,而不是独立的图形。

通过 rect() 绘制矩形(正确的写法)

const canvas_c = document.getElementById('canvas_c');
const ctx_c = canvas_c.getContext('2d');
ctx_c.beginPath(); // 调用表示新路径
ctx_c.fillStyle = '#2DE0A5';
ctx_c.rect(10, 10, 80, 40);
ctx_c.fill();

ctx_c.beginPath(); // 调用表示新路径
ctx_c.fillStyle = '#03a9f4';
ctx_c.rect(10, 60, 80, 40);
ctx_c.fill();

image.png

绘制线条(错误的写法)

const canvas_x = document.getElementById('canvas_x');
const ctx_x = canvas_x.getContext('2d');
ctx_x.lineWidth = 15;

ctx_x.strokeStyle = '#2DE0A5';
ctx_x.moveTo(20, 20);
ctx_x.lineTo(120, 20);
ctx_x.stroke();

ctx_x.strokeStyle = '#03a9f4';
ctx_x.moveTo(20, 60);
ctx_x.lineTo(120, 60);
ctx_x.stroke();

image.png

绘制线条(正确的写法)

const canvas_x = document.getElementById('canvas_x');
const ctx_x = canvas_x.getContext('2d');
ctx_x.lineWidth = 15;

ctx_x.beginPath(); // 调用表示新路径
ctx_x.strokeStyle = '#2DE0A5';
ctx_x.moveTo(20, 20);
ctx_x.lineTo(120, 20);
ctx_x.stroke();

ctx_x.beginPath(); // 调用表示新路径
ctx_x.strokeStyle = '#03a9f4';
ctx_x.moveTo(20, 60);
ctx_x.lineTo(120, 60);
ctx_x.stroke(); 

image.png


至于具体原因,看到有人说是 canvas 每次的绘制会重新把整个画布上内容重新绘制一遍,待深入了解o(╥﹏╥)o !看到的大佬也欢迎解惑^v^