Canvas学习

控制画布大小

控制画布大小

1
2
3
<body>
<canvas id="canvas" width="500" height="500"> </canvas>
</body>

或者通过 css控制大小

1
2
3
4
5
#canvas {
background: #f00;
width: 500px;
height: 5400px;
}

请不要同时使用,内容会被压缩,或者拉长

如果不支持可以在 canvas 中添加标签,标签会代替 canvas 进行展示

1
<canvas><div>换个浏览器吧!求求了</div></canvas>

开始画

通过以下代码拿去上下文

1
2
3
4
5
6
7
8
var canvas = document.getElementById("canvas")
var ctx = canvas.getContext("2d")
//也有可能拿不到
if(canvas.GetContext{
//正常逻辑
}else{
//不支持的兼容处理
}

如何下笔

坐标系

绘制直线

通过上下文的 beginPath()方法新建笔画

1
2
3
4
5
6
7
8
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath(); //新建画笔
ctx.moveTo(100, 100); //将画笔抵在画布上
ctx.lineTo(); //将画笔移动到相应位置,但是这个时候你会发现没有(他奶奶个腿儿!),因为画笔没有颜色,只是相当于划过,但是没有痕迹
ctx.stroke(); //显示痕迹轮廓
ctx.fill(); //填充绘制的路径,如果绘制的线没有闭合,会自动连接起点与终点,闭合
ctx.closePath(); //手动起点->终点闭合

绘制矩形

1
2
3
4
5
6
7
8
9
10
//矩形绘制
ctx.rect(x, y, width, height);
//如果要实心的 ctx.fill()
ctx.stroke(); //描边矩形
//代替方案
ctx.strokeRect(x, y, width, height);
//实心的代替方案 ctx.fillRect(x,y,width,height)

//橡皮擦
ctx.clearRect(20, 20, 10, 100);

绘制圆形

1
2
3
4
5
6
7
8
9
//x,y圆心,r半径,开始,终止角度(从x正半轴开始计算),顺逆时针,默认为false,如果要调整成逆时针调整成true即可
ctx.arc(x,y,r,startAngle,endAngle,anticlockwise);
//画一个半径为50px的半圆
//角度是弧度制
//弧度制转成角度制是Pi
//π÷180x角度
ctx.(100,100,50,0,Mat.PI);
ctx.stroke();
//加入想要实心的,ctx.fill()

贝塞尔曲线

一次贝塞尔曲线

1
2
3
//cp1x,cp1y控制点坐标
//x,y曲线结束点坐标
ctx.quadraticCurveTo(cp1x, cp1y, x, y);

二次贝塞尔曲线

1
2
3
//cp1x,cp1y,cp2x,cp2y控制点坐标
//x,y曲线结束点坐标
ctx.quadraticCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);

文本

1
2
3
4
5
6
7
8
//text文本内容,x,y坐标,可选项,最大宽度(超过了这个宽度,文字被压缩)
ctx.fillText(text,x,y,[,maxWidth]);
ctx.strokeText(text,y,x[,maxWidth]);
//文字样式
ctx.font//与css的font属性一致
ctx.textAlign="left|right|center|start|end"//设置文本对其
ctx.textBaseLine="top|hanging|middle|alphabetic|ideographic|bottom"//设置基线对其
ctx.direction="ltr|rtl|inherit"//文字方向

图片

1
2
3
4
5
6
7
8
9
10
var img = new Image();
img.src = "myInamge.png";
ctx.drawImage(img, x, y, width, height);
//如果图片过大
img.onload = function () {
ctx.drawImage(img, 0, 0);
};
img.src = "xxx.png";
//截取图片部分
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

前四个参数

后四个参数

样式

requestAnimationFrame()让浏览器执行动画的方法,要求在浏览器的下一次重绘之前调用一个指定函数来更新这次动画

1
2
3
4
5
6
7
8
9
10
11
//定义一个回调函数
function animate(time) {
//更新动画状态
update(time);
//绘制动画帧
draw();
//请求下一次动画帧
window.requestAnimationFrame(animate);
}
//开始动画循环
window.requestAnimationFrame(animate);

让我们尝试绘制一个时钟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//定义一个回调函数
function animate(time){
const now = new Date();
const sec = now.getSeconds();
const min now.getMinutes();
const hr = now.getHours();
const ctx = document.getElementById("canvas").getContex;
ctx.save()//由于每一次绘制需要获取大量上下文,所以这里先save一下
ctx.clearRect(0,0,600,600);//每一帧不需要保留保证不影响下一次绘制
ctx.translate(300,300);//坐标轴中心移动到300,300
//由于画的是表,x是横着的,不方便,给他逆时针90
ctx.rotate(-Math.PI/2);
//设置一些样式
ctx.strokeStyle = 'black'; //轮廓黑色
ctx.lineWidth = 5;//线宽是5
ctx.lineCap = 'round'//线的末端是个小圆
//绘制之前save一下
ctx.save()
for(let i=0;i<12;i++){
ctx.beginPath();
ctx.rotate(Math.PI/6);
ctx.moveTo(100,0);
ctx.lineTo(120,0)
}
ctx.
ctx.restore()
ctx.restore()//再读取,这样可以保证下一帧的时候状态是默认的,不会被上一帧所影响
//请求下一次动画帧
window.requestAnimationFrame(animate);
}
//开始动画循环
window.requestAnimationFrame(animate);