Canvas技术笔记
HTML5
<canvas>
元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成,<canvas>
标签只是图形容器,您必须使用脚本来绘制图形。你可以通过多种方法使用canvas
绘制路径,盒、圆、字符以及添加图像。
# 创建画布
一个画布在网页中是一个矩形框,通过 <canvas>
元素来绘制。
<canvas id="myCanvas" width="200" height="100"></canvas>
1
注意
标签通常需要指定一个id属性 (脚本中经常引用), width 和 height 属性定义的画布的大小。
# 颜色阴影样式
属性名 | 参数值 | 描述 |
---|---|---|
fillStyle | color(#000)/gradient/pattern | 设置或返回用于填充绘画的颜色、渐变或模式。 |
strokeStyle | color(blue)/gradient/pattern | 设置或返回用于笔触的颜色、渐变或模式。 |
shadowColor | color(red) | 设置或返回用于阴影的颜色。 |
shadowBlur | number(20) | 设置或返回用于阴影的模糊级别。 |
shadowOffsetX | number(5) | 设置或返回阴影与形状的水平距离。 |
shadowOffsetY | number(10) | 设置或返回阴影与形状的垂直距离。 |
createLinearGradient(x0,y0,x1,y1) | x0:x 坐标,y0:y 坐标,x1:x 坐标,y1:y 坐标 | 创建线性渐变(用在画布内容上)。 |
createPattern(image,direction) | image:图片实例,direction:"repeat、repeat-x、repeat-y、no-repeat") | 在指定的方向上重复指定的元素。 |
createRadialGradient(x0,y0,r0,x1,y1,r1) | x0:x 开始坐标,y0:y 开始坐标,r0:开始圆的半径,x1:x 结束坐标,y1:y 结束坐标,r1:结束圆的半径 | 创建放射状/环形的渐变(用在画布内容上)。 |
addColorStop(stop,color) | stop:介于 0.0 与 1.0 之间的值,表示渐变中开始与结束之间的位置,color:在 stop 位置显示的 CSS 颜色值。 | 规定渐变对象中的颜色和停止位置。 |
填充颜色示例代码:
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.fillStyle="#FF0000";
ctx.fillRect(20,20,150,100);
1
2
3
4
2
3
4
边框颜色示例代码:
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.strokeStyle="#FF0000";
ctx.strokeRect(20,20,150,100);
1
2
3
4
2
3
4
阴影示例代码:
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.shadowBlur=20;
ctx.shadowColor="black";
// ctx.shadowOffsetX="black";
// ctx.shadowOffsetY="black";
ctx.fillStyle="green";
ctx.fillRect(20,20,100,80);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
渐变示例代码:
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
let grd=ctx.createLinearGradient(0,0,170,0);
grd.addColorStop(0,"black");
grd.addColorStop(0.5,"red");
grd.addColorStop(1,"white");
ctx.fillStyle=grd;
ctx.fillRect(20,20,150,100);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
元素重复示例代码:
let direction = "repeat"; // repeat、repeat-x、repeat-y、no-repeat
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.clearRect(0,0,c.width,c.height);
let img=document.getElementById("lamp")
let pat=ctx.createPattern(img,direction);
ctx.rect(0,0,220,128);
ctx.fillStyle=pat;
ctx.fill();
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
环形渐变示例代码:
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
let grd=ctx.createRadialGradient(75,50,5,90,60,100);
grd.addColorStop(0,"red");
grd.addColorStop(1,"white");
ctx.fillStyle=grd;
ctx.fillRect(10,10,150,100);
1
2
3
4
5
6
7
2
3
4
5
6
7
# 线条样式
属性名 | 参数值 | 描述 |
---|---|---|
lineCap | butt:默认。向线条的每个末端添加平直的边缘、round:向线条的每个末端添加圆形线帽 、square:向线条的每个末端添加正方形线帽 | 设置或返回线条的结束端点样式。 |
lineJoin | bevel:创建斜角、round: 创建圆角、miter:默认。创建尖角 | 设置或返回两条线相交时,所创建的拐角类型。 |
lineWidth | number | 设置或返回当前的线条宽度。 |
miterLimit | number | 设置或返回最大斜接长度。 |
lineCap 示例代码:
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.beginPath();
ctx.lineWidth=10;
ctx.lineCap="butt";
ctx.moveTo(20,20);
ctx.lineTo(200,20);
ctx.stroke();
ctx.beginPath();
ctx.lineCap="round";
ctx.moveTo(20,40);
ctx.lineTo(200,40);
ctx.stroke();
ctx.beginPath();
ctx.lineCap="square";
ctx.moveTo(20,60);
ctx.lineTo(200,60);
ctx.stroke();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
lineJoin 示例代码:
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.beginPath();
ctx.lineJoin="round"; //bevel|round|miter
ctx.moveTo(20,20);
ctx.lineTo(100,50);
ctx.lineTo(20,100);
ctx.stroke();
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
miterLimit 示例代码:
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.lineWidth=10;
ctx.lineJoin="miter";
ctx.miterLimit=5;
ctx.moveTo(20,20);
ctx.lineTo(50,27);
ctx.lineTo(20,34);
ctx.stroke();
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
注意
试图设置 miterLimit 4(然后,斜接长度将超过斜接限制),当行满足它将显示为 lineJoin ="bevel"
# 矩形的创建
属性名 | 参数值 | 描述 |
---|---|---|
rect(x,y,width,height) | x:x坐标,y:y坐标,width:矩形的宽度,height:矩形的高度 | 创建矩形。 |
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:矩形的高度 | 在给定的矩形内清除指定的像素。 |
示例代码
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.beginPath();
ctx.lineWidth="6";
ctx.strokeStyle="red";
ctx.rect(5,5,290,140);
ctx.stroke();
ctx.beginPath();
ctx.lineWidth="4";
ctx.strokeStyle="green";
ctx.rect(30,30,50,50);
ctx.stroke();
ctx.beginPath();
ctx.lineWidth="10";
ctx.strokeStyle="blue";
ctx.rect(50,50,150,80);
ctx.stroke();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 路径的绘制
属性名 | 参数值 | 描述 |
---|---|---|
fill() | null | 填充当前绘图(路径)。 |
stroke() | null | 绘制已定义的路径。 |
beginPath() | null | 起始一条路径,或重置当前路径。 |
moveTo(x,y) | x:x 坐标,y:y 坐标 | 把路径移动到画布中的指定点,不创建线条。 |
closePath() | null | 创建从当前点回到起始点的路径。 |
lineTo(x,y) | x:x 坐标,y:y 坐标 | 添加一个新点,然后在画布中创建从该点到最后指定点的线条。 |
clip() | null | 从原始画布剪切任意形状和尺寸的区域。 |
quadraticCurveTo(cpx,cpy,x,y) | cpx:贝塞尔控制点的 x 坐标,cpy:贝塞尔控制点的 y 坐标,x:结束点的 x 坐标,y:结束点的 y 坐标 | 创建二次贝塞尔曲线。 |
bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y) | cp1x:第一个贝塞尔 x 坐标,cp1y:第一个贝塞尔 y 坐标,cp2x:第二个贝塞尔 x 坐标,cp2y:第二个贝塞尔 y 坐标,x:结束点的 x 坐标,y:结束点的 y 坐标 | 创建三次贝塞尔曲线。 |
arc(x,y,r,sAngle,eAngle,counterclockwise) | x:圆的中心的 x 坐标,y:圆的中心的 y 坐标,r:圆的半径,sAngle:起始角,以弧度计(弧的圆形的三点钟位置是 0 度),eAngle:结束角,以弧度计。,counterclockwise:可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。 | 创建弧/曲线(用于创建圆形或部分圆)。 |
arcTo(x1,y1,x2,y2,r) | x1:两切线交点的横坐标,y1:两切线交点的纵坐标,x2:第二条切线上一点的横坐标,y2:第二条切线上一点的纵坐标,r:弧的半径 | 创建两切线之间的弧/曲线。 |
isPointInPath(x,y) | x:x 坐标,y:y 坐标 | 如果指定的点位于当前路径中,则返回 true,否则返回 false。 |
两条路径代码
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.beginPath();
ctx.lineWidth="5";
ctx.strokeStyle="green";
ctx.moveTo(0,75);
ctx.lineTo(250,75);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle="purple";
ctx.moveTo(50,0);
ctx.lineTo(150,130);
ctx.stroke();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
绘制三角形示例代码
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(20,100);
ctx.lineTo(70,100);
ctx.closePath();
ctx.stroke();
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
二次贝塞尔曲线示例代码
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.quadraticCurveTo(20,100,200,20);
ctx.stroke();
1
2
3
4
5
6
2
3
4
5
6
三次贝塞尔曲线示例代码
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.bezierCurveTo(20,100,200,100,200,20);
ctx.stroke();
1
2
3
4
5
6
2
3
4
5
6
# 图形转换/变换
属性名 | 参数值 | 描述 |
---|---|---|
scale(scalewidth,scaleheight) | scalewidth:缩放当前绘图的宽度(0~1),scaleheight:缩放当前绘图的高度(0~1) | 缩放当前绘图至更大或更小。 |
rotate(angle) | angle:旋转角度,以弧度计,如需将角度转换为弧度,请使用 degrees*Math.PI/180 公式进行计算 | 旋转当前绘图。 |
translate(x,y) | x:水平坐标,y:垂直坐标 | 重新映射画布上的 (0,0) 位置。 |
transform(a,b,c,d,e,f) | a:水平缩放绘图,b:水平倾斜绘图。c:垂直倾斜绘图,d:垂直缩放绘图,e:水平移动绘图,f:垂直移动绘图 | 替换绘图的当前转换矩阵。 |
setTransform(a,b,c,d,e,f) | a:水平缩放绘图,b:水平倾斜绘图。c:垂直倾斜绘图,d:垂直缩放绘图,e:水平移动绘图,f:垂直移动绘图 | 将当前转换重置为单位矩阵。然后运行 transform()。 |
示例代码
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.fillStyle="yellow";
ctx.fillRect(0,0,250,100)
ctx.transform(1,0.5,-0.5,1,30,10);
ctx.fillStyle="red";
ctx.fillRect(0,0,250,100);
ctx.transform(1,0.5,-0.5,1,30,10);
ctx.fillStyle="blue";
ctx.fillRect(0,0,250,100);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 文本字体填充
属性/方法 | 参数值 | 描述 |
---|---|---|
font | "italic small-caps bold 12px arial" 默认:10px sans-serif | 设置或返回文本内容的当前字体属性。 |
textAlign | center、end、left、right、start | 设置或返回文本内容的当前对齐方式。 |
textBaseline | alphabetic、top、hanging、middle、ideographic、bottom | 设置或返回在绘制文本时使用的当前文本基线。 |
fillText(text,x,y,maxWidth) | text:输出的文本,x:x 坐标位置,y:y 坐标位置,maxWidth:可选。允许的最大文本宽度,以像素计 | 在画布上绘制"被填充的"文本。 |
strokeText(text,x,y,maxWidth) | text:输出的文本,x:x 坐标位置,y:y 坐标位置,maxWidth:可选。允许的最大文本宽度,以像素计 | 在画布上绘制文本(无填充)。 |
measureText(text).width | text:要测量的文本 | 返回包含指定文本宽度的对象。 |
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
let txt="Hello World"
ctx.font="20px Georgia";
ctx.strokeText(txt,10,50);
ctx.font="30px Verdana";
// 创建一个渐变
let gradient=ctx.createLinearGradient(0,0,c.width,0);
gradient.addColorStop("0","magenta");
gradient.addColorStop("0.5","blue");
gradient.addColorStop("1.0","red");
// 填充一个渐变
ctx.strokeStyle=gradient;
ctx.strokeText(txt,10,90);
ctx.fillText("width:" + ctx.measureText(txt).width,10,50)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 图像的绘制
属性/方法 | 参数值 | 描述 |
---|---|---|
drawImage(img,x,y) | img:图像、画布或视频,x: x 坐标位置,y: y 坐标位置度 | 在画布上定位图像 |
drawImage(img,x,y,width,height) | img:图像、画布或视频,x: x 坐标位置,y: y 坐标位置,width:可选。要使用的图像的宽度,height:可选。要使用的图像的高度 | 在画布上定位图像,并规定图像的宽度和高度 |
drawImage(img,sx,sy,swidth,sheight,x,y,width,height) | img:图像、画布或视频,sx:可选。开始剪切的 x 坐标位置,sy:可选。开始剪切的 y 坐标位置,swidth:可选。被剪切的宽度 ,sheight:可选。被剪切的高度,x: x 坐标位置,y: y 坐标位置,width:可选。要使用的图像的宽度,height:可选。要使用的图像的高度 | 剪切图像,并在画布上定位被剪切的部分 |
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
let img=document.getElementById("scream");
img.onload = function(){
ctx.drawImage(img,10,10);
}
1
2
3
4
5
6
2
3
4
5
6
# 元素像素操作
属性/方法 | 参数值 | 描述 |
---|---|---|
width | number | 返回 ImageData 对象的宽度。 |
height | number | 返回 ImageData 对象的高度。 |
data | ImageData | 返回一个对象,其包含指定的 ImageData 对象的图像数据。 |
createImageData(width,height) | width:ImageData 对象的宽度,以像素计,height:ImageData 对象的高度,以像素计 | 创建新的、空白的 ImageData 对象。 |
createImageData(imageData) | imageData: 另一个 ImageData 对象 | 创建新的、空白的 ImageData 对象。 |
getImageData(x,y,width,height) | x:开始复制的左上角位置的 x 坐标(以像素计),y:开始复制的左上角位置的 y 坐标(以像素计),width: 要复制的矩形区域的宽度,height:要复制的矩形区域的高度 | 返回 ImageData 对象,该对象为画布上指定的矩形复制像素数据。 |
putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight) | imgData:要放回画布的 ImageData 对象,x:左上角的 x 坐标,y:左上角的 y 坐标,dirtyX:在画布上放置图像的水平值,dirtyY:在画布上放置图像的垂直值,dirtyWidth:在画布上绘制图像所使用的宽度,dirtyHeight:在画布上绘制图像所使用的高度 | 把图像数据(从指定的 ImageData 对象)放回画布上。 |
代码示例
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
// ctx.fillStyle="red";
// ctx.fillRect(10,10,50,50);
let imgData=ctx.createImageData(100,100);
for (let i=0;i<imgData.data.length;i+=4){
imgData.data[i+0]=255;
imgData.data[i+1]=0;
imgData.data[i+2]=0;
imgData.data[i+3]=255;
}
function copy(){
let imgData=ctx.getImageData(10,10,50,50);
ctx.putImageData(imgData,10,70);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 图形合成属性
属性名 | 属性值 | 描述 |
---|---|---|
globalAlpha | number(0~1) | 设置或返回绘图的当前 alpha 或透明值。 |
globalCompositeOperation | source-over、source-atop、source-in、source-out、destination-over、destination-atop、destination-in、destination-out、lighter、copy、xor | 设置或返回新图像如何绘制到已有的图像上。 |
globalAlpha 示例代码
let c=document.getElementById("myCanvas");
let ctx=c.getContext("2d");
ctx.fillStyle="red";
ctx.fillRect(20,20,75,50);
// Turn transparency on
ctx.globalAlpha=0.2;
ctx.fillStyle="blue";
ctx.fillRect(50,50,75,50);
ctx.fillStyle="green";
ctx.fillRect(80,80,75,50);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
globalCompositeOperation 属性值说明
- source-over:默认。在目标图像上显示源图像。
- source-atop:在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
- source-in:在目标图像中显示源图像。只有目标图像之内的源图像部分会显示,目标图像是透明的。
- source-out:在目标图像之外显示源图像。只有目标图像之外的源图像部分会显示,目标图像是透明的。
- destination-over:在源图像上显示目标图像。
- destination-atop:在源图像顶部显示目标图像。目标图像位于源图像之外的部分是不可见的。
- destination-in:在源图像中显示目标图像。只有源图像之内的目标图像部分会被显示,源图像是透明的。
- destination-out:在源图像之外显示目标图像。只有源图像之外的目标图像部分会被显示,源图像是透明的。
- lighter:显示源图像 + 目标图像。
- copy:显示源图像。忽略目标图像。
- xor:使用异或操作对源图像与目标图像进行组合。
globalCompositeOperation 示例代码
let arr = ["source-atop","source-in","source-out","source-over","destination-atop","destination-in","destination-out","destination-over","lighter","copy","xor"];
for (n=0;n<arr.length;n++){
document.write("<div id='p_" + n + "' style='float:left;'>" + arr[n] + ":<br>");
let c=document.createElement("canvas");
c.width=120;
c.height=100;
document.getElementById("p_" + n).appendChild(c);
let ctx=c.getContext("2d");
ctx.fillStyle="blue";
ctx.fillRect(10,10,50,50);
ctx.globalCompositeOperation=arr[n];
ctx.beginPath();
ctx.fillStyle="red";
ctx.arc(50,50,30,0,2*Math.PI);
ctx.fill();
document.write("</div>");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 其他方法属性
方法属性名 | 描述 |
---|---|
save() | 保存当前环境的状态。 |
restore() 返回之前保存过的路径状态和属性。 | |
createEvent() | |
getContext() | |
toDataURL() |
# 代码示例
<!DOCTYPE html>
<html>
<head>
<title>正六边形</title>
<meta charset="utf-8">
</head>
<body>
<canvas id="canvas" width="1000" height="1000"></canvas>
</body>
<script type="text/javascript">
let c = document.getElementById("canvas");
let canvas = document.querySelector('#canvas'),
ctx = canvas.getContext('2d');
// 定义边长、颜色、边数、canvas大小
let length = 100, fillColor = '#000', vertices = 6, size = 1000;
// canvas.width = size;
// canvas.height = size;
let getDegree = function (vertices, index) {
return 360 / vertices * (i + 0.5) + 90;
}
let getRadian = function (degree) {
return degree * Math.PI / 180;
};
// 六边形
ctx.beginPath();
ctx.lineWidth = 12;
ctx.fillStyle = "red"
ctx.strokeStyle = 'blue'; //线条填充色
for (let i = 0; i < vertices; i++) {
// 计算偏转
let degree = getDegree(vertices, i),
radian = getRadian(degree);
// 增加1/3的canvas大小位移量以免被边缘挡住
let x = Math.cos(radian) * length + size / 3;
let y = Math.sin(radian) * length + size / 3;
ctx.lineTo(x, y);
}
ctx.fill()
ctx.closePath();
ctx.stroke();
// 圆圈
let num = 0
setInterval(() => {
// console.log(c.width,c.height);
// ctx.clearRect(100+num,100,100,100);
num = num + 5;
ctx.beginPath();
ctx.fillStyle = "#FF00FF"
ctx.lineWidth = 2;
ctx.strokeStyle = 'blue'; //线条填充色
ctx.arc(100 + num, 100, 50, 0, Math.PI * 2, true) //绘制圆形
ctx.fill()
ctx.stroke(); //绘制线段
}, 1000)
// 直线
ctx.beginPath();
ctx.lineWidth = 8;
ctx.strokeStyle = 'blue'; //线条填充色
// ctx.moveTo(180, 100); //起点坐标
ctx.lineTo(180, 100); //起点坐标
ctx.lineTo(250, 150); //中间点坐标
ctx.stroke(); //绘制线段
ctx.lineWidth = 2;
ctx.strokeStyle = 'red'; //线条填充色
ctx.lineTo(300, 100); //终点坐标
// ctx.closePath();
ctx.stroke(); //绘制线段
//文本
ctx.font = "20px Arial";
ctx.fillText("Hello World", 50, 30); //绘制实心的文本
ctx.strokeText("Hello World", 10, 50); //绘制空心的文本
// 矩形 线性渐变渐变 createLinearGradient(x,y,x1,y1) - 创建线条渐变
let grd = ctx.createLinearGradient(160, 0, 310, 0);
grd.addColorStop(0, "red");
grd.addColorStop(1, "white");
ctx.fillStyle = grd; // 填充渐变
ctx.fillRect(160, 160, 150, 80);
//径向/圆渐变 createRadialGradient(x,y,r,x1,y1,r1) - 创建一个径向/圆渐变
let grd = ctx.createRadialGradient(255, 50, 5, 300, 60, 100);
grd.addColorStop(0, "red");
grd.addColorStop(1, "white");
ctx.fillStyle = grd; // 填充渐变
ctx.fillRect(180, 10, 320, 80);
// // 把一幅图像放置到画布上
// let img = document.getElementById("scream");
// ctx.drawImage(img, 10, 10);
// 平行线 (两点、拐点样式)
ctx.beginPath();
ctx.lineWidth = 10;
ctx.strokeStyle = 'orange'; //线条填充色
ctx.moveTo(500, 100); //起点坐标
ctx.lineTo(550, 30); //拐点坐标
ctx.lineTo(600, 100); //终点坐标
ctx.lineCap = "square"
ctx.lineJoin = "bevel"
ctx.stroke(); //绘制线段
ctx.beginPath();
ctx.moveTo(500, 200); //起点坐标
ctx.lineTo(550, 130); //拐点坐标
ctx.lineTo(600, 200); //终点坐标
ctx.lineCap = "round"
ctx.lineJoin = "round"
ctx.stroke(); //绘制线段
// 三角形
ctx.beginPath();
ctx.lineWidth = 8;
ctx.strokeStyle = 'blue'; //线条填充色
ctx.fillStyle = "orange"
// ctx.moveTo(180, 100); //起点坐标
ctx.lineTo(10, 200); //起点坐标
ctx.lineTo(60, 200); //中间点坐标
ctx.lineTo(45, 250); //终点坐标
ctx.closePath();
ctx.fill()
ctx.stroke(); //绘制线段
// 镂空图形 漏斗 (非零环绕规则)
ctx.beginPath();
ctx.lineWidth = 0.1;
ctx.moveTo(0, 0);
ctx.lineTo(0, 30);
ctx.lineTo(30, 0);
ctx.lineTo(30, 30);
ctx.closePath();
ctx.fill()
ctx.stroke(); //绘制线段
// 镂空图形 正方形
ctx.beginPath();
ctx.lineWidth = 0.1;
ctx.moveTo(0, 100);
ctx.lineTo(30, 100);
ctx.lineTo(30, 130);
ctx.lineTo(0, 130);
ctx.closePath();
ctx.moveTo(10, 110);
ctx.lineTo(10, 120);
ctx.lineTo(20, 120);
ctx.lineTo(20, 110);
ctx.closePath();
ctx.fill()
ctx.stroke(); //绘制线段
// 虚线
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = 'blue'; //线条填充色
ctx.moveTo(10, 150); //起点坐标
ctx.lineTo(100, 150);
ctx.setLineDash([5, 10]);
ctx.lineDashOffset = -2;
console.log(ctx.getLineDash);
ctx.stroke(); //绘制线段
// 引入图片
let img = new Image();
img.src = cskImg;
img.onload = function () {
cxt.drawImage(img, 0, 0, 500, 500);
// cxt.draw()
cxt.stroke();
cxt.restore();
}
</script>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# 参考资料
上次更新: 2024/01/30, 00:35:17
- 02
- Node与GLIBC_2.27不兼容解决方案08-19
- 03
- Git清空本地文件跟踪缓存08-13