常用方法
<dl>
<dt>常用方法</dt>
<dd>
<dl>
<dt>直线(路径)</dt>
<dd>
<p>context.lineTo(x, y)</p>
<canvas id="line" width="800" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#line");
const context = canvas.getContext("2d");
context.fillStyle = "#000";
context.beginPath();
context.moveTo(20, 50);
context.lineTo(80, 50);
context.stroke();
context.beginPath(); //开始画新的路径
context.moveTo(120, 20);
context.lineTo(120, 80);
context.stroke();
context.beginPath();
context.moveTo(220, 20);
context.lineTo(220, 80);
context.lineTo(250, 80);
context.stroke();
context.beginPath();
context.moveTo(320, 20);
context.lineTo(320, 80);
context.lineTo(350, 80);
context.closePath(); //闭合路径
context.stroke();
}
</script>
</dd>
<dt>矩形</dt>
<dd>
<p>矩形(路径):context.rect(x, y, width, height)</p>
<p>填充矩形:context.fillRect(x, y, width, height)</p>
<p>描边矩形:context.strokeRect(x, y, width, height)</p>
<canvas id="rect" width="800" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#rect");
const context = canvas.getContext("2d");
context.fillStyle = "#000";
context.lineWidth = 1;
// 矩形
context.rect(0, 0, 80, 80);
context.stroke();
// 矩形填充
context.fillRect(100, 0, 80, 80);
// 5像素宽矩形描边
context.lineWidth = 5;
context.strokeRect(200, 0, 80, 80);
}
</script>
</dd>
<dt>圆弧 | 椭圆</dt>
<dd>
<p>正圆弧(路径):context.arc(x, y, radius, startAngle, endAngle [, anticlockwise])</p>
<p>椭圆(路径):context.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)</p>
<p>给路径添加圆弧(路径):context.arcTo(cpx1, cpy1, cpx2, cpy2, radius)</p>
<p>贝塞尔曲线(路径):context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)</p>
<canvas id="arc" width="800" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#arc");
const context = canvas.getContext("2d");
context.fillStyle = "#000";
// 顺时针绘制0到1/4弧度圆弧
context.beginPath();
context.arc(50, 50, 40, 0, Math.PI / 2);
context.stroke();
// 逆时针绘制0到1/4弧度圆弧
context.beginPath();
context.arc(150, 50, 40, 0, Math.PI / 2, true);
context.stroke();
// 绘制完整圆
context.beginPath();
context.arc(250, 50, 40, 0, 2 * Math.PI);
context.stroke();
// 绘制椭圆 旋转45°
context.beginPath();
context.ellipse(350, 50, 50, 40, Math.PI / 4, 0, 2 * Math.PI);
context.stroke();
// 绘制椭圆 旋转45°
context.beginPath();
context.ellipse(450, 50, 50, 50, Math.PI / 2, 0, Math.PI);
context.stroke();
// 给路径添加圆弧,需要指定控制点和半径,常用于绘制标准圆角
context.beginPath();
context.moveTo(500, 50);
context.arcTo(550, 100, 600, 50, 40);
context.stroke();
}
</script>
</dd>
<dt>贝塞尔曲线</dt>
<dd>
<p>贝塞尔曲线(路径):context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)</p>
<p>二次贝塞尔曲线(路径):context.quadraticCurveTo(cpx, cpy, x, y);</p>
<canvas id="bezier" width="800" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#bezier");
const context = canvas.getContext("2d");
context.fillStyle = "#000";
// 贝塞尔曲线
context.beginPath();
context.moveTo(0, 50);
context.bezierCurveTo(30, 75, 60, 40, 90, 60);
context.stroke();
context.beginPath();
context.moveTo(100, 50);
context.bezierCurveTo(130, 65, 160, 55, 190, 60);
context.stroke();
//二次贝塞尔曲线
context.beginPath();
context.moveTo(200, 50);
context.quadraticCurveTo(250, 75, 290, 30);
context.stroke();
}
</script>
</dd>
<dt>Image</dt>
<dd>
<p>context.drawImage(image, dx, dy);</p>
<p>context.drawImage(image, dx, dy, dWidth, dHeight);</p>
<p>context.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);</p>
<p>context.getImageData(sx, sy, sWidth, sHeight);</p>
<p>context.putImageData(imagedata, dx, dy);</p>
<p>context.putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);</p>
<p>context.createImageData(width, height);</p>
<canvas id="image" width="100" height="100"></canvas>
<canvas id="image1" width="100" height="100"></canvas>
<canvas id="image2" width="100" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#image");
const context = canvas.getContext("2d");
const canvas1 = document.querySelector("#image1");
const context1 = canvas1.getContext("2d");
const canvas2 = document.querySelector("#image2");
const context2 = canvas2.getContext("2d");
const image = new Image();
image.onload = function () {
context.drawImage(image, 0, 0);
context1.drawImage(image, 0, 0, 100, 100);
const val = Math.min(this.width, this.height);
context2.drawImage(image, 0, 0, val, val, 0, 0, 100, 100);
// 然后获取区域数据
const imageData = context2.getImageData(25, 25, 75, 75);
const length = imageData.data.length;
for (let index = 0; index < length; index += 4) {
const r = imageData.data[index];
const g = imageData.data[index + 1];
const b = imageData.data[index + 2];
// 计算灰度
const gray = r * 0.299 + g * 0.587 + b * 0.114;
imageData.data[index] = gray;
imageData.data[index + 1] = gray;
imageData.data[index + 2] = gray;
}
context2.putImageData(imageData, 25, 25);
const imageData1 = context1.createImageData(80, 50);
for (let x = 1; x <= 80; x += 5) {
for (let y = 1; y <= 50; y += 5) {
const index = 4 * ((y - 1) * 80 + (x - 1));
// 变为绿色,色值依次是0, 128, 0, 256
imageData1.data[index] = 0;
imageData1.data[index + 1] = 128;
imageData1.data[index + 2] = 0;
imageData1.data[index + 3] = 256;
}
}
context1.putImageData(imageData1, 25, 25, 0, 0, 50, 50);
};
image.src = "../images/1.jpg";
}
</script>
</dd>
<dt>文本</dt>
<dd>
<p>文本绘制:context.fillText(text, x, y [, maxWidth])</p>
<p>文本描边:context.strokeText(text, x, y [, maxWidth])</p>
<p>测量文本宽高等信息:context.measureText(text)</p>
<canvas id="text" width="800" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#text");
const context = canvas.getContext("2d");
// 设置水平对齐方式,可选值:left、right、center、start、end
context.textAlign = "left";
//设置字体垂直对齐方式
context.textBaseline = "alphabetic";
const str = "Canvas学习";
//font默认值:10px sans-serif
context.fillText(str, 0, 10);
context.fillText(`宽${context.measureText(str).width}`, 0, 20);
// 设置字体和字号
context.font = "20px SimSun, SimHei";
context.fillText(str, 100, 20);
context.fillText(`宽${context.measureText(str).width}`, 100, 50);
//超过maxWidth限制后,文本水平方向压缩
context.fillText(str, 100, 80, 50);
// 文字描边
context.strokeText(str, 250, 20);
// 文字先描边
context.lineWidth = 3;
context.strokeStyle = "red";
context.strokeText(str, 250, 40);
// 再填充
context.fillText(str, 250, 40);
}
</script>
</dd>
<dt>其它</dt>
<dd>
<p>清除区域:context.clearRect(x, y, width, height);</p>
<p>裁剪区域:context.clip();</p>
<p>canvas.toDataURL(mimeType, quality);</p>
<p>canvas.toBlob(callback, mimeType, quality);</p>
<p>mimeType默认值image/png;quality表示转换的图片质量。范围是0到1。默认压缩值是0.92。</p>
<canvas id="clearRect" width="100" height="100"></canvas>
<canvas id="clip" width="100" height="100"></canvas>
<img src="" id="clip1" width="100" height="100" />
<img src="" id="clip2" width="100" height="100" />
<script>
{
const canvas = document.querySelector("#clearRect");
const context = canvas.getContext("2d");
const canvas1 = document.querySelector("#clip");
const context1 = canvas1.getContext("2d");
const image = new Image();
image.onload = function () {
context.drawImage(image, 0, 0, canvas.width, canvas.height);
context.clearRect(25, 25, 50, 50);
context1.arc(50, 50, 50, 0, 2 * Math.PI);
context1.clip();
context1.drawImage(image, 0, 0, canvas.width, canvas.height);
canvas1.toBlob(function (blob) {
const url = URL.createObjectURL(blob);
document.querySelector("#clip1").src = url;
});
const dataUrl = canvas1.toDataURL();
document.querySelector("#clip2").src = dataUrl;
};
image.src = "../images/1.jpg";
}
</script>
</dd>
</dl>
</dd>
</dl>
![](https://img2024.cnblogs.com/blog/705533/202403/705533-20240301163521417-1498724564.png)
![](https://img2024.cnblogs.com/blog/705533/202403/705533-20240301163454380-1439787172.png)
绘制属性
<dl>
<dt>属性</dt>
<dd>
<dl>
<dt>线</dt>
<dd>
<p>线宽:context.lineWidth = value</p>
<p>线条转角:context.lineJoin = 'miter'; context.lineJoin = 'round'; context.lineJoin = 'bevel';</p>
<p>线条端点:context.lineCap = 'butt'; context.lineCap = 'round'; context.lineCap = 'square';</p>
<p>虚线绘制的偏移距离:context.lineDashOffset = value</p>
<canvas id="lineWidth" width="800" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#lineWidth");
const context = canvas.getContext("2d");
context.lineWidth = 2;
context.strokeRect(0, 0, 80, 80);
context.lineWidth = 10;
context.lineJoin = "miter";
context.strokeRect(100, 0, 80, 80);
context.lineJoin = "round";
context.strokeRect(200, 0, 80, 80);
context.lineJoin = "bevel";
context.strokeRect(300, 0, 80, 80);
context.lineJoin = "miter";
context.lineCap = "butt";
context.beginPath();
context.moveTo(400, 20);
context.lineTo(480, 20);
context.stroke();
context.lineCap = "round";
context.beginPath();
context.moveTo(400, 50);
context.lineTo(480, 50);
context.stroke();
context.lineCap = "square"; //线的端点多出一个方框,框框的宽度和线一样宽,高度是线厚度的一半
context.beginPath();
context.moveTo(400, 80);
context.lineTo(480, 80);
context.stroke();
context.lineCap = "butt";
//重置虚线设置 ctx.setLineDash(segments)
context.setLineDash([2, 2]);
context.lineDashOffset = 0;
context.beginPath();
context.moveTo(500, 20);
context.lineTo(580, 20);
context.stroke();
context.setLineDash([1, 2, 3, 6]);
context.lineDashOffset = 5;
context.beginPath();
context.moveTo(500, 50);
context.lineTo(580, 50);
context.stroke();
context.lineDashOffset = -5;
context.beginPath();
context.moveTo(500, 80);
context.lineTo(580, 80);
context.stroke();
}
</script>
</dd>
<dt>描边样式</dt>
<dd>
<p>context.strokeStyle = color</p>
<p>context.strokeStyle = gradient</p>
<p>context.strokeStyle = pattern</p>
<canvas id="stroke" width="800" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#stroke");
const context = canvas.getContext("2d");
context.lineWidth = 10;
context.strokeStyle = "RGB(255, 0, 0)";
context.strokeRect(0, 0, 80, 80);
context.strokeStyle = "RGBA(255, 0, 0, .5)";
context.strokeRect(100, 0, 80, 80);
context.strokeStyle = "#FF0000";
context.strokeRect(200, 0, 80, 80);
// 创建线性渐变对象 context.createLinearGradient(x0, y0, x1, y1)
const gradientLinear = context.createLinearGradient(0, 0, 0, 100);
gradientLinear.addColorStop(0, "red");
gradientLinear.addColorStop(0.5, "yellow");
gradientLinear.addColorStop(1, "green");
context.strokeStyle = gradientLinear;
context.strokeRect(300, 0, 80, 80);
// 创建径向渐变对象 context.createRadialGradient(x0, y0, r0, x1, y1, r1);
const gradientRadial = context.createRadialGradient(440, 40, 0, 440, 40, 50);
gradientRadial.addColorStop(0, "red");
gradientRadial.addColorStop(1, "green");
context.strokeStyle = gradientRadial;
context.strokeRect(400, 0, 80, 80);
// 创建图案对象
const imagePattern = document.createElement("img");
imagePattern.onload = function () {
// 缩放原始图片到50*50大小
const canvas_img = document.createElement("canvas");
canvas_img.width = canvas_img.height = 50;
const context_img = canvas_img.getContext("2d");
// 通过drawImage()方法缩放
context_img.drawImage(this, 0, 0, 50, 50);
// 把这个创建的canvas图形作为图案使用 context.createPattern(image, repetition)
const pattern = context.createPattern(canvas_img, "repeat");
// 填充图案
context.strokeStyle = pattern;
context.strokeRect(500, 0, 80, 80);
};
imagePattern.src = "../images/1.jpg";
}
</script>
</dd>
<dt>填充样式</dt>
<dd>
<p>context.fillStyle = color</p>
<p>context.fillStyle = gradient</p>
<p>context.fillStyle = pattern</p>
<canvas id="fill" width="800" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#fill");
const context = canvas.getContext("2d");
context.fillStyle = "RGB(255, 0, 0)";
context.fillRect(0, 0, 80, 80);
context.fillStyle = "RGBA(255, 0, 0, .5)";
context.fillRect(100, 0, 80, 80);
context.fillStyle = "#FF0000";
context.fillRect(200, 0, 80, 80);
// 创建线性渐变对象 context.createLinearGradient(x0, y0, x1, y1)
const gradientLinear = context.createLinearGradient(0, 0, 0, 100);
gradientLinear.addColorStop(0, "red");
gradientLinear.addColorStop(0.5, "yellow");
gradientLinear.addColorStop(1, "green");
context.fillStyle = gradientLinear;
context.fillRect(300, 0, 80, 80);
// 创建径向渐变对象 context.createRadialGradient(x0, y0, r0, x1, y1, r1);
const gradientRadial = context.createRadialGradient(440, 40, 0, 440, 40, 50);
gradientRadial.addColorStop(0, "red");
gradientRadial.addColorStop(1, "green");
context.fillStyle = gradientRadial;
context.fillRect(400, 0, 80, 80);
// 创建图案对象
const imagePattern = document.createElement("img");
imagePattern.onload = function () {
// 缩放原始图片到50*50大小
const canvas_img = document.createElement("canvas");
canvas_img.width = canvas_img.height = 50;
const context_img = canvas_img.getContext("2d");
// 通过drawImage()方法缩放
context_img.drawImage(this, 0, 0, 50, 50);
// 把这个创建的canvas图形作为图案使用
const pattern = context.createPattern(canvas_img, "repeat");
// 填充图案
context.fillStyle = pattern;
context.fillRect(500, 0, 80, 80);
};
imagePattern.src = "../images/1.jpg";
}
</script>
</dd>
</dl>
</dd>
</dl>
![](https://img2024.cnblogs.com/blog/705533/202403/705533-20240301163637712-1593025628.png)
变换
<dl>
<dt>平移</dt>
<dd>
<p>context.translate(x, y)</p>
<p>顺时针方向旋转画布,单位是弧度。角度转弧度计算公式是:radian = degree * Math.PI / 180。</p>
<p>默认旋转中心点是Canvas的左上角(0, 0)坐标点</p>
<canvas id="translate" width="100" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#translate");
const context = canvas.getContext("2d");
const width = canvas.width;
const height = canvas.height;
const img = new Image();
img.onload = function () {
context.translate(width / 2, height / 2); // 先位移坐标到中心
context.drawImage(this, 0, 0, width / 2, height / 2);
context.setTransform(1, 0, 0, 1, 0, 0); // 坐标系还原到初始
};
img.src = "../images/1.jpg";
}
</script>
</dd>
<dt>缩放</dt>
<dd>
<p>context.scale(x, y)</p>
<p>缩放Canvas画布的坐标系,只是影响坐标系,之后的绘制会受此方法影响,但之前已经绘制好的效果不会有任何变化。</p>
<p>默认缩放中心点是Canvas的左上角(0, 0)坐标点</p>
<canvas id="scale" width="800" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#scale");
const context = canvas.getContext("2d");
// 对比
context.fillRect(10, 10, 10, 10);
// 缩放
context.scale(10, 3);
context.fillRect(10, 10, 10, 10);
context.setTransform(1, 0, 0, 1, 0, 0); // 恢复坐标系
// 对比
context.fillRect(30, 10, 10, 10);
context.save(); // 记住Canvas状态
// 垂直翻转
context.scale(1, -1);
context.font = "20px SimSun, SimHei";
context.fillText("Canvas学习", 300, -50);
context.restore(); // 恢复状态,不要影响接下来的绘制
context.fillText("Canvas学习", 300, 80);
}
</script>
</dd>
<dt>旋转</dt>
<dd>
<p>context.rotate(angle)</p>
<p>顺时针方向旋转画布,单位是弧度。角度转弧度计算公式是:radian = degree * Math.PI / 180。</p>
<p>默认旋转中心点是Canvas的左上角(0, 0)坐标点</p>
<canvas id="rotate" width="100" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#rotate");
const context = canvas.getContext("2d");
const width = canvas.width;
const height = canvas.height;
const img = new Image();
img.onload = function () {
context.translate(width / 2, height / 2); // 先位移坐标到中心
context.rotate((180 * Math.PI) / 180); // 旋转
context.translate((-1 * width) / 2, (-1 * height) / 2); // 把定位中心移动到左上角
context.drawImage(this, 0, 0, width, height);
context.setTransform(1, 0, 0, 1, 0, 0); // 坐标系还原到初始
// 旋转45度
context.rotate((45 * Math.PI) / 180);
context.font = "20px SimSun, SimHei";
context.fillText("Canvas学习", 50, 40);
// 重置当前的变换矩阵为初始态
context.setTransform(1, 0, 0, 1, 0, 0);
};
img.src = "../images/1.jpg";
}
</script>
</dd>
<dt>变换</dt>
<dd>
<p>context.transform(a, b, c, d, e, f)</p>
<p>a 水平缩放 b 水平斜切</p>
<p>c 垂直斜切 d 垂直缩放</p>
<p>e 水平位移 f 垂直位移</p>
<canvas id="transform" width="100" height="100"></canvas>
<canvas id="transform1" width="100" height="100"></canvas>
<canvas id="transform2" width="100" height="100"></canvas>
<script>
{
const canvas = document.querySelector("#transform");
const context = canvas.getContext("2d");
const canvas1 = document.querySelector("#transform1");
const context1 = canvas1.getContext("2d");
const canvas2 = document.querySelector("#transform2");
const context2 = canvas2.getContext("2d");
const width = canvas.width;
const height = canvas.height;
const img = new Image();
img.onload = function () {
context.transform(0.5, 0, 0, 0.5, 0, 0);
context.drawImage(this, 0, 0, width, height);
context.setTransform(1, 0, 0, 1, 0, 0); // 坐标系还原到初始
context1.transform(1, 0, 0, 1, -20, -20);
context1.drawImage(this, 0, 0, width, height);
context1.setTransform(1, 0, 0, 1, 0, 0); // 坐标系还原到初始
context2.transform(1, 0.1, 0, 1, 0, 0);
context2.drawImage(this, 0, 0, width, height);
context2.setTransform(1, 0, 0, 1, 0, 0); // 坐标系还原到初始
};
img.src = "../images/1.jpg";
}
</script>
</dd>
</dl>
![](https://img2024.cnblogs.com/blog/705533/202403/705533-20240301163823546-1335563551.png)
![](https://img2024.cnblogs.com/blog/705533/202403/705533-20240301163841204-1001987942.png)