基础说明
标签
示例:
<canvas id="test" class="test" width="150" height="150"></canvas>
canvas 只有两个属性,一个是width,一个是height,默认值为300×150px,可以用css来定义canvas的宽高,但在绘制时图像会伸缩适应尺寸,宽高比不一致时图像会扭曲
为了预防IE9之前的浏览器,我们可以在canva里面添加替换内容,这样在浏览器不支持canvas时间可以显示对应的替换内容,例
<canvas id='test1' width="150" height="150">矩形</canvas>
渲染上下文
canvas起初可以认为是一个空白的画布,他公开了一个或者多个渲染上下文(),用于去绘制和处理内容本文暂时先讨论2D的渲染情况,以后说不定会学习一下3D。2D渲染上下文的获取示例如下:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
同样我们可以通过canvas的getContext()判断浏览器是否支持canvas,代码示例如下:
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
} else {
// 浏览器不支持canvas
}
绘制基本图形和线条
在绘制图形之前,我们先了解一下canvas在2D情况下的坐标体系,从下图中我们可以很明显的看出canvas的坐标系和我们数学中的略有不同
矩形
废话不说,直接上例子:
例子中的三个Rect的方法的参数意义都是一样的(x, y, width, height),x代表横坐标,y代表竖坐标,width代表图形的宽度,height代表图形的高度。
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillRect(25, 25, 100, 100); // 画一个填充的矩形
ctx.clearRect(45, 45, 60, 60); // 将矩形置为透明
ctx.strokeRect(50, 50, 50, 50); // 画一个矩形框
}
路径
图形是由路径构成的,我们会绘制路径就可以自由绘制很多图形了。我用windows自带的画图去理解的canvas函数,废话少说,直接看例子:
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath(); // 新建一条路径,图形的绘制位置将指向到对应位置,可以理解为画图的时候鼠标选择了绘制路径
ctx.moveTo(75, 50); // 鼠标移动到x为75px,y为70px的位置
ctx.lineTo(100, 75); // 鼠标摁住不动移动到坐标100,75的位置
ctx.lineTo(100, 25); // 鼠标保持摁住的状态移动到100,25
ctx.fill(); // 刚刚走过的路径包围起来的地方进行填充
// ctx.closePath(); // 闭合路径之后绘制命令又重新指向到上下文之中,可以理解为鼠标松开了
// ctx.stroke(); // 刚刚走过的路径用线条绘制
}
示例中closePath()和stroke()效果大家可以自己试一下看,,记得把fill()注释掉,其实在上面的例子中我们已经成功的绘制了三角形,同理大家可以自己绘制任何想要的由直线构成的图形。
那我们想要绘制曲线应该怎么办呢,那就要用到圆弧了
arc(x, y, radius, startAngle, endAngle, anticlockwise)
画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise(true或者false)给定的方向(默认为顺时针)来生成。
注意:在这里startAngle和 endAngle,代表的是弧度,不是角度。角度与弧度的js表达式
为:弧度=(Math.PI/180)*角度
arcTo(x1, y1, x2, y2, radius)
根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。下面是几个示例:
ctx.beginPath();
ctx.arc(300, 75, 50, 0 , Math.PI, true);
ctx.stroke();
ctx.beginPath();
ctx.arc(300, 75, 50, 0 , Math.PI, false);
ctx.fill();
ctx.beginPath();
ctx.moveTo(0,200);
ctx.arcTo(100, 200, 100, 300 , 100 );
ctx.stroke();
样式与颜色
颜色
fillStyle 是填充的颜色,strokeStyle是图形轮廓的颜色,使用方法:
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.strokeStyle = "rgb(255,165,0)";
ctx.strokeStyle = "rgba(255,165,0,1)";
我们在赋值之后,其后的图形颜色都会是这个,如果要每个图形颜色不一致,需要每次重新赋值。
透明度
我们在设置透明度时有两种方法,一种是使用rgba(相信大家都会),一种是使用globalAlpha,使用起来也比较简单:
ctx.globalAlpha = 0.2;
globalAlpha的影响范围也是后面所有的图形,如果不同的图形不一致,需要注意重新置为1
线条相关属性
lineWidth
设置线条宽度,使用时直接ctx.lineWidth 等于一个数值就好了
lineCap
设置线条末端的样式,共有三种butt
,round
和 square,默认是butt
三种的效果分别如下:
butt的话就是标准的直接横切,round的话线条两端会多出一个半圆,直径为线条的宽度,square会在两端多出宽度的一半
lineJoin
设置线条与线条连接处的样式,同样也是三个选项round,bevel和miter,默认是miter,三种效果分别如下
miterLimit
限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。通俗一点说就是lineJoin为miter的时候,也就是上图最后一种效果,当两个线条之间的夹角很小时,那个连接处的尖啊,会很长很长, 加上miterLimit这个属性就能把小于某些角度的连接线的尖直接给他削平。效果如下面两个的图展示的效果
至于这个东西怎么算呢,看一下别人写的吧
miterLimit
= maxmiterLength
/lineWidth
= 1 / sin ( min θ / 2 )- 斜接限定值默认为10.0,这将会去除所有小于大约11度的斜接。
- 斜接限定值为√2 ≈ 1.4142136 (四舍五入)时,将去除所有锐角的斜接,仅保留钝角或直角。
- 1.0是合法的斜接限定值,但这会去除所有斜接。
- 小于1.0的值不是合法的斜接限定值。
使用虚线
用 setLineDash
方法和 lineDashOffset
属性来制定虚线样式. setLineDash
方法接受一个数组,来指定线段与间隙的交替;lineDashOffset
属性设置起始偏移量。看示例:
ctx.setLineDash([4, 2]);
ctx.lineDashOffset = -offset;
ctx.strokeRect(10,10, 100, 100);
绘制文本
fillText(text, x, y [, maxWidth]) 在指定的(x, y)处绘制文字,绘制的最大宽度是可选的
strokeText(text, x, y [, maxWidth]) 在指定的(x, y)位置绘制文本边框,绘制的最大宽度是可选的
示例:
tx.font = "48px serif";
ctx.fillText("Hello world", 10, 50);
ctx.strokeText("Hello world", 10, 100);
文本样式
font 与css的font属性相同的语法,默认的字体是10px sans-serif
textAlign 设置文本对齐的选项,可选的值包括start,end,left,right,center;默认是start
textBaseline 基线对齐选项,可选的值包括:top, hanging,middle,alphabetic,ideographic,bottom;默认是alphabetic
direction 文本方向,可选的值包括:ltr,rtl,inherit。默认是inherit
预测量文本宽度
measureText 返回一个TextMetrics对象的宽度,所在像素,示例:
var ctx = document.getElementById('canvas').getContext('2d');
var text = ctx.measureText("foo"); // TextMetrics object
text.width; // 16;
绘制图像
1、获取图像
HTMLImageElement 使用Image() 构建函数创建的图像,以及任何<img>元素
SVGImageElement 使用<image>元素嵌入的图像
HTMLVideoElement 使用html<video>元素作为图像源会从视频中抓取当前帧并将其用作图像
HTMLCanvasElement 使用另一个<canvas>作为图像源
下面举两个例子,其他用法大家自行钻研:
// 第一种
var img = new Image(); // Create new img element
img.addEventListener('load', function() {
// execute drawImage statements here
}, false);
img.src = 'myImage.png'; // Set source path
// 第二种
var img = new Image(); // Create new img element
img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
2、绘制图像
drawImage(img, x, y) 在坐标x,y处绘制图像img
drawImage(img, x, y, width, height) width和height可以指定图像的宽和高
drawImage(img, imgx, imgy, imgWidth, imgHeight, canvasx, canvasy, canvasWidth, canvasHeight) imgx, imgy, imgWidth, imgHeight分别代表图片上的x, y,width和height;canvasx, canvasy, canvasWidth, canvasHeight分别代表画布上的x,y以及绘制的宽高
第三种示例:
transform
canvas封装了一些我们平常css会用到的transform属性,大家想体验的话推荐一个微软的插件OpenSeadragon,git地址是OpenSeadragon,示例可以看Viewport Zoom and Pan | OpenSeadragon
save() 保存画布的整体状态
restore() 恢复最近保存的画布状态
translate(x, y) 水平移动画布,x,y代表移动的距离
rotate(angle) 按照angle弧度围绕当前原点顺时针旋转画布,弧度于角度的转换公式为:弧度=(Math.PI/180)*角度
scale(x,y) 将画布水平缩放x,垂直缩放y;x,y为1代表保持原大小,为0.5缩小一倍,为2放大一倍以此类推
transform(a, b, c, d, e, f, g) 待学习
动画
我们可以通过setInterval,setTimeout或requestAnimationFrame(callback)进行图像更新
requestAnimationFrame告诉浏览器您希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。requestAnimationFrame方法通过在系统准备好绘制帧时调用动画帧,提供了一种更流畅、更有效的动画制作方式。回调的次数通常为每秒 60 次,在后台选项卡中运行时可能会降低到较低的频率。更多示例也可以看这个Basic animations - Web APIs | MDN