> 文档中心 > html5 Canvas 绘制基本图形 从直线图形到使用路径 - 直线、矩形、路径、多边形、复杂组合图形

html5 Canvas 绘制基本图形 从直线图形到使用路径 - 直线、矩形、路径、多边形、复杂组合图形

html5: Canvas 绘制基本图形
从绘制直线 到 路径


Jack Lee 的 CSDN 博客
邮箱 :291148484@163.com
CSDN 主页:https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343
本文地址:https://blog.csdn.net/qq_28550263/article/details/123661151

相关文章推荐:

  • Flutter框架: 使用Canvas绘制直线
  • html5: Canvas绘制曲线图形

目 录

1. Canvas 相关概念

  • 1.1 什么是Canvas
  • 1.2 Canvas坐标系
  • 1.3 Canvas元素
    • 1.3.1 基本用法
    • 1.3.2 在 TypeScript 中的用法

2. Canvas 绘制直线

  • 2.1 直线与路径:从绘制基本线段开始
    • 2.1.1 CanvasRenderingContext2D 对象的 moveTo() 方法
    • 2.1.2 CanvasRenderingContext2D 对象的 lineTo() 方法
    • 2.1.3 CanvasRenderingContext2D 对象的 stroke() 方法
  • 2.2. Canvas 绘制矩形
    • 2.2.1 通过路径绘制矩形
    • 2.2.2 通过 CanvasRenderingContext2D 对象的矩形方法
      • 2.2.2.1 rect(x, y, width, height) 方法
      • 2.2.2.2 fillRect(x, y, width, height)
      • 2.2.2.3 strokeRect(x, y, width, height)
      • 2.2.2.4 clearRect(x, y, width, height)

3 Canvas 路径

  • 3.1 什么是 Canvas 路径
  • 3.2 操作 Canvas 路径的方法
    • 3.2.1 beginPath() 方法
    • 3.2.2 closePath() 方法
    • 3.2.3 bezierCurveTo() 方法
    • 3.2.4 quadraticCurveTo() 方法
    • 3.2.5 arc() 方法
    • 3.2.6 arcTo() 方法
    • 3.2.7 ellipse() 方法
    • 3.2.8 rect() 方法
    • 3.2.9 fill() 方法
    • 3.2.10 drawFocusIfNeeded() 方法
    • 3.2.11 scrollPathIntoView() 方法
    • 3.2.12 clip() 方法
    • 3.2.13 isPointInPath() 方法
    • 3.2.14 isPointInStroke() 方法

4. Canvas实战:多边形与组合图形的绘制

  • 4.1 绘制五边形
  • 4.2 绘制一个五角星
  • 4.3 绘制房屋

1. Canvas 相关概念

1.1 什么是Canvas

Canvas是 HTML5 的 2D图形技术之一,是一门纯JavaScript操作的图形技术。另一个是2D图形技术为 SVG。这两者的区别在于:

Canvas SVG
Canvas是基于位图的,放大图形会导致失真,适用于像素处理和动态渲染 SVG是基于矢量图的,放大图形不会导致失真,但不适用于像素处理和适合静态描述
Canvas是使用JavaScript动态生成的 SVG是使用XML静态描述的
若发生修改,使用Canvas需要重绘 使用SVG需要重绘

1.2 Canvas坐标系

Canvas使用的坐标系是 W3C坐标系 这与数学中的直角坐标系中的区别在于,数学直角坐标系y轴正方向向上,而W3C坐标系中的y轴正方向向下:
在这里插入图片描述

1.3 Canvas元素

1.3.1 基本用法

Canvas 使用一个通过JavaScript 和 HTML的元素来绘制图形的方式,以下是 HTML 中的一个Canvas元素:

<canvas id="canvas" width="300" height="200"></canvas>

要操作Canvas绘图首先要获取 HTML 元素的引用,然后获取这个元素的context,需要依次使用以下方法:

方法 描述
Document.getElementById() 取HTML 元素的引用
getContext() 获取这个元素的context,图像稍后将在此被渲染。

如获取上面id属性值为 canvas的上下文对象(context):

const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');

在 HTML 中,你需要指定canvas元素的宽度和高度作为你的画布大小,宽度和高度都为纯数字。

