1.什么是canvas
1-1 定义
canvas英文翻译为画布,作为一种html5的标签,canvas主要功能是绘画.也就是说使用canvas可以用javasccript在网页上绘制图像,可以精确控制每一个像素.
1-2 用途
(1) 动画,游戏开发 (2) 可视化数据,如echarts图表等 (3) banner广告
2.canvas基础
canvas是常规的html闭合标签,可以设置 width 和 height 属性,单位是 px ,不设置时默认为 300*150 . ie9 以上才支持 canvas, 其他 chrome、ff、苹果浏览器等都支持.
<canvas id="cavasEle">
你的浏览器不支持canvas,请升级浏览器.浏览器不支持,显示此行文本
</canvas>
canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。有以下关键概念:
(1) Context:
Canvas 的上下文、绘制环境。Context是javascript操作canvas的入口,使用canvas.getContext('2d')获取.
let canvas = document.getElementById('cavasEle');
canvas.width = 1200;
canvas.height = 900;
let ctx = canvas.getContext('2d');
(2) 坐标系:
canvas 坐标系,从最左上角 0,0 开始。x 向右增大, y 向下增大
(3) 绘制直线
像我们在一张纸上绘制一条直线一样,首先将笔触放在绘制起点,然后开始绘制,直至直线终点,代码表示如下:
// 简单线条
// 设置直线状态 起点 终点 宽度 颜色
ctx.moveTo(100, 100);
ctx.lineTo(100, 700);
ctx.lineWidth = 3;
// 开始绘制 stroke 笔画 绘制线条
ctx.strokeStyle = "red";
ctx.stroke();
// 线条相连成为形状
ctx.moveTo(200, 200);
ctx.lineTo(700, 700);
ctx.lineTo(200, 700);
ctx.lineTo(200, 200);
// 开始绘制 stroke 笔画 绘制线条
ctx.strokeStyle = "rgb(0,0,0)";
ctx.stroke(); // 描边
(4)路径开启与闭合
上面代码操作我们绘制了一条红色的直线和黑色的三角形,但是绘制结果却是两个黑色的,这是由于canvas是基于状态的绘制,在上一个绘制状态没有结束之前,下一次绘制将继承上一次的绘制状态.我们就需要路径开启和闭合工具来对两个不同操作进行隔离.
开始路径:ctx.beginPath(); 每次执行此方法,表示重新绘制一个路径,跟之前的绘制的墨迹可以进行分开样式设置和管理。
闭合路径:ctx.closePath();
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(100, 700);
ctx.closePath();
// 开始绘制 stroke 笔画 绘制线条
ctx.lineWidth = 3;
ctx.strokeStyle = "red";
ctx.stroke();
// 线条相连成为形状
ctx.beginPath();
ctx.moveTo(200, 200);
ctx.lineTo(700, 700);
ctx.lineTo(200, 700);
ctx.lineTo(200, 200);
ctx.closePath();
// 开始绘制 stroke 笔画 绘制线条
ctx.strokeStyle = "rgb(0,0,0)";
ctx.stroke();
ctx.fillStyle = "red";
ctx.fill()
要点代码总结:
// 划线
context.moveTo() // 移动画笔位置
context.lineTo()
context.beginPath()
context.closePath()
// 样式设置
context.lineWidth // 线宽
context.strokeStyle // 描边
context.fillStyle // 填充
// 绘制
context.stroke()
context.fill()
(5)七巧板的绘制实例
绘制之前首先要知道七巧板各个形状的坐标位置,整理如图所示:
代码如下:
let 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},{x:600,y: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"},
];
let canvas = document.getElementById('cavasEle');
canvas.width = 1200;
canvas.height = 900;
let ctx = canvas.getContext('2d');
function drawTangram () {
for(let i=0; i<tangram.length; i++){
let piece = tangram[i];
ctx.beginPath();
ctx.moveTo(piece.p[0].x, piece.p[0].y);
for(let j=1; j<piece.p.length; j++){
ctx.lineTo(piece.p[j].x, piece.p[j].y);
}
ctx.closePath();
ctx.fillStyle = piece.color;
ctx.stroke();
ctx.fill()
}
}
drawTangram();
效果如下图:
(6)绘制形状文字
6-1 绘制圆与弧
context.arc(centerx, // 圆心x坐标
centery, // 圆心y坐标
radius, // 圆半径
startingAngle, // 起始角度
endingAngle, // 结束角度
anticlockwise = false); // 顺时针:false 逆时针 true
// demo
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = "red";
ctx.arc(50, 50, 20, 0, 1.5*Math.PI);
ctx.stroke();
ctxCircle.beginPath();
ctxCircle.arc(90, 50, 20, 0, 1.5*Math.PI, true);
ctx.strokeStyle = "black";
ctxCircle.stroke();
6-2 绘制矩形
// (1) 两步绘制
context.rect(x, // 绘制起点x坐标
y, // 绘制起点y坐标
width, // 矩形宽
height); // 矩形高
// x, y是矩形左上角坐标
context.stroke();
// (2) 描边矩形
context.strokeRect(x, y, width, height)
// (3) 填充矩形
context.fillRect(x, y, width, height)
// 清除矩形 清除某个矩形内的绘制的内容,相当于橡皮擦
context.clearRect(x, y, width, hegiht);
6-3 绘制文字
文字样式设置与css相同
context.moveTo(300, 300);
context.fillStyle = 'purple'; //设置填充颜色为紫色
context.font = '20px "微软雅黑"'; //设置字体
context.textBaseline = 'bottom'; //设置字体底线对齐绘制基线
context.textAlign = 'left'; //设置字体对齐的方式
context.strokeText( "hello", 360, 250 ); // 在画布上绘制文本(无填充)
context.fillText('hello world', 660, 250); // 填充文字
let text1 = context.measureText('hello') // 返回包含指定文本宽度的对象
console.log(text1)
let text2 = context.measureText('hello world')
console.log(text2)
(7)小球运动动画绘制
要用canvas做一个小球运动的动画效果,首选需要知道小球的运动轨迹,这就需要用到我们以前学到的物理学知识,简略的小球运动示意图如下:
代码如下:
// data:
let runBallConfig = {
ballRadius: 20,
startX: 30,
startY: 30,
vx: 5,
vy: 0,
g: 2,
}
// js:
let canvasBall = this.$refs.canvasBall;
canvasBall.width = 1200;
canvasBall.height = 400;
ctxBall = canvasBall.getContext("2d");
drawRunBall(runBallConfig.startX, runBallConfig.startY);
setInterval(()=>{
updateBall();
},50)
updateBall(){
runBallConfig.startX += runBallConfig.vx
runBallConfig.startY += runBallConfig.vy
runBallConfig.vy += runBallConfig.g
drawRunBall(runBallConfig.startX, runBallConfig.startY);
// 临界判断
if(runBallConfig.startY >= 400 - runBallConfig.ballRadius){
runBallConfig.startY = 400 - runBallConfig.ballRadius; // 落地
runBallConfig.vy = - (runBallConfig.vy) * 0.5; // 摩擦阻力系数0.5
}
},
drawRunBall(x, y){
ctxBall.clearRect(0, 0, 1200, 400);
ctxBall.beginPath();
ctxBall.lineWidth = 3;
ctxBall.strokeStyle = "red";
ctxBall.arc(x, y, runBallConfig.ballRadius, 0, 2*Math.PI);
ctxBall.stroke();
ctxBall.fillStyle = "red";
ctxBall.fill()
},
(8)绘制图片
// 图片绘制
context.drawImage(img, x, y, width, height);
//img为绘制图片的dom对象,x、y为绘制的左上角坐标.
//width, height 绘制图片的宽高
// 图片裁剪
context.drawImage(img, sx, sy, swidth, sheight, x, y, width, height);
// sx, sy 裁剪的xy坐标
// swidth, sheight 裁剪图片的xy
(9) 折线图demo 与 饼状图demo
git地址:github.com/aicai0/test…
如有问题,欢迎探讨,如果满意,请手动点赞,谢谢!🙏
及时获取更多姿势,请您关注!!