1 使用canvas

标签创建一块画布,属性有:id(标识画布,以便js对其引用),width(宽度),height(高度)。默认情况下画布大小为宽300px,高150px。

注意,与不同,需要结束标签,如果结束标签不存在,则文档的其余部分会被认为是替代内容,将不会显示出来

 1<body>
 2    <canvas id="myCanvas" width="200" height="100" style="border: 1px solid;"></canvas>
 3
 4    <script>
 5        var c = document.getElementById('myCanvas');
 6        var context = c.getContext("2d") 
 7        context.fillStyle = "#ff00ff";
 8        context.fillRect(50, 25, 100, 50);
 9    </script>
10</body>

在canvas中,坐标原点(0,0)位于canvas画布的左上角,x轴水平向右延伸,y轴垂直向下延伸,所有元素的位置都相对于原点进行定位。

浏览器兼容:

老版本浏览器可能不支持canvas元素,因此在特定用户群体中,需要为这些浏览器提供替代内容,只需要在标签内嵌入替代内容。

2 绘制图形

2.1 矩形

fillRect(x, y, width, height):绘制一个填充的矩形

strokeRect(x, y, width, height):绘制一个矩形的边框

clearRect(x, y, width, height):清除指定矩形区域,让清除部分完全透明

2.2 路径

通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径甚至一个子路径,都是闭合的,路径绘制步骤:

(1)创建路径起始点

(2)使用画图命令绘制路径

(3)封闭路径

(4)生成路径之后,可以通过描边或填充路径区域来渲染图形

beginPath():开始路径。新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径

closePath():闭合路径。闭合路径之后图形绘制命令又重新指向到上下文中

stroke():描边路径。通过线条来绘制图形轮廓

fill():填充路径。通过填充路径的内容区域生成实心的图形

提示:生成路径的第一步是调用beginPath方法,每次调用这个方法之后,表示开始重新绘制新的图形。闭合路径closePath不是必须得,当调用fill 方法时,所有没有闭合的形状都会自动闭合,但是调用stoke时不会自动闭合。

moveTo(x, y):绘制一些不连续的路径。

2.3 直线

lineTo(x, y):将绘制一条从当前位置到指定(x,y)位置的直线

 1<canvas id="myCanvas" width="400" height="400" style="border: 1px solid;"></canvas>
 2
 3    <script>
 4        var c = document.getElementById('myCanvas')
 5        var ctx = c.getContext("2d") 
 6        //填充三角形
 7        ctx.beginPath()
 8        ctx.moveTo(25,25)
 9        ctx.lineTo(105,25)
10        ctx.lineTo(25,105)
11        ctx.fill()
12
13        //描边三角形
14        ctx.beginPath()
15        ctx.moveTo(125,125)
16        ctx.lineTo(125,45)
17        ctx.lineTo(45,125)
18        ctx.closePath()
19        ctx.stroke()
20    </script>

2.4 圆弧

arc(x, y, r, sAngle, eAngle, counterclockwise);

sAngle:起始角,以弧度计。弧的圆形的三点钟位置是0°

eAngle:结束角,以弧度计

counterclockwise:可选参数,定义绘图方向。false为顺时针,默认值,true为逆时针

arc(x, y, r, 0, 2*Math.PI):圆形

actTo(x1, y1, x2, y2,r):绘制曲线,是lineTo的曲线版,能够创建两条切线之间的弧或曲线

 1        
 2        ctx.beginPath();
 3        ctx.arc(75,75,50,0,Math.PI*2,true);
 4        ctx.moveTo(110,75);
 5        ctx.arc(75,75,35,0,Math.PI,false) 
 6        ctx.moveTo(65,65);
 7        ctx.arc(60,65,5,0,Math.PI*2,false) 
 8        ctx.moveTo(95,65);
 9        ctx.arc(90,65,5,0,Math.PI*2,false) 
10        ctx.stroke();
11
12        
13        ctx.beginPath();
14        ctx.moveTo(200,20);
15        ctx.lineTo(280,20);
16        ctx.arcTo(330,20,330,70,50);
17        ctx.lineTo(330,150);
18        ctx.stroke();

