文章目录
H5 canvas学习笔记
简介
HTML有两个主要的2D图形技术:Canvas和SVG
| canvas | svg |
|---|---|
| 2D | 2D |
| 基于JavaScript动态生成 | 使用XML静态描述 |
| 不会保留绘制的图形的信息,基于像素点绘制位图,放大会会失真 | 内存中保留绘制的图形的信息,用html标签描绘形状,矢量图放大不会失真 |
| canvas无法对已经绘制的图像进行修改、操作 如果发生修改,需要重绘 | svg中每个图形又对应真实的dom节点、svg可以获取到标签进行操作 |
H5 Canvas就是使用JavaScript来操作Canvas元素(画布)的技术。
①获取Canvas对象(画布)
②获取渲染上下文环境对象context(画笔)
③开始绘制图形
所有canvas图形操作的属性和方法都是基于context对象
Canvas画布/画笔
坐标系是二维x/y轴,像素为最小单元(栅格),每个像素具有RGBA数据,像素数量等于画布长*宽

- canvas画布的大小
- 可以是行间样式
- 可以通过
canvas.width/canvas.height设置和获取画布的大小
- canvas画笔
- 2d画笔
canvas.getContext('2d') - 3d画笔
canvas.getContext('webgl')或者canvas.getContext('webgl2')
- 2d画笔
<body>
<canvas id="canvas">不支持时的提示文字</canvas>
</body>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
</script>
1.Canvas标签中的文字是在不支持Canvas标签的浏览器中使用的,因为支持Canvas标签的浏览器会忽略容器中包含的内容正常渲染Canvas标签,而不支持Canvas标签的浏览器则相反,浏览器会忽略容器而显示其中的内容。
2.Canvas标签的默认大小为:300 x 150 (像素)
Canvas路径
在Canvas中,除了矩形,其他所有的Canvas基本图形(适用范围)都是以路径为基础。
| 方法 | 说明 |
|---|---|
| beginPath() | 开始一条新路径 |
| closePath() | 封闭当前路径 |
| isPointInPath(x,y) | 判断某一个点(x,y)是否存在当前路径内 |
beginPath():新建一条路径,判断是否同一路径的标准是是否使用了beginPath方法。closePath():闭合路径,连接起点与终点,封闭当前路径:closePath是指将同一路径的起点和终点连接起来,使其成为一个封闭图形。isPointInPath(x,y):不支持Canvas自带的两个方法strokeRect()和fillRect(),只能用rect()
Canvas状态
Canvas基于"状态"来绘制图形,每一次绘制(stroke或者fill),Canvas会检测整个程序定义的所有状态(strokeStyle、fillStyle、lineWidth等)。
①如果开启了一个新路径,则不同路径使用不同的值
②如果没有开启新路径,后面的值会覆盖前面的值
绘图样式必须先于矩形绘制方法之前,把相应参数设置好,canvas再根据已设置的参数来画图。
状态属性
状态包括:填充效果、描边效果、线条效果、文本效果、阴影效果和全局属性
- 填充效果:fillStyle
- 描边效果:strokeStyle
- 线条效果:lineCap、lineJoin、lineWidth、miterLimit
- 文本效果:font、textAlign、textBaseLine
- 阴影效果:shawBlu、shadowColor、shadowOffsetX、shadowOffsetY
- 全局属性:globalAlpha、globalCompositeOperation
globalAlpha属性定义Canvas环境的透明度,默认为1.0,取值范围为0.0~1.0
globalCompositeOperation属性改变图形交叉显示的顺序
| 属性值 | 说明 | 符号表示 |
|---|---|---|
| source-over | 默认值,新图覆盖旧图 | 新图B,旧图A |
| destination-over | 旧图A覆盖新图B | |
| copy | 只显示新图,旧图透明 | |
| darker | 两种图形都显示,在重叠部分颜色由两种图形的颜色值相减后形成 | |
| light | 两种图形都显示,在重叠部分颜色由两种图形的颜色值相加后形成 | |
| destination-atop | 只显示新图与旧图的重叠部分以及新图的其余部分 | A∩BUB |
| source-atop | 只显示新图与旧图的重叠部分以及旧图的其余部分 | A∩BUA |
| destination-in | 只显示旧图中与新图的重叠部分 | |
| source-in | 只显示新图中与旧图重叠的部分 | |
| destination-out | 只显示旧图中与新图不重叠的部分 | |
| source-out | 只显示新图中与旧图不重叠的部分 | |
| xor | 两图都绘制,重叠部分透明 |

