简言
学习canvas路径绘制点、线、面的api。
canvas路径
图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形需要一些额外的步骤。
- 首先,你需要创建路径起始点。
- 然后你使用画图命令去画出路径。
- 之后你把路径封闭。
- 一旦路径生成,你就能通过描边或填充路径区域来渲染图形。
canvas的路径有许多方法供使用。
beginPath 开始新子路径
CanvasRenderingContext2D.beginPath() 是 Canvas 2D API 通过清空子路径列表开始一个新路径的方法。当你想创建一个新的路径时,调用此方法。
示例:
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
// First path
ctx.beginPath();
stroke 绘制路径
CanvasRenderingContext2D.stroke() 是 Canvas 2D API 使用非零环绕规则,根据当前的画线样式,绘制当前或已经存在的路径的方法。
非零环绕规则是图形学中判断某个区域是在所属区域外面还是内部的一种规则。假设以一个点做射线,初始为0,与顺时针路径相交则+1,与逆时针路径相交则-1,最后相交点相加不为0,这个点则在路径内部,否则外部。
参数:
-path — 绘制的路径Path2D 。(可选的)
moveTo 将子路径起始点移到指定位置
CanvasRenderingContext2D.moveTo() 是 Canvas 2D API 将一个新的子路径的起始点移动到 (x,y) 坐标的方法。
语法:
void ctx.moveTo(x, y);
参数:
- x — 点的 x 轴。
- y — 点的 y 轴。
lineTo 使用直线连接新路径
CanvasRenderingContext2D.lineTo() 是 Canvas 2D API 使用直线连接子路径的终点到 x,y 坐标的方法(并不会真正地绘制)。
语法:
void ctx.lineTo(x, y);
- x — 直线终点的 x 轴坐标。
- y — 直线终点的 y 轴坐标。
示例:
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.beginPath(); // Start a new path
ctx.moveTo(30, 50); // Move the pen to (30, 50)
ctx.lineTo(150, 100); // Draw a line to (150, 100)
ctx.stroke(); // Render the path
closePath 回到子路径起始点
CanvasRenderingContext2D.closePath() 是 Canvas 2D API 将笔点返回到当前子路径起始点的方法。它尝试从当前点到起始点绘制一条直线。如果图形已经是封闭的或者只有一个点,那么此方法不会做任何操作。
相当于lineTo(x,y),x,y是起始点坐标。
语法:
void ctx.closePath();
示例:
闭合三角形
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(20, 140); // p1
ctx.lineTo(120, 10); // l1
ctx.lineTo(220, 140); // l2
ctx.closePath(); // l3
ctx.stroke(); // 绘制
arc 圆弧路径
CanvasRenderingContext2D.arc() 是 Canvas 2D API 绘制圆弧路径的方法。圆弧路径的圆心在 (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,逆时针绘制圆弧,反之,顺时针绘制。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas1</title>
<style>
#canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const PI = Math.PI
const cDom = document.getElementById("canvas")
// 定义画布宽高
cDom.width = 500
cDom.height = 500
const context = cDom.getContext("2d")
// ctx.fillRect(0, 0, cDom.width, cDom.height)
// cDom.addEventListener("click", (e) => {
// console.log(e.offsetX, e.offsetY, e)
// context.fillStyle = '#000'
// context.beginPath()
// context.arc(e.offsetX, e.offsetY, 1, 0, 2 * Math.PI)
// context.fill()
// })
drawSmile(context)
function drawSmile (ctx) {
ctx.beginPath()
ctx.arc(200, 200, 100, 0, 2 * PI)
ctx.stroke()
ctx.beginPath()
ctx.arc(160, 180, 10, 0, 2 * PI)
ctx.stroke()
ctx.beginPath()
ctx.arc(240, 180, 10, 0, 2 * PI)
ctx.stroke()
ctx.beginPath()
ctx.arc(200, 220, 30, PI, 2 * PI, true) // 逆时针路径
ctx.stroke()
}
</script>
</body>
</html>
arcTo 两切线圆弧
CanvasRenderingContext2D.arcTo() 是 Canvas 2D API 根据控制点和半径绘制圆弧路径,使用当前的描点 (前一个 moveTo 或 lineTo 等函数的止点)。根据当前描点与给定的控制点 1 连接的直线,和控制点 1 与控制点 2 连接的直线,作为使用指定半径的圆的切线,画出两条切线之间的弧线路径。
语法:
void ctx.arcTo(x1, y1, x2, y2, radius);
参数:
- x1 — 第一个控制点的 x 轴坐标。
- y1 — 第一个控制点的 y 轴坐标。
- x2 — 第二个控制点的 x 轴坐标。
- y2 — 第二个控制点的 y 轴坐标。
- radius — 圆弧的半径。
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.setLineDash([]);
ctx.beginPath();
ctx.moveTo(150, 20);
ctx.arcTo(150, 100, 50, 20, 30);
ctx.stroke();
ctx.fillStyle = "blue";
// base point
ctx.fillRect(150, 20, 10, 10);
ctx.fillStyle = "red";
// control point one
ctx.fillRect(150, 100, 10, 10);
// control point two
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();
ellipse 椭圆路径
CanvasRenderingContext2D.ellipse() 是 Canvas 2D API 添加椭圆路径的方法。椭圆的圆心在(x,y)位置,半径分别是radiusX 和 radiusY,按照anticlockwise(默认顺时针)指定的方向,从 startAngle 开始绘制,到 endAngle 结束。
语法:
void ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);
参数:
- x — 椭圆圆心的 x 轴坐标。
- y — 椭圆圆心的 y 轴坐标。
- radiusX — 椭圆长轴的半径。
- radiusY — 椭圆短轴的半径。
- rotation — 椭圆的旋转角度,以弧度表示 (非角度度数)。
- startAngle — 将要绘制的起始点角度,从 x 轴测量,以弧度表示 (非角度度数)。
- endAngle — 椭圆将要绘制的结束点角度,以弧度表示 (非角度度数)。
- anticlockwise — Boolean 选项,如果为 true,逆时针方向绘制椭圆(逆时针),反之顺时针方向绘制。默认false.
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
// Draw the ellipse
ctx.beginPath();
ctx.ellipse(100, 100, 50, 75, Math.PI / 4, 0, 2 * Math.PI);
ctx.stroke();
// Draw the ellipse's line of reflection
ctx.beginPath();
ctx.setLineDash([5, 5]);
ctx.moveTo(0, 200);
ctx.lineTo(200, 0);
ctx.stroke();
rect 矩形路径
CanvasRenderingContext2D.rect() 是 Canvas 2D API 创建矩形路径的方法,矩形的起点位置是 (x, y),尺寸为 width 和 height。矩形的 4 个点通过直线连接,子路径做为闭合的标记,所以你可以填充或者描边矩形。
语法:
void ctx.rect(x, y, width, height);
参数:
- x — 矩形起点的 x 轴坐标。
- y — 矩形起点的 y 轴坐标。
- width — 矩形的宽度。
- height — 矩形的高度。
quadraticCurveTo 二次贝塞尔曲线路径
CanvasRenderingContext2D.quadraticCurveTo() 是 Canvas 2D API 新增二次贝塞尔曲线路径的方法。它需要 2 个点。第一个点是控制点,第二个点是终点。起始点是当前路径最新的点,当创建二次贝赛尔曲线之前,可以使用 moveTo() 方法进行改变。
语法:
void ctx.quadraticCurveTo(cpx, cpy, x, y);
参数:
- cpx — 控制点的 x 轴坐标。
- cpy — 控制点的 y 轴坐标。
- x — 终点的 x 轴坐标。
- y — 终点的 y 轴坐标。
示例:
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
// Quadratic Bézier curve
ctx.beginPath();
ctx.moveTo(50, 20);
ctx.quadraticCurveTo(230, 30, 50, 100);
ctx.stroke();
// Start and end points
ctx.fillStyle = "blue";
ctx.beginPath();
ctx.arc(50, 20, 5, 0, 2 * Math.PI); // Start point
ctx.arc(50, 100, 5, 0, 2 * Math.PI); // End point
ctx.fill();
// Control point
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(230, 30, 5, 0, 2 * Math.PI);
ctx.fill();
bezierCurveTo 三次贝塞尔路径
CanvasRenderingContext2D.bezierCurveTo() 是 Canvas 2D API 绘制三次贝赛尔曲线路径的方法。该方法需要三个点。第一、第二个点是控制点,第三个点是结束点。起始点是当前路径的最后一个点,绘制贝赛尔曲线前,可以通过调用 moveTo() 进行修改。
语法:
void ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
参数:
cp1x — 第一个控制点的 x 轴坐标。
cp1y — 第一个控制点的 y 轴坐标。
cp2x — 第二个控制点的 x 轴坐标。
cp2y — 第二个控制点的 y 轴坐标。
x — 结束点的 x 轴坐标。
y — 结束点的 y 轴坐标。
示例:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(50, 20);
ctx.bezierCurveTo(230, 30, 150, 60, 50, 100);
ctx.stroke();
ctx.fillStyle = "blue";
// start point
ctx.fillRect(50, 20, 10, 10);
// end point
ctx.fillRect(50, 100, 10, 10);
ctx.fillStyle = "red";
// control point one
ctx.fillRect(230, 30, 10, 10);
// control point two
ctx.fillRect(150, 70, 10, 10);
fill 填充路径
CanvasRenderingContext2D.fill() 是 Canvas 2D API 根据当前的填充样式,填充当前或已存在的路径的方法。采取非零环绕或者奇偶环绕规则。
语法:
void ctx.fill();
void ctx.fill(fillRule);
void ctx.fill(path, fillRule);
参数:
- fillRule — 一种算法,决定点是在路径内还是在路径外。 允许的值:nonzero非零环绕规则,默认的规则。evenodd 奇偶环绕规则。
- path — 需要填充的Path2D 路径。
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.rect(10, 10, 150, 100);
ctx.fill();
clip 裁剪路径
CanvasRenderingContext2D.clip() 是 Canvas 2D API 将当前创建的路径设置为当前剪切路径的方法。
语法:
void ctx.clip();
void ctx.clip(fillRule);
void ctx.clip(path, fillRule);
参数:
- fillRule — 这个算法判断一个点是在路径内还是在路径外。 允许的值:nonzero非零环绕原则,默认的原则。evenodd奇偶环绕原则。
- path — 需要剪切的 Path2D 路径。
示例:
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
// Create circular clipping region
ctx.beginPath();
ctx.arc(100, 75, 50, 0, Math.PI * 2);
ctx.clip();
// Draw stuff that gets clipped
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "orange";
ctx.fillRect(0, 0, 100, 100);
绘制点
一个点可看作一个半径为1px的圆或者矩形,然后填充路径。
const PI = Math.PI
const cDom = document.getElementById("canvas")
// 定义画布宽高
cDom.width = 500
cDom.height = 500
const context = cDom.getContext("2d")
cDom.addEventListener("click", (e) => {
console.log(e.offsetX, e.offsetY, e)
context.fillStyle = '#000'
context.beginPath()
context.arc(e.offsetX, e.offsetY, 1, 0, 2 * Math.PI)
context.fill()
})
绘制线
线有直线、曲线和闭合的曲线等,可以使用lineTo、rect、arc等上面的方法,然后使用stroke方法绘制路径。
绘制面
绘制面主要是使用fill方法来填充路径,显示绘制成面的效果。
const PI = Math.PI
const cDom = document.getElementById("canvas")
// 定义画布宽高
cDom.width = 500
cDom.height = 500
const context = cDom.getContext("2d")
// context.fillRect(0, 0, cDom.width, cDom.height)
cDom.addEventListener("click", (e) => {
console.log(e.offsetX, e.offsetY, e)
context.fillStyle = '#000'
context.beginPath()
context.arc(e.offsetX, e.offsetY, 10, 0, 2 * Math.PI)
context.fill()
})
结语
结束了。