2.5 二次方曲线(贝塞尔曲线)

quadraticCurveTo(cpx, cpy, x, y)

cpx:贝塞尔控制点的x坐标;cpy:贝塞尔控制点的y坐标;x:结束点x坐标;y:结束点y坐标

 1ctx.beginPath()
 2ctx.moveTo(20, 20)
 3ctx.quadraticCurveTo(20,100,200,20)
 4ctx.stroke()

2.6 三次方曲线

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

cp1x:第一个贝塞尔控制点的x坐标;cp1y:第一个贝塞尔控制点的y坐标;cp2x:第二个贝塞尔控制点的x坐标;cp2y:第二个贝塞尔控制点的y坐标;x:结束点x坐标;y:结束点y坐标

globalCompositeOperation = “source-over”:绘制出曲线的控制点和控制线

3 定义样式和颜色

3.1 颜色

fillStylestrokeStyle属性可以给图形上色,值为css颜色字符串或渐变对象或图案对象

3.2 不透明度

globalAlpha全局属性可以设置绘制图形的不透明度,相对来说更常用rgba值设置颜色调整透明度。

3.3 实线

lineWidth属性设置线条粗细,取值必须为正数,默认1.0

lineCap属性设置线段端点样式,值有butt、round和square,默认butt

lineJoin属性设置两条线段连接处样式,值有round、bevel和miter。默认miter

miterLimit属性设置两条线段连接处交点的绘制方式,起作用是为斜面的长度设置一个上限,默认为10。即规定斜面的长度不能超过线条宽度的10倍,当斜面的长度达到线条宽度的10倍时,就会变成斜角。如果lineJoin属性值为round或bevel时,miterLimit属性无效

3.4 虚线(IE11开始支持)

setLineDash(Array):指定线段与间隙的交替

lineDashOffset属性设置起始偏移量

3.5 线性渐变

createLinearGradient(x0, y0, x1, y1):创建canvasGradient对象(0是开始点,1是结束点),该对象使用addColorStop(stop, color)方法上色。

stop:介于0.0 与 1.0的值,表示渐变中开始与结束之间的相对位置,渐变起点的偏移值为0,结束的偏移值为1.如果position值为0.5,则表示色标会出现在渐变的正中间。

color:在结束为止显示的css颜色值