状态的保存和恢复
- 保存当前状态sava()
- 恢复之前的保存状态restore()
Canvas的状态是存储在栈中的,每次调用save()方法后,当前的状态都会被推送到栈中保存起来。调用restore()方法,栈顶的状态被pop出来。
const ctx = canvas.getContext('2d');
ctx.fillStyle = "#cccccc";
ctx.fillRect(10, 10, 300, 100);
ctx.save(); // 保存状态
ctx.fillStyle = "#ee7034";
ctx.fillRect(10, 150, 300, 100);
ctx.restore(); // 还原到上次保存的状态
ctx.fillRect(10, 300, 300, 100);
基本图形stroke/fill
strokeStyle属性:设置边框样式stroke():通过线条来绘制图形轮廓,执行描边动作fillStyle属性:设置填充的颜色fill():通过填充路径的内容区域生成实心的图形。如果路径未关闭, fill() 方法会从路径结束点到开始点之间添加一条线,以关闭该路径,然后填充该路径。
直线moveTo()/lineTo()
context对象的moveTo(x1,y1):将画笔移动到(x1,y1)位置,表示直线的起点.。
context对象的lineTo(x2,y2):使用画笔从起点(x1,y1)开始画直线,一直画到终点(x2,y2)。
<body>
<canvas id="canvas"></canvas>
</body>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.moveTo(100,100); //
ctx.lineTo(100,200); //
ctx.stroke();//开始绘画
</script>
画多条直线
lineTo方法可以重复调用,默认是以上一次的终点位置作为本次的起点位置。
矩形trokeRect()/fillRect()/clearRect()/react()
矩形也可以使用四条直线来画,不过太复杂了。
Canvas API 给提供了三种绘制矩形的方法。
trokeRect(x, y, width, height)绘制一个矩形的边框fillRect(x, y, width, height)绘制一个填充的矩形clearRect(x, y, width, height)清除指定矩形区域,让清除部分完全透明。
trokeRect(x, y, width, height):绘制矩形边框- x和y 是矩形左上角的起点坐标
- width和height 是矩形的宽高
fillRect(x, y, width, height) 绘制一个填充的矩形
- x和y 是矩形左上角的起点坐标
- width和height 是矩形的宽高。
clearRect(x, y, width, height) 清除指定矩形区域,让清除部分完全透明
- x和y 是矩形左上角的起点坐标
- width和height 是矩形的宽高
rect(x,y,width,height) 绘制一个矩形,需要调用stroke()或fill()方法
绘图样式属性的取值
- 颜色值
- 十六进制颜色值
#FF0000 - 颜色关键字
red - rgb颜色
rgb(255,0,0) - rgba颜色值
rgba(255,0,0,0.8)
- 十六进制颜色值
- 渐变色
- 图案
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.fillRect(100, 100, 200, 100);
ctx.strokeRect(300, 300, 200, 100)
ctx.clearRect(100, 100, 100, 70);
</script>

圆弧和圆arc()
arc(x, y, radius, startAngle, endAngle, anticlockwise)
- x和y为圆心的坐标,radius为半径
- startAngle为圆弧或圆的开始位置(弧度),endAngle为圆弧或圆的结束位置(弧度)
- anticlockwise是绘制的方向,默认为false(顺时针方向)
- 需要结合stroke()函数
在画弧的时候,arc()函数中角的单位是弧度而不是角度。
角度换算为弧度的表达式为:弧度=(Math.PI/180)*角度。
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// 绘制一段圆弧
ctx.arc(60, 60, 50, 0, Math.PI, false);
ctx.stroke();
// 绘制一个圆弧
ctx.arc(300, 300, 50, 0, Math.PI*2, false);
ctx.stroke();
</script>

