-
验证浏览器是否支持
<canvas id="myCanvas" width="400" height="400"> Your browser does not support HTML5 Canvas. </canvas>
function canvasAPP () { var myCanvas = document.getElementById('myCanvas'); if (!myCanvas || !myCanvas.getContext) { return; } // 这里开始绘制 var ctx = myCanvas.getContext('2d'); function drawScreen () { // ... } drawScreen(); }
-
绘制线段
ctx.strokeStyle
用于设置画笔绘制路径的颜色、渐变和模式ctx.lineWidth
定义绘制线条的宽度ctx.beginPath()
开始一个新的绘制路径ctx.moveTo(x,y)
移动画笔到指定的坐标点(x,y),该点就是新的子路径的起始点ctx.lineTo(x,y)
使用直线边接当前端点和指定的坐标点(x,y)ctx.stroke()
沿着绘制路径的坐标点顺序绘制直线ctx.closePath()
如果当前的绘制路径是打开的,则关闭掉该绘制路径ctx.setLineDash([])
绘制虚线,数组内可以传一个元素,两个或者三个分别表示线段,间隔大小-
ctx.lineCap
线帽,取值有butt、round和square
,其中默认的值是butt。
ctx.lineJoin
线段的连接点,取值有round、bevel和miter
,其中miter是其默认值,取值为miter时,还可以指定一个miterLimit属性。
-
如果绘制一条真正1像素宽的线段,你必须将该线段绘制在某两个像素之间的那个像素中(比如从
moveTo(30.5,100.5) lineTo(50.5,120.5)
),而不能将它绘制在两个像素的交界处。
-
对于save()和restore()方法,一开始有一个错误的理解,以为每一步都save()之后restore()就等同于command + z(或者ctrl + z),其实save()保存的只是CanvasRenderingContext2D对象的状态以及对象的所有属性,并不包括这个对象上绘制的图形。官方文档描述如下:
save()和restore()方法允许你保存和恢复一个CanvasRenderingContext2D对象的状态。save()把当前状态推入到绘图堆栈中,而restore()从绘图堆栈中的顶端弹出最近保存的状态,并且根据这些存储的值来设置当前绘图状态。
-
绘制矩形api
- fillRect(x, y, width, height):绘制一个填充的矩形
- strokeRect(x, y, width, height):绘制一个矩形的边框
- clearRect(x, y, width, height):清除指定矩形区域,让清除部分完全透明.经常用来清除干净画布,`ctx.clearRect(0,0,myCanvas.width,myCanvas.height);
- rect(x, y, width, height):也是Canvas中路径的一个方法,需要配合fill()和stroke()。
function drawScreen () { ctx.strokeStyle = '#000'; ctx.fillStyle = '#9f9' ; ctx.lineWidth = 4; // 绘制 ctx.beginPath(); ctx.rect(30,30,200,200); ctx.stroke(); // 绘制 ctx.beginPath(); ctx.rect(300,30,200,200); ctx.fill(); // 绘制既有边框又填充,注意因为lineWidth为4,fill方法的值大小 ctx.strokeRect(240,10,100,100); ctx.fillRect(242,12,96,96); }
-
在Canvas中,CanvasRenderingContext2D对象提供了两个方法(arc()和arcTo())来绘制圆和圆弧。其中arc()即可绘制弧线,圆,也可以绘制扇形,但arcTo()仅能绘制出弧线。但arcTo()可以更轻易的帮助我们实现带圆角的矩形。
-
arc(x, y, radius, startRad, endRad, [anticlockwise])
坐标点(x,y)为圆心、半么为radius的圆上的一段弧线。这段弧线的起始弧度是startRad,结束弧度是endRad。这里的弧度是以x轴正方向为基准、进行顺时针旋转的角度来计算。其中anticlockwise表示arc()绘制圆或圆弧是以顺时针还是逆时针方向开始绘制。如果其值为true表示逆时针,如果是false表示为顺时针。该参数是一个可选参数,如果没有显式设置,其值是false(也是anticlockwise的默认值)。 -
arcTo(x1, y1, x2, y2, radius)
arcTo()方法将利用当前端点、端点一(x1, y1)和端点二(x2, y2)这三点所形成的夹角,然后绘制一段与夹角的两边相切并且半径为radius的圆上的弧线。弧线的起点就是当前端点所在边与圆的切点,弧线的终点就是商端点二(x2,y2)所在边与圆的切点,并且绘制的弧线是两个切点之间长度最短的那个圆弧。此外,如果当前端点不是弧线起点,arcTo()方法还将添加一条当前端点到弧线起点的直线线段。
-
-
Canvas坐标变换有移动、旋转和缩放
- ctx.translate(x, y) :translate方法接受两个参数。x是左右偏移量,y是上下偏移量。当偏移量操作出Canvas的width或height时,坐标将会移出Canvas的画布,这个时候你绘制的东西都将看不到。
- ctx.rotate(angle) :rotate()方法只接受一个参数,旋转的角度angle,它是顺时针方向的,以弧度为单位的值。
- ctx.scale(x, y) :scale()方法接受两个参数。x和y分别是横轴和纵轴的缩放因子。其缩放因子默认是1,如果比1小是缩小,如果比1大则放大。在绘制了某个图形后,可以调用ctx.scale(-1, 1)来绘制其水平镜像或者调用ctx.scale(1, -1)来绘制其垂直镜像(这里只是把坐标系翻转,翻转后还需要再绘制一遍要镜像的图形)。
Canvas中可以通过ctx.fillText("内容",x,y,maxWidth)绘制填充文本,ctx.strokeText()可以绘制描边文本,另外通过ctx.textAlign和ctx.textBaseline设置所绘制文本的位置,并且使用ctx.measureText('text').width可以得到所绘制文本text的宽度值,虽然这个值并不精确
-
在Canvas中有两个属性globalAlpha和globalCompositeOperation来控制图像合成操作:
- globalAlpha:设置图像的透明度。globalAlpha属性默认值为1,表示完全不透明,并且可以设置从0(完全透明)到1(完全不透明)。这个值必须设置在图形绘制之前。
- globalCompositeOperation:该属性的值在globalAlpha以及所有变换都生效后控制在当前Canvas位图中绘制图形
// 上面是目标图像(已有),下面是源图像(新的); // source-over 默认。在目标图像上显示源图像。 // source-atop 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。 // source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。 // source-out 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。 // destination-over 在源图像上方显示目标图像。 // destination-atop 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。 // destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。 // destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。 // lighter 显示源图像 + 目标图像。 // copy 显示源图像。忽略目标图像。 // source-over 使用异或操作对源图像与目标图像进行组合。 ctx.globalCompositeOperation = "source-over";
-
clip()方法将剪切区域设置为当前剪切区域与当前路径的交集。在第一次调用clip()方法之前,剪切区域与整个Canvas画布大小一致。因为clip()方法会将剪切区域设置为当前剪切区域与当前路径的交集,所以对该方法的调用一般都是嵌入save()和restore()方法之间的。否则,剪切区域将会越变越小,这通常不是我们想要的效果。
- Canvas中的clip()方法用于从原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。也可以在使用clip()方法前通过使用save()方法对当前画布区域进行保存,并在以后的任意时间通过restore()方法对其进行恢复。
- [实现探照灯效果](https:// www.w3cplus.com/canvas/clip.html)
-
ImageData操作,无论时getImageData还是putImageData都是针对画布来说的,拿到画布上的像素。一般可以结合drawIamge来用,先把图片通过drawImage绘制到图像上,然后再通过getImageData获取像素数据,循环修改其中的data属性,最后再通过putImageData,把修改后的imageData放回到画布。
-
createImageData() 方法创建新的空白 ImageData 对象。新对象的默认像素值 transparent black。
对于 ImageData 对象中的每个像素,都存在着四方面的信息,即 RGBA 值:
R - 红色 (0-255)
G - 绿色 (0-255)
B - 蓝色 (0-255)
A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
因此 ,transparent black 表示 (0,0,0,0)。
color/alpha 以数组形式存在,并且既然数组包含了每个像素的四条信息,数组的大小是 ImageData对象的四倍。(获得数组大小有更简单的办法,就是使用 ImageDataObject.data.length)。
注意:包含 color/alpha 信息的数组存储于 ImageData 对象的 data 属性中。// 1. 以指定的尺寸(以像素计)创建新的 ImageData 对象: var imgData=ctx.createImageData(width,height); // 2. 创建与指定的另一个 ImageData 对象尺寸相同的新 ImageData 对象(不会复制图像数据): var imgData=ctx.createImageData(imageData);
-
getImageData() 方法返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。
// x 开始复制的左上角位置的 x 坐标。相对与canvas // y 开始复制的左上角位置的 y 坐标。 // width 将要复制的矩形区域的宽度。 // height 将要复制的矩形区域的高度。 var imgData=context.getImageData(x,y,width,height); // 返回的 ImageData 对象中第一个像素的 color/alpha 信息,注意这里只是第一个像素,每个像素占数组的四个元素 red=imgData.data[0]; green=imgData.data[1]; blue=imgData.data[2]; alpha=imgData.data[3];
-
putImageData() 方法将图像数据(从指定的 ImageData 对象)放回画布上
// imgData 规定要放回画布的 ImageData 对象。 // x ImageData 对象左上角的 x 坐标,以像素计。 // y ImageData 对象左上角的 y 坐标,以像素计。 // dirtyX 可选。水平值(x),以像素计,在画布上放置图像的位置。 // dirtyY 可选。水平值(y),以像素计,在画布上放置图像的位置。 // dirtyWidth 可选。在画布上绘制图像所使用的宽度。 // dirtyHeight 可选。在画布上绘制图像所使用的高度。 ctx.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
ImageDate对象的三个属性
width 返回 ImageData 对象的宽度
height 返回 ImageData 对象的高度
data 返回一个对象,其包含指定的 ImageData 对象的图像数据
-
-
图像绘制,向画布上绘制图像、画布或视频
// img 规定要使用的图像、画布或视频。 // sx 可选。开始剪切的 x 坐标位置。 // sy 可选。开始剪切的 y 坐标位置。 // swidth 可选。被剪切图像的宽度。 // sheight 可选。被剪切图像的高度。 // x 在画布上放置图像的 x 坐标位置。 // y 在画布上放置图像的 y 坐标位置。 // width 可选。把图像绘制到画布上的宽度。(伸展或缩小图像) // height 可选。把图像绘制到画布上的高度。(伸展或缩小图像) ctx.drawImage(img,x,y); ctx.drawImage(img,x,y,width,height); ctx.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
-
如何把canvas画布转换成img图像,[更多canvas压缩图片操作](http:// www.zhangxinxu.com/wordpress/2017/07/html5-canvas-image-compress-upload/)
- canvas.toDataURL()方法,注意是canvas对象调用的方法
canvas.toDataURL(mimeType, qualityArgument)
可以把图片转换成base64格式信息,纯字符的图片表示法。
其中:
mimeType表示canvas导出来的base64图片的类型,默认是png格式,也即是默认值是'image/png',我们也可以指定为jpg格式'image/jpeg'或者webp等格式。file对象中的file.type就是文件的mimeType类型,在转换时候正好可以直接拿来用(如果有file对象)。
qualityArgument表示导出的图片质量,只要导出为jpg和webp格式的时候此参数才有效果,默认值是0.92,是一个比较合理的图片质量输出参数,通常情况下,我们无需再设定。- canvas.toBlob()方法
canvas.toBlob(callback, mimeType, qualityArgument)
可以把canvas转换成Blob文件,通常用在文件上传中,因为是二进制的,对后端更加友好。
和toDataURL()方法相比,toBlob()方法是异步的,因此多了个callback参数,这个callback回调方法默认的第一个参数就是转换好的blob文件信息,本文demo的文件上传就是将canvas图片转换成二进制的blob文件,然后再ajax上传的,代码如下:// canvas转为blob并上传 canvas.toBlob(function (blob) { // 图片ajax上传 var xhr = new XMLHttpRequest(); // 开始上传 xhr.open("POST", 'upload.php', true); xhr.send(blob); });
-
beginPath 的重要性,从下面代码开始
var ctx = document.getElementById('cvs').getContext('2d'); ctx.beginPath(); ctx.moveTo(100.5,20.5); ctx.lineTo(200.5,20.5); ctx.stroke(); ctx.moveTo(100.5,40.5); ctx.lineTo(200.5,40.5) ctx.strokeStyle = '#f00'; ctx.stroke();
其中的0.5是为了避免”1px线条模糊问题“,你懂的。那么上面的代码会得到什么样的图形呢?是不是一条黑线一条红线呢?
从代码上看,我们的逻辑毫无问题,但结果是我们得到的是两条红线,并不是一黑一红。
canvas中的绘制方法(如stroke,fill),都会以“上一次beginPath”之后的所有路径为基础进行绘制。比如上面的代码里面我stroke了两次,其实这两次都是以第一次beginPath后的所有路径为基础画的。也就是说第一条路径我们stroke了两下,第一下是黑的,第二下是红的,所以最终也是红的。- 不管你用moveTo把画笔移动到哪里,只要不beginPath,那你一直都是在画一条路径。
- fillRect与strokeRect这种直接画出独立区域的函数,也不会打断当前的path.
说到beginPath,就不得不提到closePath,两者是不是有很“紧”的联系呢?答案是几乎没有关系。
closePath的意思不是结束路径,而是关闭路径,它会试图从当前路径的终点连一条路径到起点,让整个路径闭合起来。但是,这并不意味着它之后的路径就是新路径了!
我们在上面的代码的第一个lineTo后面加上closePath,可以发现还是得到了两条红线。但如果我们在第一个stroke后面加上beginPath,则会如愿得到一条黑线一条红线。ctx.stroke(); ctx.beginPath(); // 注意啦! ctx.moveTo(100.5,40.5); ctx.lineTo(200.5,40.5) ctx.strokeStyle = '#f00'; ctx.stroke();