后文默认使用变量名 cts 表示一个已经获取的Canvas上下文对象(CanvasRenderingContext2D)

1.3.2 在 TypeScript 中的用法

在TypeScript中你需要指定类型。在这里,getElementById()方法返回的类型应该被断言为 HTMLCanvasElement 而非直接断言成普通的 HTMLElement
HTMLCanvasElement 接口提供用于操作元素布局和表示的属性和方法。HTMLCanvasElement 接口还继承了HTMLElement 接口的属性和方法。

<canvas id="canvas" width="300" height="200" ></canvas><script lang="ts">  let canvas = document.getElementById("canvas") as HTMLCanvasElement;  let ctx = canvas.getContext("2d") as CanvasRenderingContext2D;</script>

2. Canvas 绘制直线

2.1 直线与路径:从绘制基本线段开始

不同于 SVG, 只支持两种形式的图形绘制:矩形路径(由一系列点连成的直线段)。所有其他类型的图形都是通过一条或者多条路径组合而成的。不过,我们拥有众多路径生成的方法让复杂图形的绘制成为了可能。

我们可以使用以下两个方法来配合绘制直线:

方法 描述 说明
moveTo(x, y) 将一个新的子路径的起始点移动到(x,y)坐标 -
lineTO(x, y) 使用直线连接子路径的终点到x,y坐标的方法 并不会真正地绘制
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");ctx.beginPath();ctx.moveTo(50,50);ctx.lineTo(200, 50);ctx.stroke();

2.1.1 CanvasRenderingContext2D 对象的 moveTo() 方法

将一个 新的子路径的起始点 移动到(x,y)坐标的方法。

语法

void ctx.moveTo(x, y);

2.1.2 CanvasRenderingContext2D 对象的 lineTo() 方法

使用直线连接子路径的终点到x,y坐标的方法(并不会真正地绘制)

语法

void ctx.lineTo(x, y);

参数

参数 描述
x 点的 x 轴。
y 点的 y 轴。

2.1.3 CanvasRenderingContext2D 对象的 stroke() 方法

使用非零环绕规则,根据当前的画线样式,绘制当前或已经存在的路径的方法。

语法

void ctx.stroke();void ctx.stroke(path);

参数

参数 描述 说明
path 绘制Path2D的路径 Path2D对象 用于声明路径

2.2. Canvas 绘制矩形

2.2.1 通过绘制直线的方法绘制矩形

ctx.beginPath();ctx.strokeStyle = 'red';ctx.moveTo(0,0);ctx.lineTo(160,0);ctx.lineTo(160,100);ctx.lineTo(0,100);ctx.lineTo(0,0);ctx.stroke();

效果如下:
在这里插入图片描述

2.2.2 通过 CanvasRenderingContext2D 对象的矩形方法

2.2.2.1 rect(x, y, width, height) 方法

创建矩形路径的方法,矩形的起点位置是 (x, y) ,尺寸为 width 和 height。矩形的4个点通过直线连接,子路径做为闭合的标记,所以你可以填充或者描边矩形。

语法
void ctx.rect(x, y, width, height);
例如
ctx.beginPath();ctx.rect(10, 30, 200, 100);ctx.fill();

效果如下:
在这里插入图片描述


2.2.2.2 fillRect(x, y, width, height)

CanvasRenderingContext2D.fillRect() 函数是Canvas 2D API 绘制填充矩形的方法。当前渲染上下文中的fillStyle 属性决定了对这个矩形对的填充样式。
这个方法是直接在画布上绘制填充,并不修改当前路径,所以在这个方法后面调用 fill() 或者stroke()方法并不会对这个方法有什么影响。

语法

void ctx.fillRect(x, y, width, height);

参数:

  • x:矩形起始点的 x 轴坐标。
  • y:矩形起始点的 y 轴坐标。
  • width:矩形的宽度。
  • height:矩形的高度。

fillRect()方法绘制一个填充了内容的矩形,这个矩形的开始点(左上点)在(x, y) ,它的宽度和高度分别由widthheight 确定,填充样式由当前的fillStyle 决定。

例如

ctx.fillStyle = 'yellow';ctx.fillRect(60, 20, 200, 100);

效果如下:
在这里插入图片描述


