canvas 只支持一种原生的图形绘制,原生只支持矩形绘制;
所有其他的图形的绘制都至少需要生成一条路径;
绘制矩形
API 和属性
API 或 属性 | 描述 |
---|---|
fillRect(x, y, width, height) | 绘制一个填充的矩形 · x、y 指定了绘制的矩形的左上角的坐标 · width、height 设置矩形的尺寸 (存在边框的话,边框会在 width、height 上占据一个边框的宽度) |
strokeRect(x, y, width, height) | 绘制一个矩形的边框 · x、y 指定了绘制的矩形的左上角的坐标 · width、height 设置矩形的尺寸 (存在边框的话,边框会在 width、height 上占据一个边框的宽度) |
clearRect(x, y, width, height) | 清除指定矩形区域 · x、y 指定了绘制的矩形的左上角的坐标 · width、height 设置矩形的尺寸 (存在边框的话,边框会在 width、height 上占据一个边框的宽度) |
fillStyle | 设置图形的填充颜色 (默认黑色) |
strokeStyle | 设置图形轮廓的颜色 (默认黑色) |
lineWidth | 设置当前绘线的粗细,属性值必须为正数 (默认值是 1.0,为 0、负数、Infinity 和 NaN 会被忽略) |
lineJoin | 设定线条与线条间接合处的样式 (round: 圆角、bevel: 斜角、miter: 直角(默认) |
案例
-
实现代码
HTMLJavaScript<canvas id="canvas" width="100%" height="300px"></canvas>
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var height = 0; var timer = setInterval(function () { ctx.clearRect(0, 0, 400, 300); // ctx.fillStyle = "deeppink"; // 设置图形的填充颜色 ctx.strokeStyle = "pink"; // 设置图形轮廓的颜色 ctx.lineWidth = 5; // 设置当前绘线的粗细 ctx.lineJoin = "round"; // 设定线条与线条间接合处的样式:圆角、斜角、直角 ctx.strokeRect(100, height, 50, 50); height += 2; if (height > 300) height = 0; }, 1000 / 60);
-
效果展示
绘制路径
绘制步骤
图形的基本元素是路径,路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合;
- 首先需要创建路径起始点;
- 然后使用画图命令去画出路径;
- 之后把路径封闭;
一旦路径生成,就能通过描边或填充路径区域来渲染图形;
API 和属性
API 或 属性 | 描述 |
---|---|
beginPath() | 开始一条路径,或重置当前的路径 |
moveTo(x, y) | 把路径移动到画布中的指定点,不创建线条 |
lineTo(x, y) | 添加一个新点,然后创建从该点到画布中最后指定点的线条 |
closePath() | 不是必需的,这个方法会通过绘制一条从当前点到开始点的直线来闭合图形 |
stroke() | 通过线条来绘制图形轮廓 |
fill() | 通过填充路径的内容区域生成实心的图形,自动调用 closePath() |
rect(x, y, width, height) | 绘制一个坐标为 (x, y),宽高为 width、height 的矩形 |
lineCap | 指定绘制每一条线段末端的属性 · butt:线段末端以矩形结束(默认值) · round:线段末端以圆形结束 · square:线段末端以矩形结束,线段两端长度增加为线段厚度一半的矩形区域 |
save() | 将当前状态放入栈中,保存到栈中的绘制状态 · 当前的变换矩阵 · 当前的剪切区域(基本用不到) · 当前的虚线列表(基本用不到) · 以下属性当前的值:strokeStyle、fillStyle、lineWidth、lineCap、lineJoin … |
restore() | 在绘图状态栈中弹出顶端的状态,将 canvas 恢复到最近的保存状态的方法 |
其他概念
路径容器:每次调用路径 api 时,都会向路径容器里做登记,调用 beginPath 时,清空整个 路径容器;
样式容器:每次调用样式 api 时,都会往样式容器里做登记,调用 save 时候,将样式容器里的状态压入样式栈,调用 restore 时候,将样式栈的栈顶状态弹出到样式样式容器里,进行覆盖;
样式栈:调用 save 时候,将样式容器里的状态压入样式栈,调用 restore 时候,将样式栈的栈顶状态弹出到样式样式容器里,进行覆盖;
案例一
-
示例代码
HTMLJavaScript<canvas id="canvas"></canvas>
window.onload = function () { var canvas = document.querySelector("#canvas"); if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.save(); ctx.fillStyle = "pink"; ctx.save(); ctx.fillStyle = "deeppink"; ctx.fillStyle = "blue"; ctx.save(); ctx.fillStyle = "red"; ctx.save(); ctx.fillStyle = "green"; ctx.save(); ctx.beginPath(); // 出栈两次 为红色 ctx.restore(); ctx.restore(); ctx.fillRect(50, 50, 100, 100); } }
-
效果展示
案例二
-
示例代码
HTMLJavaScript<canvas id="canvas"></canvas>
window.onload = function() { var canvas = document.querySelector("#canvas"); const getPixelRatio = (context) => { return window.devicePixelRatio || 1; } const ratio = getPixelRatio(); canvas.style.width = document.documentElement.clientWidth + 'px'; canvas.style.height = 250 + 'px'; canvas.width = document.documentElement.clientWidth * ratio; canvas.height = 250 * ratio; if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.strokeStyle = "deeppink"; ctx.fillStyle = "green"; ctx.lineWidth = 10; ctx.moveTo(100, 100); ctx.lineTo(100, 200); ctx.lineTo(200, 200); ctx.lineTo(100, 100); ctx.closePath(); ctx.stroke(); ctx.moveTo(200, 200); ctx.lineTo(200, 300); ctx.lineTo(300, 300); // fill方法会自动合并路径 ctx.fill(); ctx.beginPath(); // 设置原点的坐标 var originX = canvas.width / 2; var originY = canvas.height / 2; ctx.moveTo(100 + originX, 100); ctx.lineTo(100 + originX, 200); ctx.lineTo(200 + originX, 200); ctx.lineTo(100 + originX, 100); ctx.closePath(); ctx.stroke(); // 重置当前的路径 ctx.moveTo(200 + originX, 200); ctx.lineTo(200 + originX, 300); ctx.lineTo(300 + originX, 300); // fill方法会自动合并路径 ctx.fill(); } }
-
效果展示
绘制曲线
API 和属性
API 或 属性 | 描述 |
---|---|
arc(x, y, radius, startAngle, endAngle, anticlockwise) | 绘制圆形 · x、y 为圆心坐标 · radius 为半径 · startAngle、endAngle 参数用弧度定义了开始以及结束的弧度,这些都是以 x 轴为基准 · anticlockwise 为一个布尔值,为 true 时,是逆时针方向,否则顺时针方向 |
arcTo(x1, y1, x2, y2, radius) | 根据给定的控制点和半径 radius 画一段圆弧,肯定会从 (x1, y1) ,但不一定经过 (x2, y2) , (x2, y2) 只是控制一个方向 |
quadraticCurveTo(cp1x, cp1y, x, y) | 绘制二次贝塞尔曲线,cp1x、cp1y 为一个控制点,x、y 为结束点,起始点为 moveto 时指定的点 |
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) | 绘制三次贝塞尔曲线,cp1x、cp1y 为控制点一,cp2x、cp2y 为控制点二,x、y 为结束点,起始点为 moveto 时指定的点 |
坐标系
案例:绘制曲线
-
示例代码:
HTMLJavaScript<canvas id="canvas"></canvas>
window.onload = function () { var canvas = document.querySelector("#canvas"); const getPixelRatio = (context) => { return window.devicePixelRatio || 1; } const ratio = getPixelRatio(); canvas.style.width = document.documentElement.clientWidth + 'px'; canvas.style.height = 250 + 'px'; canvas.width = document.documentElement.clientWidth * ratio; canvas.height = 250 * ratio; if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(50, 50); ctx.lineTo(300, 0); ctx.lineTo(200, 200); ctx.stroke(); ctx.beginPath(); ctx.moveTo(50, 50) //以(300,0)、(200,200)为控制点,绘制一个半径是50的一段圆弧 ctx.arcTo(300, 0, 200, 200, 50); ctx.stroke(); // 设置原点的坐标 var originX = canvas.width / 3; ctx.beginPath(); ctx.moveTo(50 + originX, 50); ctx.lineTo(300 + originX, 0); ctx.lineTo(200 + originX, 200); ctx.stroke(); ctx.beginPath(); ctx.moveTo(50 + originX, 50) //以(300,0)、(200,200)绘制二次贝塞尔曲线 ctx.quadraticCurveTo(300 + originX, 0, 200 + originX, 200); ctx.stroke(); var originX = canvas.width / 3 * 2; ctx.beginPath(); ctx.moveTo(50 + originX, 50); ctx.lineTo(300 + originX, 0); ctx.lineTo(0 + originX, 300); ctx.lineTo(300 + originX, 300); ctx.stroke(); ctx.beginPath(); ctx.moveTo(50 + originX, 50) //以(300,0)、(0,300)、(300,300)绘制三次贝塞尔曲线 ctx.bezierCurveTo(300 + originX, 0, 0 + originX, 300, 300 + originX, 300); ctx.stroke(); } }
-
效果展示:
绘制文字
API 和属性
API 或 属性 | 描述 |
---|---|
fillText(text, x, y) | 在指定的 (x, y) 位置填充指定的文本 |
strokeText(text, x, y) | 在指定的 (x, y) 位置绘制文本边框 |
measureText(text) | 返回一个 TextMetrics 对象,包含关于文本尺寸的信息 |
font | 在指定时,必须要有大小和字体缺一不可,默认的字体是 font=“10px sans-serif” |
textAlign | 文本对齐方式 · 文本左对齐 · 文本右对齐 · 文本居中对齐,居中是基于在 fillText 的时候所给的 x 值,也就是说文本一半在 x 左边,一半在 x 右边 |
textBaseline | 文本基线 · 文本基线在文本块的顶部 · 文本基线在文本块的中间 · 文本基线在文本块的底部 |
绘制阴影
属性 | 描述 |
---|---|
shadowOffsetX | 阴影在 X 轴的延伸距离,默认为 0 |
shadowOffsetY | 阴影在 Y 轴的延伸距离,默认为 0 |
shadowBlur | 设定阴影的模糊程度,其数值并不跟像素数量挂钩,默认为 0 |
shadowColor | 设定阴影颜色效果,默认是全透明的黑色 |
案例
-
示例代码
HTMLJavaScript<canvas id="canvas" width="600px" height="250px"></canvas>
window.onload = function () { var canvas = document.querySelector("#canvas"); if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.fillStyle = "green"; ctx.font = "40px sans-serif"; ctx.fillText("你好", 100, 100); // 文本阴影 & 盒阴影 ctx.fillStyle = 'green'; ctx.shadowOffsetX = 5; ctx.shadowOffsetY = 5; ctx.shadowColor = '#333'; ctx.shadowBlur = 10; ctx.fillRect(300, 100, 200, 100); } }
-
效果展示
🏷 canvas 基本用法、高清绘制
上一篇