addColorStop方法可添加多个色标。

 1        var lingrad = ctx.createLinearGradient(0,0,0,200)
 2        lingrad.addColorStop(0, '
 3        lingrad.addColorStop(1/3, '
 4        lingrad.addColorStop(2/3, '
 5        lingrad.addColorStop(1, '
 6        ctx.fillStyle = lingrad
 7        ctx.strokeStyle = lingrad
 8        ctx.fillRect(0,0,300,200)

3.6 径向渐变

createRadialGradient(x0, y0, r0, x1, y1, r1):创建canvasGradient对象(0是开始点,1是结束点),该对象使用addColorStop(stop, color)方法上色。

3.7 图案

createPattern(image, “repeat | repeat-x | repeat-y | no-repeat”);方法绘制图案效果

第二参数依次实现 水平和垂直方向重复 | 只在水平方向重复| 只在垂直方向重复| 不重复

 1  var img = new Image()
 2        img.src = '/1.jpg'
 3        img.onload = function(){
 4            var ptrn = ctx.createPattern(img, 'repeat')
 5            ctx.fillStyle = ptrn
 6            ctx.fillRect(0,0,200,200)
 7        }

3.8 阴影

shadowColor:设置阴影颜色

shadowBlur:设置阴影的模糊级别

shadowOffsetX:阴影在x轴的偏移距离

shadowOffsetY:y轴的偏移距离

 1ctx.shadowOffsetX = 4
 2ctx.shadowOffsetY = 4
 3ctx.shadowBlur = 4
 4ctx.shadowColor = "rgba(0,0,0,0.5);
 5ctx.font = "60px Times New Roman";
 6ctx.fillStyle = "Black";
 7ctx.fillText("canvas API", 5,80);
 8

3.9 填充规则

fill(“nonzero|evenodd”)方法可以填充图形;内两个值分别为非零环绕数规则|奇偶规则

填充规则根据某处在路径的外面或者里面来决定是否被填充,这对于路径相交或者路径被嵌套的时候用。IE暂不支持evenodd填充规则

4 图形变形

4.1 保存和恢复状态

canvas状态存储在栈中,一个绘画状态包括两部分

(1)当前应用的变形,如移动、旋转和缩放,包括的样式属性:strokeStyle、fillStyle、globalAlpha、lineWidth、lineCap、lineJoin、miterLimit、shadowOffsetX、shadowOffsetY、shadowBlur、shadowColor、globalCompositeOp

eration

(2)当前的裁切路径,参考4.5介绍

save()方法:将当前的状态推送到栈中保存

restore()方法:将上一个保存的状态从栈中弹出,回复上一次所有的设置

 1      var c = document.getElementById('myCanvas')
 2        var ctx = c.getContext("2d") //返回一个画布渲染上下文对象,使用该对象可以在canvas元素中绘制图形,参数“2d”表示二维绘图
 3        ctx.fillStyle = "#ff00ff"
 4        ctx.strokeStyle = "blue"
 5        ctx.fillRect(50, 25, 100, 50)
 6        ctx.strokeRect(50, 25, 100, 50)
 7        ctx.fill()
 8        ctx.stroke()
 9        //保存
10        ctx.save()
11
12        ctx.fillStyle = "#ff0000"
13        ctx.strokeStyle = "green"
14        ctx.fillRect(180, 25, 100, 50)
15        ctx.strokeRect(180, 25, 100, 50)
16        ctx.fill()
17        ctx.stroke()
18        //恢复
19        ctx.restore()
20        ctx.fillRect(50, 100, 100, 50)
21        ctx.strokeRect(180, 100, 100, 50)

4.2 清除画布

clearRect(x, y, width, height)

参数依次对应:要清除的矩形左上角x坐标,y坐标,宽度,高度

4.3 移动坐标

在默认状态下,画布以左上角(0,0)为原点作为绘图参考。使用translate(dx, dy)方法移动坐标原点。

注意:在使用translate方法之前,应该先使用save方法保存画布的原始状态,当需要时可以使用restore方法恢复原始状态,特别是在重复绘图时非常重要。

4.4 旋转坐标

rotate(angle);方法可以以原点为中心旋转canvas上下文对象的坐标空间。参数为旋转角度,以顺时针方向为证方向,以弧度为单位。

提示:如需将角度转换为弧度,可以使用 degrees*Math.PI/180 公式进行计算,degrees为度数。

4.5 缩放图形

scale(x, y)方法增减canvas上下文对象的像素数目,从而实现图形的放大和缩小,x为横轴的缩放因子,y为纵轴的缩放因子,值必须是正值。

4.6 变换图形

transform(a,b,c,d,e,f)方法可以同时缩放、旋转、移动和倾斜当前的上下文环境;参数对应为水平缩放绘图,水平倾斜绘图,垂直倾斜绘图,垂直缩放绘图,水平移动绘图,垂直移动绘图

提示:

translate(x, y)可以用 transform(0,1,1,0,dx,dy)或 transform(1,0,0,1,dx,dy)替代

scale(x,y)可以用 transform(m11,0,0,m22, 0, 0)或 transform(0 ,m12, m21, 0, 0, 0)替代,m11、m22或 m12、m21为沿x,y轴放大的倍数

rotate(angle)可以用 transform(cosθ, sinθ, -sinθ, cosθ, 0, 0)替代,θ为旋转角度的弧度值

setTransform(m11, m12, m21, m22, dx, dy)方法将当前的变换矩阵进行重置为最初的矩阵,然后以相同的参数调用transform方法。

 1   var c = document.getElementById('myCanvas')
 2        var ctx = c.getContext("2d") //返回一个画布渲染上下文对象,使用该对象可以在
 3        //使用scale、translate、rotate实现图形呈螺旋状由大到小变化
 4        ctx.translate(200,20)
 5        for (let i = 1
 6            ctx.save()
 7            ctx.translate(30,30)
 8            ctx.scale(0.95,0.95)
 9            ctx.rotate(Math.PI/12)
10            ctx.beginPath()
11            ctx.fillStyle = "red"
12            ctx.globalAlpha = "0.4"
13            ctx.arc(0,0,50,0,Math.PI*2,true)
14            ctx.closePath()
15            ctx.fill()
16        }
17
18        //使用setTransform将前面已经发射变换的矩阵首先重置为最初的
19        //矩阵,即恢复最初的原点,然后再将坐标原点改为(10,10),
20        //并以新的坐标为基准绘制一个蓝色的矩形
21        ctx.setTransform(1,0,0,1,10,10)
22        ctx.fillStyle = "blue"
23        ctx.fillRect(0,0,50,50)
24        ctx.fill()

5 图形合成

5.1 合成

当两个或两个以上的图形存在重叠区域时,默认情况下一个图形画在前一个图形之上。通过指定图形globalCompositionOperation属性的值可以改变图形的绘制顺序或绘制方式,从而实现更多种可能。以下为对应值(方块为A,圆为B)

source-over/destination-over/source-atop/destination-atop/source-in/destination-in/source-out/destination-out/lighter/darker/copy/xor

5.2 裁切

clip()方法从原始画布中剪切任意形状和尺寸,其原理与绘制普通canvas图形类似,只不过clip的作用是形成一个蒙版,没有被蒙版的区域会被隐藏。

提示:一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内,不能访问画布上的其他其余。用户也可以在使用clip方法前,通过save方法对当前画布区域进行保存,并在以后得任意时间通过restore方法进行恢复

6 绘制文本

6.1 填充文字

fillText(text, x, y, maxWidth)

参数依次为、;规定在画布上输出的文本;开始绘制文本的x坐标;开始绘制文本的y坐标;可选参数,允许的最大文本宽度,单位是像素。

6.2 轮廓文字(文档艺术字效果)

strokeText(text, x, y, maxWidth)

6.3 文本样式

文本样式相关属性

font:定义字体样式,语法同css字体样式,默认 10px sans-serif

textAlign:设置正在绘制的文本的对齐方式。可取值start(默认,开始位置)/ end / center / left / right

textBaseline:设置文本基线对齐方式,即文本垂直对齐方式。可取值 alphabetic(默认值,普通的字母基线对齐) / top (em方框顶端对齐) / hanging(悬挂基线) / middle(em方框的正中对齐) / ideographic(表意基线对齐) / bottom (em方框底端对齐)

ps:大部分浏览器不支持 hanging 和 ideographic

direction:文本方向。取值 ltr(从左到右)/rtl(从右到左)/ inherit(默认,继承)

 1    var c = document.getElementById("myCanvas")
 2    var ctx = c.getContext("2d")
 3    ctx.strokeStyle = "blue"
 4    ctx.moveTo(0,100)
 5    ctx.lineTo(400,100)
 6    ctx.stroke()
 7    ctx.font = "20px Arial"
 8    //在 y=100 以不同的textBaseline处绘制文字
 9    ctx.textBaseline = "top"
10    ctx.fillText("Top", 5, 100)
11    ctx.textBaseline = "bottom"
12    ctx.fillText("Bottom", 50, 100)
13    ctx.textBaseline = "middle"
14    ctx.fillText("Middle", 120, 100)
15    ctx.textBaseline = "alphabetic"
16    ctx.fillText("Alphabetic", 190, 100)
17    
18
19    ctx.moveTo(100,0)
20    ctx.lineTo(100,400)
21    ctx.stroke()
22    ctx.font = "20px Arial"
23    //在 y=100 以不同的textBaseline处绘制文字
24    ctx.textAlign = "start"
25    ctx.fillText("Start", 100, 40)
26    ctx.textAlign = "end"
27    ctx.fillText("End", 100, 60)
28    ctx.textAlign = "left"
29    ctx.fillText("Left", 100, 80)
30    ctx.textAlign = "right"
31    ctx.fillText("Right", 100, 100)

6.4 测量宽度

measureText(text)方法测量当前所绘制文字中指定文字的宽度,返回一个TextMetrics对象,使用该对象的width属性可以得到指定文字参数后所绘制文字的总宽度。参数text为所绘制的文字字符串。常用来在文本向画布输出之前就了解文本的宽度。

如:ctx.measureText(‘HRLLO WORD’).width 获取’HRLLO WORD’宽度

7 使用图像

7.1 导入图像

(1)确定图像来源

(2)使用drawImage()方法将图像绘制到canvas中

确定图像来源方式:

<1>页面内的图片:如果已知图片元素的ID,则可以通过document.images集合、document.getElementsByTagName()或 document.getElementById()等方法获取页面内的该图片元素

<2>其他canvas元素:可以通过document.getElementsByTagName()或document.getElementById()等方法获取已经设计好的canvas元素

<3>js创建一个新的image对象:使用js从零创建一个新的image对象。但是缺点为如果图像文件来源于网络且较大,则会花费较长的时间来装载,所以要做好预装载工作。

<4>使用data:url 方式引用图像:该方法允许用base64编码的字符来定义一个图片,优点是图片即时使用不必等待装载,而且迁移容易。缺点是无法缓存图像,所以图片较大不适宜,会导致嵌入的url数据相当庞大

预装载解决方案:

 1//使用onload事件一边装载图像一边绘制图像的函数
 2var img = new Image()
 3img.onload = function(){
 4//放置drawImage的语句
 5}
 6img.src='image1.png'

在画布上定位图像:drawImage( img, x, y);

在画布上定位图像并规定图像的宽度和高度:drawImage( img, x, 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:要使用的图像的高度,可以实现伸展或缩小图像

7.2 缩放图像

drawImage( img, x, y, width, height);

7.3 裁切图像

drawImage(img, sx, sy, swidth, sheight, dx, dy, dwidth, dheight);

7.4 平铺图像

即让图像填满画布

<1>drawImage实现

<2>createPattern( image, type)实现,type取值no-repeat/repeat-x/repeat-y/repeat;创建image对象,指定图像文件后,使用createPattern方法创建填充样式,然后将该样式指定给图形上下文对象fillStyle属性,最后填充画布。

 1var img = "image/1.png"
 2var ptrn = ctx.createPattern(img , 'repeat')
 3ctx.fillStyle = ptrn
 4ctx.fillRect(0,0,300,200)

8 像素操作

8.1 认识ImageData对象

表示图像数据,存储canvas对象真实的像素数据,它包含以下几个只读属性:

width:返回ImageDtata对象的宽度,单位像素

height:返回ImageDtata对象的高度,单位像素

data:返回一个对象,其包含指定的ImageData对象的图像数据,为数组,包含着RGBA格式的整型数据,范围在0-255,通过图像数据可以查看画布初始像素数据,每个像素用4个值来代表,分别是红、绿、蓝和透明值。数组格式[ r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3,…],像素是从左到右,自上而下。

8.2 创建图像数据

以指定的尺寸创建新的ImageData对象(所有像素被预设为透明黑): var imaData = context.createImageData( width, height)

创建一与指定的另一个ImageData对象尺寸相同的新ImageData对象(不会复制图像数据): var imaData = context.createImageData( imageData )

8.3 将图像数据写入画布

putImageData( imgData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight )

imgData:要写入画布对的ImageData对象

x:ImageData对象左上角的x坐标

y:ImageData对象左上角的y坐标

dirtyX:可选参数,在画布上放置图像的x轴位置

dirtyY:可选参数,在画布上放置图像的y轴位置

dirtyWidth:可选参数,在画布上绘制图像所使用的宽度

dirtyHeight:可选参数,在画布上绘制图像所使用的高度

8.4 在画布中复制图像数据

getImageData(x, y, width, height )

x:开始复制的左上角位置x坐标

y:开始复制的左上角位置y坐标

width:将要复制的矩形区域的宽度

height:将要复制的矩形区域的高度

8.5 保存图片

canvas.toDataURL( type, encoderOprions);返回一个包含图片展示的dataURI;type:可选参数,默认为image/png;encoderOptions:可选参数,默认为0.92,在指定图片格式为 image/jpeg或image/webp的情况下,可以设置图片的质量,取值为0-1,超出范围使用默认值

canvas.toBlob( callback, type, encoderOptions )将画布存储到Blob对象中,泳衣展示canvas上的图片,这个图片文件可以被缓存或保存到本地,当存储色成功时调用 callback回调函数,可获取一个单独的Blob对象参数,另外两个参数同上

提示:data URI指目前大多数浏览器能够识别的一种base64位编码的URI,主要用于小型的、可以在网页中直接嵌入,而不需要从外部文件嵌入的数据,如img元素中的图像文件等

9 Path2D对象

参考内容:developer.mozilla.org/zh-CN/docs/…

9.1 Canvas 2D API新功能

(1)新增Path2D对象

允许用户存储路径,简化了canvas绘制代码,并提升了运行速度。用户可以通过三种方式创建: new Path2D();(空的path对象);new Path2D(path);(复制的path对象)new Path2D(d);(通过SVG path字符串创建path对象)

(2)点击区域

需要用户设置canvas.hitregions.enabled = true来测试,点击区域提供了一个更方便来探测鼠标是否在一个特定区域,不再手动检查坐标。定义点击区域方法:

CanvasRenderingContext2D.addHitRegion() //在canvas中添加一个点击区域

CanvasRenderingContext2D.removeHitRegion() //在canvas中移除一个带有id的点击区域

CanvasRenderingContext2D.clearHitRegion() //在canvas中移除所有的点击区域

addHitRegion方法可以在一个现有的路径或是一个Path2D路径中添加一个点击区域,MouseEvent接口有一个扩展的region属性,用户可以用来检查鼠标是否点击了区域

(3)焦点环

drawFocusIfNeeded( element ) 可以无须属性切换自定支持。如果在canvas元素中提供的回退元素获得焦点,用户可以使用这个API在canvas中绘制一个焦点环

(4)CSS/SVG过滤器可用于canvas

canvas渲染内容的过滤器,语法和CSS过滤器属性相同

(5)其他

alpha属性在Firefox 30中可用

可以在样式中添加transformations

新增ctx.resetTransform重置变形

9.2 使用Path2D对象

path.moveTo(x, y):将光标移动到指定坐标点

path.lineTo(x, y):在当前坐标点与参数中指定的直线重点之间绘制一条直线

path.rect(x, y, width, height):绘制矩形

path.arc(x, y, r, sAngle, eAngle, counterclockwise):绘制圆形或圆弧

path.ellipse(x, y, rX, rY, rotation, sAngle, eAngle, counterclockwise):绘制椭圆或椭圆形圆弧

path.arcTo(x, y):绘制圆形曲线或圆弧曲线

path.bezierCurveTo(cpx, cpy, x, y):绘制贝塞尔曲线

path.quadraticCurveTo(cpx, cpy, x, y):绘制二次元曲线

path.closePath():闭合路径

可以使用图形上下文对象的fill()方法填充使Path2D对象绘制的路径所形成的图形,或者使用图形上下文对象的stroke()方法绘制使用Path2D对象绘制的路径所形成的图形轮廓。参数为对应path对象

 1var canvas = document.getElementById("myCanvas")
 2var ctx = canvas.getContext("2d")
 3var path = new Path2D()
 4path.arc(25, 25, 10, 0, Math.PI*2, true)
 5path.closePath()
 6ctx.fillStyle = 'rgba(255,0,0,0.25)'
 7ctx.fill(path)

可以使用Path2D对象的addPath方法将一个Path2D对象所代表的路径添加到另一个Path2D对象所代表的路径中:path2.addPath( path1 )

个人笔记记录 2021 ~ 2025