2.2.2.3 strokeRect(x, y, width, height)

该方法使用当前的绘画样式,描绘一个起点在 (x, y) 、宽度为 w 、高度为 h 的矩形的方法。

语法

void ctx.strokeRect(x, y, width, height);

例如

ctx.shadowColor = '#5F9CFA';ctx.shadowBlur = 30;ctx.lineJoin = 'bevel';ctx.lineWidth = 15;ctx.strokeStyle = '#5FFA7A';ctx.strokeRect(30, 30, 90, 90);

效果如下:
在这里插入图片描述


2.2.2.4 clearRect(x, y, width, height)

该方法通过把像素设置为透明以达到擦除一个矩形区域的目的。

语法

void ctx.clearRect(x, y, width, height);
参数 描述
x 矩形起点的 x 轴坐标。
y 矩形起点的 y 轴坐标。
width 矩形的宽度。
height 矩形的高度。

例如

除整个画布:

ctx.clearRect(0, 0, canvas.width, canvas.height);

清除画布一个区域显现出矩形:

// 绘制背景色ctx.beginPath();ctx.fillStyle = '#eca601';ctx.fillRect(0, 0, canvas.width, canvas.height);// 绘制矩形清除区域ctx.clearRect(10, 10, 120, 100);

效果如下:
在这里插入图片描述

3 Canvas 路径

3.1 什么是 Canvas 路径

在Canvas中除了下一节中的矩形提供了直接绘制方法,其它的所有Canvas基本图形,包括上一小节中的直线,以及圆形、弧线、贝塞尔曲线,都是以路径为基础进行绘制的。

3.2 操作 Canvas 路径的方法

1. 操作路径

方法 描述 说明
beginPath() 清空子路径列表开始一个新的路径。 当你想创建一个新的路径时,调用此方法。
closePath() 使笔点返回到当前子路径的起始点。它尝试从当前点到起始点绘制一条直线。 如果图形已经是封闭的或者只有一个点,那么此方法不会做任何操作。
moveTo() 将一个新的子路径的起始点移动到(x,y)坐标。 参见 2.1.1 节
lineTo() 使用直线连接子路径的最后的点到x,y坐标。 参见 2.1.2 节
bezierCurveTo() 添加一个3次贝赛尔曲线路径。该方法需要三个点。 第一、第二个点是控制点,第三个点是结束点。起始点是当前路径的最后一个点,绘制贝赛尔曲线前,可以通过调用 moveTo() 进行修改。
quadraticCurveTo() 添加一个2次贝赛尔曲线路径。
arc() 绘制一段圆弧路径, 圆弧路径的圆心在 (x, y) 位置,半径为 r ,根据anticlockwise (默认为顺时针)指定的方向从 startAngle 开始绘制,到 endAngle 结束。
arcTo() 根据控制点和半径绘制圆弧路径,使用当前的描点(前一个moveTo或lineTo等函数的止点)。根据当前描点与给定的控制点1连接的直线,和控制点1与控制点2连接的直线,作为使用指定半径的圆的切线,画出两条切线之间的弧线路径。
ellipse() 添加一个椭圆路径,椭圆的圆心在(x,y)位置,半径分别是radiusX 和 radiusY ,按照anticlockwise (默认顺时针)指定的方向,从 startAngle 开始绘制,到 endAngle 结束。 实验中的功能
rect() 创建一个矩形路径,矩形的起点位置是 (x, y) ,尺寸为 width 和 height。
stroke() 使用非零环绕规则,根据当前的画线样式,绘制当前或已经存在的路径的方法。 参见 2.1.3节

2. 绘制路径

方法 描述 说明
fill() 使用当前的样式填充子路径。
stroke() 使用当前的样式描边子路径。
drawFocusIfNeeded() 如果给定的元素获取了焦点,那么此方法会在当前的路径绘制一个焦点。
scrollPathIntoView() 将当前或给定的路径滚动到窗口。
clip() 从当前路径创建一个剪切路径。在 clip() 调用之后,绘制的所有信息只会出现在剪切路径内部。
isPointInPath() 判断当前路径是否包含检测点。
isPointInStroke() 判断检测点是否在路径的描边线上。

3.2.1 beginPath() 方法

清空子路径列表开始一个新的路径。当你想创建一个新的路径时,调用此方法。

