Canvas基础
canvas在HTML中的代码
<canvas id="myCanvas" width="300" height="300">
//writing some words here while broswer do not support canvas.
//or some <img src="" alt="" /> is cool too.
</canvas>
canvas核心API
- 渲染上下文
getContext()
let ctx = document.getElementById("mycanvas").getContext("2d");
- 画布栅格
- 矩形绘制
fillRect(x , y , width , height)
绘制一个填充的矩形strokeRect(x , y , width , height)
绘制一个矩形的边框clearRect(x , y , width , height)
清除指定矩形区域,让清除部分完全透明。- rect(x, y, width, height)
绘制一个左上角坐标为(x,y),宽高为width以及height的矩形。当该方法执行的时候,moveTo()方法自动设置坐标参数(0,0)。也就是说,当前笔触自动重置回默认坐标。
function draw() {
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);
}
}
输出如下:
- 圆弧绘制
arc(x, y, radius, startAngle, endAngle, anticlockwise)
画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle(弧度)开始到endAngle(弧度)结束,按照anticlockwise给定的方向(默认为顺时针)来生成。anticlockwise为bool值,true代表逆时针。arcTo(x1, y1, x2, y2, radius)
根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
for(var i=0;i<4;i++){
for(var j=0;j<3;j++){
ctx.beginPath();
var x = 25+j*50; // x 坐标值
var y = 25+i*50; // y 坐标值
var radius = 20; // 圆弧半径
var startAngle = 0; // 开始点
var endAngle = Math.PI+(Math.PI*j)/2; // 结束点
var anticlockwise = i%2==0 ? false : true; // 顺时针或逆时针
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
if (i>1){
ctx.fill();
} else {
ctx.stroke();
}
}
}
}
}
输出:
值得注意的是:
1. 无论顺逆时针弧度的走向都是顺时针为正;
2. 使用fill方法会自动闭合路径;
路径绘制
beginPath()
新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。closePath()
闭合路径之后图形绘制命令又重新指向到上下文中。这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。stroke()
通过线条来绘制图形轮廓。路径不会自动闭合。fill()
通过填充路径的内容区域生成实心的图形。当你调用fill方法时,所有没有闭合的形状都会自动闭合。
基本步骤应为:
- 首先,需要创建路径起始点。
- 然后使用画图命令去画出路径。
- 之后路径封闭。
- 一旦路径生成,就能通过描边或填充路径区域来渲染图形。
触笔相关函数
moveTo(x , y)
将笔触移动到指定的坐标x以及y上。lineTo(x , y)
绘制一条从当前位置到指定x以及y位置的直线。
贝塞尔曲线
quadraticCurveTo(cp1x, cp1y, x, y)
绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。
如图,蓝色为起始点与结束点,红色为控制点
- 添加色彩
// 这些 fillStyle 的值均为 '橙色'
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255,165,0)";
ctx.fillStyle = "rgba(255,165,0,1)";//rgba可指定透明度
同样的还有ctx.strokeStyle
,使用方法相同。值得注意的是fillStyle,只对fill类方法有用,strokeStyle只对stroke类方法有用;
- 添加线型
lineWidth = value
设置线条宽度。lineWidth存在精度问题
如果你想要绘制一条从 (3,1) 到 (3,5),宽度是 1.0 的线条,你会得到像第二幅图一样的结果。实际填充区域(深蓝色部分)仅仅延伸至路径两旁各一半像素。而这半个像素又会以近似的方式进行渲染,这意味着那些像素只是部分着色,结果就是以实际笔触颜色一半色调的颜色来填充整个区域(浅蓝和深蓝的部分)。这就是上例中为何宽度为 1.0 的线并不准确的原因。
要解决这个问题,你必须对路径施以更加精确的控制。已知粗 1.0 的线条会在路径两边各延伸半像素,那么像第三幅图那样绘制从 (3.5,1) 到 (3.5,5) 的线条,其边缘正好落在像素边界,填充出来就是准确的宽为 1.0 的线条。lineCap = type
设置线条末端样式。可取值为butt、round、square,默认为butt
lineJoin = type
设定线条与线条间接合处的样式。可取bevel、round和miter,默认为mitermiterLimit = value
限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。getLineDash()
返回一个包含当前虚线样式,长度为非负偶数的数组。setLineDash(segments)
设置当前虚线样式。lineDashOffset = value
设置虚线样式的起始偏移量。
- 添加渐变
createLinearGradient(x1, y1, x2, y2)
createLinearGradient 方法接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)。createRadialGradient(x1, y1, r1, x2, y2, r2)
createRadialGradient 方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。
var lineargradient = ctx.createLinearGradient(0,0,150,150);
var radialgradient = ctx.createRadialGradient(75,75,0,75,75,100);
gradient.addColorStop(position, color)
addColorStop 方法接受 2 个参数,position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。color 参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)。
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
// Create gradients
var lingrad = ctx.createLinearGradient(0,0,0,150);
lingrad.addColorStop(0, '#00ABEB');
lingrad.addColorStop(0.5, '#fff');
lingrad.addColorStop(0.5, '#26C000');
lingrad.addColorStop(1, '#fff');
var lingrad2 = ctx.createLinearGradient(0,50,0,95);
lingrad2.addColorStop(0.5, '#000');
lingrad2.addColorStop(1, 'rgba(0,0,0,0)');
// assign gradients to fill and stroke styles
ctx.fillStyle = lingrad;
ctx.strokeStyle = lingrad2;
// draw shapes
ctx.fillRect(10,10,130,130);
ctx.strokeRect(50,50,50,50);
}
可以看到最终渐变是属于颜色范畴,我们需要将它们赋予给fillStyle或者strokeStyle
- 图案样式
待补充:Path2D对象
参考:
1. MDN文档