关闭路径其实并不是必须的,对于新路径其实每次都开启新路径就ok。
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// 绘制一段圆弧
ctx.beginPath() // 开启路径
ctx.arc(60, 60, 50, 0, Math.PI, false);
ctx.stroke();
// 绘制一个圆弧
ctx.beginPath() // 开启路径
ctx.arc(300, 300, 50, 0, Math.PI*2, false);
ctx.stroke();
</script>

<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.beginPath()
ctx.arc(60, 60, 50, 0, Math.PI, false);
ctx.strokeStyle="pink";
ctx.closePath()
ctx.stroke();
</script>

椭圆ellipse()
ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
- x、y:椭圆的圆心位置
- radiusX、radiusY:x轴和y轴的半径
- rotation:椭圆的旋转角度,以弧度表示
- startAngle:开始绘制点
- endAngle:结束绘制点
- anticlockwise:绘制的方向,默认顺时针,可选参数。
贝塞尔曲线
贝塞尔曲线一般用来绘制复杂有规律的图形,通常被用于画曲线。
常见的贝塞尔曲线:起点一般由moveTo()或lineTo()提供
- 二次贝塞尔
quadraticCurveTo(cx,cy,x,y)- (cx,cy)表示控制点的坐标
- (x,y)表示结束点的坐标
- 三次贝塞尔
bezierCurveTo(cx1,cy1,cx2,cy2,x,y)- (cx1,cy1)表示控制点1
- (cx2,cy2)表示控制点2
- 结束点
可以通过二次/三次贝塞尔曲线调试工具查看效果
二次贝塞尔案例
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.moveTo(50, 50);//起点
ctx.quadraticCurveTo(200, 200, 350, 50);//控制点
ctx.stroke();//结束点

三次贝塞尔案例
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.moveTo(50, 200);
ctx.bezierCurveTo(150, 50, 250, 350, 350, 200);
ctx.stroke();

线条的操作
lineWidth设置当前绘线的粗细,属性值为正数,默认值为1,单位为pxlineCap设置线段端点显示的样子。- butt:默认值,默认无处理
- round:每条线的开始处和结尾处都增加一个半圆,半圆的直径为线宽
- square:每条线的开始处和结尾处都增加一个长方形,长为线宽的一半,高为线宽
lineJoin设置两条线条交接处样式miter:默认是尖角round:圆角,圆角所在圆的直径等于线宽bevel:斜角,斜角所在正方形的对角线长等于线宽
setLineDash(array)定义线条的虚实样式- [虚线长度px,空白长度px,…(重复)]
getLineDash()返回当前虚线设置的样式lineDashOffset设置虚线样式的起始偏移量
在同一个路径中,状态会被一直使用。所以如果需要定义一个新的线条样式,使用beginPath()方法开启一个新路径。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// lineJoin 值为 miter
ctx.beginPath()
ctx.lineWidth = 40;
ctx.lineJoin='miter'
ctx.moveTo(50, 20);
ctx.lineTo(100, 60);
ctx.lineTo(150, 20);
ctx.lineTo(200, 60);
ctx.lineTo(250, 20);
ctx.stroke();
ctx.closePath();
// lineJoin 值为 round
ctx.beginPath()
ctx.lineWidth = 40;
ctx.lineJoin='round'
ctx.moveTo(50, 100);
ctx.lineTo(100, 140);
ctx.lineTo(150, 100);
ctx.lineTo(200, 140);
ctx.lineTo(250, 100);
ctx.stroke();
ctx.closePath();
// lineJoin 值为 bevel
ctx.beginPath()
ctx.lineWidth = 40;
ctx.lineJoin='bevel'
ctx.moveTo(50, 180);
ctx.lineTo(100, 220);
ctx.lineTo(150, 180);
ctx.lineTo(200, 220);
ctx.lineTo(250, 180);
ctx.stroke();
ctx.closePath();