语法
void ctx.beginPath();
例如
// 第一条路径ctx.beginPath();ctx.strokeStyle = 'blue';ctx.moveTo(30,30);ctx.lineTo(0,200);ctx.stroke();// 第二条路径ctx.beginPath();ctx.strokeStyle = '#FE5B5C';ctx.moveTo(30,30);ctx.lineTo(120,120);ctx.stroke();

效果如下:
在这里插入图片描述

效果图(其中边框是为了展示canvas画布区域有意添加上去的)

3.2.2 closePath() 方法

该方法 将笔点返回到当前子路径起始点 。它尝试从当前点到起始点绘制一条直线。 如果图形已经是封闭的或者只有一个点,那么此方法不会做任何操作。

语法
void ctx.closePath();
例子
不使用该方法时:
ctx.beginPath();ctx.strokeStyle = 'blue';ctx.moveTo(0,0);ctx.lineTo(200,20);ctx.lineTo(120,120);ctx.stroke();

效果如下:
在这里插入图片描述

效果图(其中边框是为了展示canvas画布区域有意添加上去的)

使用该方法返回到当前子路径起始点后:
ctx.beginPath();ctx.strokeStyle = 'blue';ctx.moveTo(0,0);ctx.lineTo(200,20);ctx.lineTo(120,120);ctx.closePath(); // 绘制三角形的最后一条线ctx.stroke();

效果如下:
在这里插入图片描述

效果图(其中边框是为了展示canvas画布区域有意添加上去的)

3.2.3 bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) 方法

该方法用于绘制三次贝赛尔曲线路径。

贝塞尔曲线它是依据四个位置任意的点坐标绘制出的一条光滑曲线。它通过控制 曲线上的四个点起始点终止点 以及 两个相互分离的中间点 )来创造、编辑图形。

在这里插入图片描述

其中起重要作用的是位于曲线中央的控制线。这条线是虚拟的,中间与贝塞尔曲线交叉,两端是控制端点。移动两端的端点时贝塞尔曲线改变曲线的曲率(弯曲的程度);移动中间点(也就是移动虚拟的控制线)时,贝塞尔曲线在起始点和终止点锁定的情况下做均匀移动。

语法
void ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
参数 描述
cp1x 第一个控制点的 x 轴坐标。
cp1y 第一个控制点的 y 轴坐标。
cp2x 第二个控制点的 x 轴坐标。
cp2y 第二个控制点的 y 轴坐标。
x 结束点的 x 轴坐标。
y 结束点的 y 轴坐标。

例如:

ctx.beginPath();ctx.moveTo(20,20);ctx.bezierCurveTo(230, 30, 150, 60, 50, 100);ctx.stroke();// 绘制相关点ctx.fillStyle = 'blue';ctx.fillRect(20, 20, 10, 10);// 起点ctx.fillRect(50, 100, 10, 10);// 终点ctx.fillStyle = 'red';ctx.fillRect(230, 30, 10, 10);// 控制点1ctx.fillRect(150, 70, 10, 10);// 控制点2

效果如下:
在这里插入图片描述

3.2.4 quadraticCurveTo(cpx, cpy, x, y) 方法

该方法是 Canvas 2D API 新增 二次贝塞尔曲线路径 的方法。它需要2个点。 第一个点是控制点,第二个点是终点起始点当前路径最新的点,当创建二次贝赛尔曲线之前,可以使用 moveTo() 方法进行改变。

语法
void ctx.quadraticCurveTo(cpx, cpy, x, y);
参数 描述
cpx 控制点的 x 轴坐标。
cpy 控制点的 y 轴坐标。
x 终点的 x 轴坐标。
y 终点的 y 轴坐标。
例如
ctx.beginPath();ctx.moveTo(50, 20);ctx.quadraticCurveTo(230, 30, 50, 100);ctx.stroke();ctx.fillStyle = 'blue';ctx.beginPath();ctx.arc(50, 20, 5, 0, 2 * Math.PI);   // 起始点ctx.arc(50, 100, 5, 0, 2 * Math.PI);  // 终点ctx.fill();ctx.fillStyle = 'red';ctx.beginPath();ctx.arc(230, 30, 5, 0, 2 * Math.PI); // 控制点ctx.fill();

