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 颜色
fillStyle和strokeStyle属性可以给图形上色,值为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 )