Canvas
标签
- 通过 HTML 创建 canvas 元素,其 width、height 属性指定其宽、高。
<canvas id="canvas" width="800" height="800"></canvas>
- 通过 JS 获取 canvas 元素,可以通过获取后元素的 width、height 属性拿到其宽高。
var canvas = document.getElementById('canvas'); // 获取 canvas 元素
var context = canvas.getContext('2d'); // 获取 canvas 元素中上下文
// 获取 canvas 元素的宽高
var canvas_width = canvas.width;
var canvas_height = canvas.height;
console.log(canvas_width,canvas_height); // 800 800
canvas 元素的实际方法并不多,绘制使用的是其 getContext('2d') 返回的上下文中的方法,以下我们用 context 代表 canvas 所在的上下文。
直线
绘制方法
- context.moveTo
- context.lineTo
- context.lineWidth
- context.strokeStyle
- context.fillStyle
- context.stroke
- context.beginPath
- context.closePath
线条属性
- lineWidth
- lineCap 用于设置一个线条两端的形状
- butt(default)
- round
- square
- lineJoin 线条和线条香蕉皮的时候所展现的形态
- miter(default)
- bevel
- round
- miterLimit 描述lineJoin为miter的时候内角和外角之间距离的最大值,当超过miterLimit将自动转换成bevel属性
线条
把笔尖放在坐标轴(100,100)的位置上,笔从(100,100)走到了(200,200)。以上只是绘制意图,具体的绘制需要调用 stroke 方法。
context.moveTo(100,100); // 把笔尖放在坐标轴(100,100)的位置上
context.lineTo(200,200); // 把笔从(100,100)走到了(200,200)
context.lineWidth = 2; // 设置笔的宽度
context.strokeStyle = '#35b558'; //给绘制设置样式
context.stroke(); // 具体的绘制需要调用 stroke 方法
多边形
通过不断的 lineTo 方法可以绘制出一个多边形。
context.moveTo(100,100);
context.lineTo(200,200);
context.lineTo(100,200);
context.lineTo(100,100);
context.stroke();
不同路径
对于,多个路径,我们需要分开处理其样式的话,需要在路径定义的首尾通过 beginPath 和 closePath 方法。
// 绘制一个红色的三角形
context.beginPath();
context.moveTo(100,100);
context.lineTo(200,200);
context.lineTo(100,200);
context.lineTo(100,100);
context.closePath();
context.lineWidth = 5;
context.strokeStyle = 'red';
context.stroke();
// 再绘制另一条绿色的线段
context.beginPath();
context.moveTo(150,100);
context.lineTo(250,200);
context.closePath();
context.strokeStyle = '#35b558';
context.stroke();
七巧板版示例
<canvas id="canvas" width="800" height="800"></canvas>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var tangram = [
{p:[{x:0,y:0},{x:800,y:0},{x:400,y:400}],color:'#caff67'},
{p:[{x:0,y:0},{x:400,y:400},{x:0,y:800}],color:'#67becf'},
{p:[{x:800,y:0},{x:800,y:400},{x:600,y:600},{600:200}],color:'#ef3d61'},
{p:[{x:600,y:200},{x:600,y:600},{x:400,y:400}],color:'#f9f51a'},
{p:[{x:400,y:400},{x:600,y:600},{x:400,y:800},{x:200,y:600}],color:'#a594c0'},
{p:[{x:200,y:600},{x:400,y:800},{x:0,y:800}],color:'#fa8ecc'},
{p:[{x:800,y:400},{x:800,y:800},{x:400,y:800}],color:'#f6ca29'},
]
tangram.forEach(function(data,index){
context.beginPath();
context.moveTo(data.p[0].x,data.p[0].y);
data.p.forEach(function(pos,p_index){
context.lineTo(pos.x,pos.y)
})
context.closePath();
// 填充颜色
context.fillStyle = data.color;
context.fill();
// 描边
context.strokeStyle = "black";
context.lineWidth = 2;
context.stroke();
})
弧线
context.arc(cx,cy,radius,startingAngle,endingAngle,anticlockwise = false) 无论是逆时针或者顺时针的方向绘制,坐标轴中的弧度坐标是不会变发送变化的。
- cx、cy 圆心坐标
- radius 半径
- startingAngle,endingAngle 开始的弧度到终止的弧度
- 是否逆时针的方向来绘制
其他曲线绘制方法
- context.arcTo(x1,y1,x2,y2,radius)
- context.quadraticCurveTo(x1,y1,x2,y2)
- context.bezeirCurveTo(x1,y1,x2,y2,x3,y3)
context.lineWidth = 2;
context.strokeStyle = "#35b558";
context.arc(300,300,200,0,1.5 * Math.PI);
context.stroke();
在我们绘制的路径不是封闭的情况下,使用 closePath 之后会自动把首位两端连接起来形成一个封闭的路径。
context.lineWidth = 2;
context.strokeStyle = "red";
for (var i = 0; i < 10 ; i++) {
context.beginPath()
context.arc(10 + i * 50, 90,20,0,2 * Math.PI * (i+1)/10 )
// 添加closePath
context.closePath();
context.stroke();
}
context.strokeStyle = "#35b558";
for (var i = 0; i < 10 ; i++) {
context.beginPath()
context.arc(10 + i * 50, 180,20,0,2 * Math.PI * (i+1)/10 )
// 没有添加closePath
context.stroke();
}
context.fillStyle = "blue";
for (var i = 0; i < 10 ; i++) {
context.beginPath()
context.arc(10 + i * 50, 270,20,0,2 * Math.PI * (i+1)/10 )
context.fill();
}
矩形
- context.rect(x,y,width,height);
- context.fillRect(x,y,width,height);
- context.strockRect(x,y,width,height);
context.rect(100,100,100,100);
context.fillStyle = "blue";
context.fill();
context.fillRect(200,200,100,100);
context.strokeRect(300,100,100,100);
填充
fillStyle = color 、gradient、image、canvas、video
线性渐变
通过(x1,y1,x2,y2)参数可以控制渐变背景的大小和方向
var grd = context.createLinearGradient(0,0,200,200);
grd.addColorStop(0,'white');
grd.addColorStop(1,'black');
context.fillStyle = grd;
context.fillRect(0,0,200,200);
径向渐变
通过(x0,y0,r0,x1,y1,r1)定义两个圆的原点坐标和半径
var grd = context.createRadialGradient(100,100,0,100,100,100);
grd.addColorStop(0,'white');
grd.addColorStop(1,'black');035
context.fillStyle = grd;
context.fillRect(0,0,200,200);
其他填充
- createPattern(img, repeat-style)
- createPattern(canvas, repeat-style)
- createPattern(video, repeat-style)
- repeat-style
- no-repeat
- repeat-x
- repeat-y
- repeat
- repeat-style
文字
基础方法
- context.font = "bold 40px Arial";
- context.fillText(string ,x ,y, [maxLen]);
- context.strokeText(string, x, y, [maxLen]);
context.font = "bold 40px Arial";
context.fillStyle = "#058";
context.fillText('Hello, world!',40,100);
context.lineWidth = 1;
context.strokeStyle = "#058";
context.strokeText('Hello, world!',40,200);
context.fillText('Hello, world!',40,300,100);
context.strokeText('Hello, world!',40,400,100);
字体
context.font = font-style font-variant font-weight font-size font-family
- font-style
- normal
- italic
- oblique
- font-variant
- nromal
- smal-caps
- font-weight
- lighter
- normal
- bold
- bolder
- 100,200,300,400(normal)
- 500,600,700(bold)
- 800,900
- font-size
- px
- em
- %
- xx-small、x-small
- medium
- large、x-large、xx-large
- font-family
文本对齐
水平对齐 context.textAlign
- left
- center
- right
context.font = "bold 40px Arial";
context.fillStyle = "#058";
// 400 的位置左对齐
context.textAlign = "left";
context.fillText('Hello, world!',400,100);
// 400 的位置居中
context.textAlign = "center";
context.fillText('Hello, world!',400,200);
// 400 的位置有对齐
context.textAlign = "right";
context.fillText('Hello, world!',400,300);
垂直对齐 context.textBase
- top
- middle
- bottom
- alphabetic(default)
- ideographic
- hanging
function drawBaseline(h){
var width = context.canvas.width;
context.save();
context.strokeStyle = '#e4e4e4';
context.lineWidth = 2;
context.moveTo(0,h);
context.lineTo(width,h);
context.stroke();
context.restore();
}
context.font = "bold 40px Arial";
context.fillText('Hello, world!',100,100);
drawBaseline(100)
context.textBaseline = "bottom";
context.fillText('Hello, world!',100,200);
drawBaseline(200)
context.textBaseline = "middle";
context.fillText('Hello, world!',100,300);
drawBaseline(300)
context.textBaseline = "top";
context.fillText('Hello, world!',100,400);
drawBaseline(400)
上下剧中对齐示例
// 绘制画布剧中文字
context.font = "bold 40px Arial";
context.fillStyle = "#058";
context.textAlign = 'center';
context.textBaseline = 'middle';
context.fillText('CANVAS',canvas.width/2,canvas.height/2);
// 辅助线
context.strokeStyle = '#e4e4e4';
context.moveTo(0,canvas.height/2);
context.lineTo(canvas.width,canvas.height/2);
context.moveTo(canvas.width/2,0);
context.lineTo(canvas.width/2,canvas.height);
context.stroke();
文本度量,返回该文本在 canvas 上绘制所占用的宽高, context.measureText(String).width;
var str_width = context.measureText("HELLO,WORD!").width;
console.log(str_width)
变换
- translate(x,y) 位移
- rotate(deg) 旋转
- scale(sx,sy) 缩放