渐变
线性渐变
createLinearGradient(x1, y1, x2, y2)创建LinearGradient渐变对象,参数分别为渐变的起点坐标和终点坐标。- 渐变对象的实例
addColorStop(offset, color)添加渐变的颜色,color为颜色,offset表示渐变位置的偏移量(百分比:0~1)。第一次表示渐变的开始颜色,第二次调用表示结束,第三次以上一次结束为起点进行渐变,依次类推。 - 将LinearGradient渐变对象赋值给
fillStyle属性 - 进行绘图
fill()、fillRect()图形渐变、fillText()文字渐变
gradient1.addColorStop(0, "#00ff00");
gradient1.addColorStop(1, "#ff0000");
ctx.fillStyle = gradient1
ctx.fillRect(0,0,200,200)
径向渐变
ctx.createRadialGradient(x0, y0, r0, x1, y1, r1)参数分别为开始圆的坐标(x0,y0)和半径r0以及结束圆的坐标(x1,y1)和半径r1。
图像
Canvas中想绘制图案效果,需要用createPattern(image, type) 方法来实现
- Image 参数可以是一个 Image 对象,也可以是一个 canvas 对象
- Type 为图案绘制的类型,可用的类型分别有:repeat,repeat-x,repeat-y 和 no-repeat。
// 获取绘图上下文
const ctx = canvas.getContext('2d');
// 创建一个 image对象
const img = new Image();
img.src = "./image.png";
img.onload = function() {
// 图片加载完以后
// 创建图案
const ptrn = ctx.createPattern(img, 'no-repeat');
ctx.fillStyle = ptrn;
ctx.fillRect(0, 0, 500, 500);
}
绘制文本
canvas 中提供了两种方法来渲染文本①描边②填充
ctx.strokeText(text, x, y, maxWidth)- text绘制的文案
- x、y文本的起始位置
- maxWidth可选参数,最大宽度。当文案大于最大宽度时不是裁剪或者换行,而是缩小字体。
ctx.fillText(text, x, y, maxWidth)- text绘制的文案
- x、y文本的起始位置
- maxWidth可选参数,最大宽度。当文案大于最大宽度时不是裁剪或者换行,而是缩小字体。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.font = "50px serif"; // 设置文案大小和字体
ctx.strokeText("Canvas", 100, 100);
ctx.fillText("Canvas", 100, 100);
文本样式
- font属性:绘制文案大小和字体,默认”10px sans-serif“
- textAlign属性:文本对齐的方式。可选值为:left、right、center、start(默认)和end。
- direction属性:文本的方向。可选值为:ltr(从左向右)、rtl(从右向左)、inherit(根据情况继承 Canvas元素或者 Document ,默认)
- textBaseline属性:基线对齐选项,决定文字垂直方向的对齐方式。可选值为:top、hanging、middle、alphabetic(默认)、ideographic和bottom。
direction 属性会对 textAlign 属性产生影响。如果 direction 属性设置为 ltr,则textAlign属性的 left 和 start 的效果相同,right 和 end 的效果相同,如果 direction 属性设置为 rtl,则 textAlign属性的 left 和 end 的效果相同,right 和 start 的效果相同。
阴影
- shadowOffsetX、shadowOffsetY设定阴影在 X 和 Y 轴的延伸距离,不受变换矩阵影响。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0。
- shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,不受变换矩阵的影响,默认为 0。
- shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。
图片操作
drawImage()
drawImage可以将图片导入Canvas进行平铺、切割、像素处理等操作。
必须等图片载入完成后开始绘制
drawImage()的用法有三种,根据不同的传参实现不同的功能。
- image:绘制到上下文(页面)的图片,可以是页面中的img元素,也可以是JavaScript创建的image对象。
- sx、sy(source):裁剪框的左上角X轴坐标和Y轴坐标
- sWidth、sHeight:裁剪框的宽度和高度。
- dx、dy(destination):绘制到上下文(页面)的元素,在上下文中(页面)左上角的X轴坐标和Y轴坐标。
- dWidth、dHeight:绘制到上下文(页面)的元素,在上下文(页面)中绘制的宽度和高度。如果不说明,在绘制时image宽度和高度不会缩放。
绘制
drawImage(image,dx,dy):单纯的绘制功能,可以绘制图片、视频和别的Canvas对象等。
//从javaScript动态创建
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const img = new Image(); //创建image对象
img.src = '';
//图片载入完成后开始绘制
img.onload = function(){
ctx.drawImage(img, 0, 0);
}
//来自img元素,优点在于JavaScript执行时图片已经加载完成,一般会使用css隐藏图片元素,可以避免在DOM中再显示一次图片
缩放
drawImage(image, dx, dy, dWidth, dHeight):dWidth和dHeight可以控制绘制元素的大小。
裁剪
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)可以裁剪图片后绘制
裁剪 clip()
clip() 将当前正在构建的路径转换为当前的裁剪路径,不支持Canvas自带的两个方法strokeRect()和fillRect(),只能用rect()。
默认情况下,canvas 有一个与它自身一样大的裁剪路径(也就是没有裁剪效果)。现在可以通过clip()来创建一个裁剪路劲(也就有裁剪效果了)。裁剪的作用是遮罩,用来隐藏不需要的部分,所有在路径以外的部分都不会在 canvas 上绘制出来。
裁剪路径不会在 canvas 上绘制东西,永远不受新图形的影响。超过剪切区域的部分不会被显示。
案例
1.绘制基本图形作为裁剪路径
2.使用clip()方法
3.绘制图片
//1.绘制基本图片,用于裁剪
ctx.arc(200,200,50,0,360*Math.PI/180,true);
ctx.stroke();
//2.创建裁剪路径
ctx.clip()
//3.绘制图片
const img = new Image(); //创建image对象
img.src = '';
img.onload = function(){
ctx.drawImage(img, 0, 0);
}
像素
getImageData()获取一张图的像素
CanvasRenderingContext2D.getImageData(x,y,width.height) 返回一个 ImageData 对象,用来描述 canvas 区域隐含的像素数据。
这个区域通过矩形表示,x、y为左上角的横纵坐标,width和height表示所选区域的宽度和高度。
const imgData = ctx.getImageData(x, y, width, height);
ImageData 对象会有三个属性
height:使用像素描述ImageData的实际高度,这个值等于getImageData()方法中的参数heightwidth:使用像素描述ImageData的实际高度,这个值等于 getImageData() 方法中的参数widthdata:一个一维数组,保存像素数据,每4个数(R红G绿B蓝A透明度)存储1个像素的RGBA颜色值。ImageData.data.length表示一张图的像素总和。

说明getImageData()方法不允许操作此域名外的图片/视频资源- 可以将图片转换成base64编码,直接把base64编码赋值给图片的src属性就可以简单的解决这个问题了。
putImageData()设置一张图的像素
putImageData(image,x,y):image表示重新绘制的图形ImageData对象,x,y分别表示重新绘制的图形左上角的横坐标、纵坐标。
使用场景:通过getImageData获取到imageData后,然后进行处理,再通过putImageData绘制到canvas上,
本文介绍了H5canvas的基础知识,包括Canvas画布和画笔的使用,路径的创建,状态管理,如strokeStyle、fillStyle等属性,以及如何绘制直线、矩形、圆弧、椭圆和贝塞尔曲线。同时讲解了线条样式、渐变、阴影效果和图像处理,如drawImage方法。文章还涵盖了文本绘制和阴影效果,以及如何使用getImageData和putImageData进行像素操作。

2049

被折叠的 条评论
为什么被折叠?