效果如下:
在这里插入图片描述

3.2.5 arc(x, y, radius, startAngle, endAngle, anticlockwise) 方法

该方法用于绘制圆弧路径。 圆弧路径的圆心在 (x, y) 位置,半径为 r ,根据anticlockwise (默认为顺时针)指定的方向从 startAngle 开始绘制,到 endAngle 结束。

语法
void ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
参数 描述
x 圆弧中心(圆心)的 x 轴坐标。
y 圆弧中心(圆心)的 y 轴坐标。
radius 圆弧的半径。
startAngle 圆弧的起始点, x轴方向开始计算,单位以弧度表示。
endAngle 圆弧的终点, 单位以弧度表示。
anticlockwise 可选的Boolean值 ,如果为 true,逆时针绘制圆弧,反之,顺时针绘制。

例如:

ctx.beginPath();ctx.arc(50, 50, 50, 0, 2 * Math.PI);ctx.stroke();

效果如下:
在这里插入图片描述

3.2.6 arcTo(x1, y1, x2, y2, radius) 方法

该方法根据控制点和半径绘制圆弧路径,使用当前的描点(前一个moveTo或lineTo等函数的止点)。根据当前描点与给定的控制点1连接的直线,和控制点1与控制点2连接的直线,作为使用指定半径的圆的切线,画出两条切线之间的弧线路径。

语法
void ctx.arcTo(x1, y1, x2, y2, radius);
参数 描述
x1 第一个控制点的 x 轴坐标。
y1 第一个控制点的 y 轴坐标。
x2 第二个控制点的 x 轴坐标。
y2 第二个控制点的 y 轴坐标。
radius 圆弧的半径。
例如
ctx.setLineDash([])ctx.beginPath();ctx.moveTo(150, 20);ctx.arcTo(150,100,50,20,30);ctx.stroke();ctx.fillStyle = 'blue';ctx.fillRect(150, 20, 10, 10);  // 基本点ctx.fillStyle = 'red';ctx.fillRect(150, 100, 10, 10); // 控制点1ctx.fillRect(50, 20, 10, 10);  // 控制点2ctx.setLineDash([5,5])ctx.moveTo(150, 20);ctx.lineTo(150,100);ctx.lineTo(50, 20);ctx.stroke();ctx.beginPath();ctx.arc(120,38,30,0,2*Math.PI);ctx.stroke();

效果如下:
在这里插入图片描述

3.2.7 ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise) 方法

语法
void ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);
参数 描述
x 椭圆圆心的 x 轴坐标。
y 椭圆圆心的 y 轴坐标。
radiusX 椭圆长轴的半径。
radiusY 椭圆短轴的半径。
rotation 椭圆的旋转角度,以弧度表示(非角度度数)。
startAngle 将要绘制的起始点角度,从 x 轴测量,以弧度表示(非角度度数)。
endAngle 椭圆将要绘制的结束点角度,以弧度表示(非角度度数)。
anticlockwise 可选的 Boolean 选项,如果为 true,逆时针方向绘制椭圆 (逆时针), 反之顺时针方向绘制。

3.2.8 fill() 方法

该方法根据当前的填充样式,填充当前或已存在的路径的方法。采取非零环绕或者奇偶环绕规则。

语法
void ctx.fill();void ctx.fill(fillRule);void ctx.fill(path, fillRule);
参数
参数 描述 说明
fillRule 一种算法,决定点是在路径内还是在路径外。 允许的值:
"nonzero": 非零环绕规则, 默认的规则。
"evenodd": 奇偶环绕规则。
path 需要填充的Path2D 路径。 -
例子
ctx.beginPath();ctx.strokeStyle = 'blue';ctx.moveTo(0,0);ctx.lineTo(200,90);ctx.lineTo(120,120);ctx.closePath();ctx.stroke();ctx.fill();

效果如下:
在这里插入图片描述

3.2.10 drawFocusIfNeeded() 方法

该方法用来给 当前路径特定路径 绘制焦点的方法,如果给定的元素获取了焦点。

