Canvas 绘制形状
Canvas 绘制形状
绘制矩形
fillRect(x, y, width, height)
: 绘制一个填充的矩形。x
: 矩形起始点的 x 轴坐标y
: 矩形起始点的 y 轴坐标width
: 矩形的宽度。正值在右侧,负值在左侧。height
: 矩形的高度。正值在下,负值在上。
strokeRect(x, y, width, height)
: 绘制一个矩形的边框。x
: 矩形起始点的 x 轴坐标y
: 矩形起始点的 y 轴坐标width
: 矩形的宽度。正值在右侧,负值在左侧。height
: 矩形的高度。正值在下,负值在上。
clearRect(x, y, width, height)
: 清除指定矩形区域,让清除部分完全透明。x
: 矩形起始点的 x 轴坐标y
: 矩形起始点的 y 轴坐标width
: 矩形的宽度height
: 矩形的高度
<canvas id="drawRectangleCanvas">
function draw() {
var canvas = document.getElementById('drawRectangleCanvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
// 在坐标 (25, 25) 处,绘制一个宽 100px 高 100px 的正方形(矩形)
ctx.fillRect(25, 25, 100, 100);
// 在坐标 (45, 45) 处,清除一个宽 60px 高 60px 的正方形(矩形)
ctx.clearRect(45, 45, 60, 60);
// 在坐标 (50, 50) 处,绘制一个宽 50px 高 50px 的正方形(矩形)边框
ctx.strokeRect(50, 50, 50, 50);
}
}
draw()
绘制路径
相关API:
beginPath()
: 新建路径。通过清空子路径列表开始一个新路径。closePath()
: 闭合路径。将笔点从当前点返回到当前子路径起始点,形成闭合区域。stroke()
: 对路径进行描边。使用非零环绕规则,根据当前的画线样式,绘制当前或已经存在的路径。fill(fillRule)
: 路径填充。采取非零(Nonzero Rule)环绕或者奇偶(Even-odd Rule)环绕规则。fillRule
nonzero
: 默认规则,非零(Nonzero Rule)环绕规则: 路径包围的区域任意点P向外做一条射线,环绕数为 0,如果相交的边是从左向右环绕数【减1】,从右向左环绕数【加1】,环绕数不为零填充,反之不填充。evenodd
: 奇偶(Even-odd Rule)环绕规则:路径包围的区域任意点P向外做一条射线,如果相交的边总数是奇数填充,反之不填充。
绘制步骤:
生成路径
beginPath()
。本质上,路径由多个子路径构成,这些子路径都在一个列表中,所有的子路径(线、弧形等)构成图形。beginPath()
调用之后,子路径列表将会清空重置,重新绘制新的图形。提示
当前路径为空时,即调用
beginPath()
之后,或者 Canvas 刚创建的时候,第一条路径构造命令通常被视为moveTo()
调用函数指定绘制路径。
闭合路径
closePath()
,并不是必需的。closePath()
会通过绘制一条从当前点到开始点的直线来闭合图形。如果图像已闭合,则当前点为开始点。提示
调用
fill()
进行路径填充,没有闭合的形状将会自动闭合,不需要调用closePath()
闭合路径。但是调用stroke()
进行路径描边时,不会自动闭合路径。
moveTo() 移动笔触
moveTo(x, y)
: 将笔触移动到指定的坐标 (x, y) 上,不创建线条。
当 Canvas 初始化或者使用 beginPath()
新建路径之后,通常会使用 moveTo()
设置笔触起点。同时,也可以绘制不连续的路径。
lineTo() 绘制直线
lineTo(x, y)
: 绘制一条从当前位置到指定坐标 (x, y) 位置的直线。
rect() 绘制矩形
rect(x, y, width, height)
: 绘制矩形路径。从矩形起点坐标 (x, y) 开始,绘制出宽为 width 、高为 height 的矩形路径。
x
: 矩形起点的 x 轴坐标。y
: 矩形起点的 y 轴坐标width
: 矩形的宽度。height
: 矩形的高度。
acr() / arcTo() 绘制圆弧
arc(x, y, radius, startAngle, endAngle, anticlockwise)
: 绘制圆弧。绘制圆心在坐标 (x, y) 上,半径为 radius ,根据 anticlockwise (默认为顺时针)指定的方向从圆弧开始角度 startAngle 开始,到圆弧结束角度 endAngle 结束。x
: 圆弧中心(圆心)的 x 轴坐标。y
: 圆弧中心(圆心)的 y 轴坐标。radius
: 圆弧的半径。startAngle
: 圆弧的起始点,x 轴方向开始计算,单位以弧度表示。endAngle
: 圆弧的终点,单位以弧度表示。anticlockwise
: 可选Boolean
值。如果为 true,逆时针绘制圆弧,反之,顺时针绘制。
<canvas id="drawArcCanvasByArc">
var canvas = document.getElementById('drawArcCanvasByArc'); var ctx = canvas.getContext('2d'); for (let i = 0; i < 4; i++) { for (let j = 0; j < 3; j++) { ctx.beginPath(); var x = 25 + j * 50; // 圆弧中心(圆心)的 x 轴坐标 var y = 25 + i * 50; // 圆弧中心(圆心)的 y 轴坐标 var radius = 20; // 圆弧的半径 var startAngle = 0; // 圆弧的起始点,x 轴方向开始计算,单位以弧度表示 var endAngle = Math.PI + (Math.PI * j) / 2; // 圆弧的终点,单位以弧度表示 var clockwise = i % 2 == 0 ? false : true; // 指定绘制方向:顺时针 / 逆时针 // 绘制圆弧 ctx.arc(x, y, radius, startAngle, endAngle, clockwise); if (i > 1) { ctx.fill(); } else { ctx.stroke(); } } }
arcTo(x1, y1, x2, y2, radius)
: 根据控制点 (x1, y1) (x2, y2) 以及半径绘制圆弧。根据当前锚点(为当前路径的最新点,可使用moveTo()
方法进行改变)和控制点1 (x1, y1)的直线 与 控制点1 (x1, y1)和控制点(x2, y2)的直线,作为指定半径 radius 的圆的切线,绘制出两条切线之间的弧线路径。x1
: 第一个控制点的 x 轴坐标。y1
: 第一个控制点的 y 轴坐标。x2
: 第一个控制点的 x 轴坐标。y2
: 第一个控制点的 y 轴坐标。radius
: 圆弧的半径。
<canvas id="drawArcCanvasByArcTo">
var canvas = document.getElementById('drawArcCanvasByArcTo'); var ctx = canvas.getContext('2d'); ctx.setLineDash([]); // 在填充线时使用虚线模式 ctx.beginPath(); ctx.moveTo(150, 20); // 锚点 (152, 20) // 绘制圆弧 ctx.arcTo(150, 100, 50, 20, 30); // 控制点1 (150, 100) 、 控制点2 (50, 20) 、 圆弧半径 30 ctx.stroke(); ctx.fillStyle = 'blue'; // 标识锚点(150, 20) - 在坐标 (150, 20) 上绘制一个宽 10px 高 10px 的正方形(矩形) ctx.fillRect(150, 20, 10, 10); ctx.fillStyle = 'red'; // 标识控制点1 (150, 100) - 在坐标 (150, 100) 上绘制一个宽 10px 高 10px 的正方形(矩形) ctx.fillRect(150, 100, 10, 10); // 标识控制点2 (50, 20) - 在坐标 (50, 20) 上绘制一个宽 10px 高 10px 的正方形(矩形) ctx.fillRect(50, 20, 10, 10); ctx.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();
quadraticCurveTo() 二次贝塞尔曲线
quadraticCurveTo(cp1x, cp1y, x, y)
: 绘制二次贝塞尔曲线。它需要两个点,控制点 (cp1x, cp1y) 与 终点 (x, y) 。起始点是当前路径最新的点,当创建二次贝赛尔曲线之前,可以使用 moveTo()
方法进行改变。
cp1x
: 控制点的 x 轴坐标。cp1y
: 控制点的 y 轴坐标。x
: 终点的 x 轴坐标。y
: 终点的 y 轴坐标。
<canvas id="drawBezierCurveCanvasByQuadraticCurveTo" width="300" height="300">
const canvas = document.getElementById('drawBezierCurveCanvasByQuadraticCurveTo');
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(50, 20); // 锚点 (50, 20)
// 绘制二次贝塞尔曲线:控制点 (230, 30) 、 终点 (50, 100)
ctx.quadraticCurveTo(230, 30, 50, 100);
ctx.stroke(); // 路径描边
// 标识开始锚点 (50, 20) 以及终点 (50, 100)
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();
// 标识控制点 (230, 30)
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(230, 30, 5, 0, 2 * Math.PI);
ctx.fill();
// 绘制对话气泡
ctx.beginPath();
ctx.moveTo(75, 175);
ctx.quadraticCurveTo(25, 175, 25, 212.5);
ctx.quadraticCurveTo(25, 250, 50, 250);
ctx.quadraticCurveTo(50, 270, 30, 275);
ctx.quadraticCurveTo(60, 270, 65, 250);
ctx.quadraticCurveTo(125, 250, 125, 212.5);
ctx.quadraticCurveTo(125, 175, 75, 175);
ctx.stroke();
bezierCurveTo() 三次贝塞尔曲线
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
: 绘制三次贝塞尔曲线。它需要三个点:控制点1 (cp1x, cp1y) 、控制点1 (cp2x, cp2y) 、结束点 (x, y) 。起始点是当前路径的最后一个点,绘制贝赛尔曲线前,可以通过调用 moveTo()
进行修改。
cp1x
: 第一个控制点的 x 轴坐标。cp1y
: 第一个控制点的 y 轴坐标。cp2x
: 第二个控制点的 x 轴坐标。cp2y
: 第二个控制点的 y 轴坐标。x
: 结束点的 x 轴坐标。y
: 结束点的 y 轴坐标。
<canvas id="drawBezierCurveCanvasByBezierCurveTo" width="300" height="300">
var canvas = document.getElementById("drawBezierCurveCanvasByBezierCurveTo");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(50,20); // 锚点 (50, 20)
// 绘制三次贝塞尔曲线:控制点1 (230, 30)、 控制点2 (150, 60)、 终点 (50, 100)
ctx.bezierCurveTo(230, 30, 150, 60, 50, 100);
ctx.stroke();
ctx.fillStyle = 'blue';
// 标识起始点 (50, 20)
ctx.fillRect(50, 20, 10, 10);
// 标识结束点 (50, 100)
ctx.fillRect(50, 100, 10, 10);
ctx.fillStyle = 'red';
// 标识控制点1 (230, 30)
ctx.fillRect(230, 30, 10, 10);
// 标识控制点2 (150, 70)
ctx.fillRect(150, 70, 10, 10);
// 绘制心形
ctx.beginPath();
ctx.moveTo(75, 190);
ctx.bezierCurveTo(75, 187, 70, 175, 50, 175);
ctx.bezierCurveTo(20, 175, 20, 212.5, 20, 212.5);
ctx.bezierCurveTo(20, 230, 40, 252, 75, 270);
ctx.bezierCurveTo(110, 250, 130, 230, 130, 212.5);
ctx.bezierCurveTo(130, 212.5, 130, 175, 100, 175);
ctx.bezierCurveTo(85, 175, 75, 187, 75, 190);
ctx.fill();