语法
void ctx.drawFocusIfNeeded(element);void ctx.drawFocusIfNeeded(path, element);
参数 描述
element 是否需要设置焦点的元素。
path Path2D 路径。
例如
<canvas id="canvas" width="300" height="200" >  <input id="button" type="range" min="1" max="12"></canvas><script lang="ts">let canvas = document.getElementById("canvas") as HTMLCanvasElement;let ctx = canvas.getContext("2d") as CanvasRenderingContext2D;let button = document.getElementById("button") as HTMLElement ;</script>

效果如下:
在这里插入图片描述

3.2.11 scrollPathIntoView() 方法

该方法将当前或给定的路径滚动到窗口的方法。类似于 Element.scrollIntoView()

语法
void ctx.scrollPathIntoView();void ctx.scrollPathIntoView(path);
参数 描述
path 使用的Path2D 路径。
例如
ctx.beginPath();ctx.fillRect(10, 10, 30, 30);ctx.scrollPathIntoView();

3.2.12 clip() 方法

语法
void ctx.clip();void ctx.clip(fillRule);void ctx.clip(path, fillRule);
参数 描述 说明
fillRule 这个算法判断一个点是在路径内还是在路径外。 允许的值:
“nonzero”: 非零环绕原则,默认的原则。
“evenodd”: 奇偶环绕原则。
path 需要剪切的 Path2D 路径。 -
例如
ctx.beginPath();ctx.arc(100, 100, 50, 0, Math.PI*2, false);ctx.clip();ctx.fillRect(0, 0, 100,100);

效果如下:
在这里插入图片描述

3.2.13 isPointInPath() 方法

语法
boolean ctx.isPointInPath(x, y);boolean ctx.isPointInPath(x, y, fillRule);boolean ctx.isPointInPath(path, x, y);boolean ctx.isPointInPath(path, x, y, fillRule);
参数 描述 说明
x 检测点的X坐标
y 检测点的Y坐标
fillRule 用来决定点在路径内还是在路径外的算法。 允许的值:
“nonzero”: 非零环绕规则 ,默认的规则。
“evenodd”: 奇偶环绕原则 。
path Path2D应用的路径。
返回值

一个Boolean值:

返回值 描述
true 当检测点包含在当前或指定的路径内时
false 没有检测到时
例子
ctx.rect(50, 50, 50, 50);ctx.stroke();let _ = ctx.isPointInPath(10, 10)console.log(_); // true

控制台输出为:true
效果如下:
在这里插入图片描述

3.2.14 isPointInStroke() 方法

语法
boolean ctx.isPointInStroke(x, y);boolean ctx.isPointInStroke(path, x, y);
参数 描述
x 检测点的X坐标。
y 检测点的Y坐标。
path Path2D 路径。
返回值

一个Boolean值:

返回值 描述
true 当这个点在路径的描边线上时
false 不在路径的描边线上时
例子
ctx.rect(50, 50, 50, 50);ctx.stroke();let _ = ctx.isPointInStroke(10, 10)console.log(_); // false

控制台输出为:false
效果如下:
在这里插入图片描述


4. Canvas实战:多边形与组合图形的绘制

4.1 绘制五边形

ctx.beginPath();ctx.lineWidth = 5;ctx.strokeStyle = 'blue';ctx.moveTo(100, 0); ctx.lineTo(195, 69);ctx.lineTo(159, 181);ctx.lineTo(41, 181);ctx.lineTo(5, 69);ctx.closePath();ctx.stroke(); 

效果如下:
在这里插入图片描述

4.2 绘制一个五角星

ctx.beginPath();ctx.lineWidth = 5;ctx.strokeStyle = 'blue';ctx.beginPath(); ctx.moveTo(100, 0);ctx.lineTo(159, 181);ctx.lineTo(5, 69);ctx.lineTo(195, 69);ctx.lineTo(41, 181); ctx.closePath();ctx.stroke();

效果如下:
在这里插入图片描述

4.3 绘制房屋

// 线条宽度ctx.lineWidth = 5;ctx.beginPath();// 绘制屋顶ctx.moveTo(50, 95);ctx.lineTo(150, 20);ctx.lineTo(250, 95);ctx.closePath();ctx.stroke();ctx.strokeRect(100, 95, 100, 100); // 绘制墙ctx.fillRect(130, 135, 40, 60);   // 绘制门

效果如下:
在这里插入图片描述