JS——canvas及其应用
一、canvas基础
1、canvas——画布:
-
canvas本身没有外观,只是一个画板
-
IE9以前不支持
-
canvas不要使用css来定义大小,要直接使用自身的属性width、height来设置并且不带单位
-
可用getContext()方法来返回一个画笔
-
可用于可视化数据、游戏等的制作
2、let pen = canvas.getContext()——画笔:
-
pen.moveTo(x,y):设置一个新的起点,用于画一些不连续的线条
-
pen.lineTo(x,y):轨迹,上一次的终点是下一次轨迹的起点,通常与moveTo方法配合使用
-
pen.closePath():闭合轨迹,将终点和起点连接起来,灵活使用可以在画闭合图形时不必画最后一条线
-
pen.strokStyle:轨迹颜色,默认是黑色,可以识别多种颜色表示方法
-
pen.lineWidth:轨迹宽度,设置后在该位置上内外各一半
-
pen.fillStyle:填充颜色,可以识别多种颜色表示方法
-
pen.fill():填充,不写默认不填充,写了默认黑色,仅封闭图形才可以使用填充方法
-
pen.strok():沿轨迹绘制,不写无法显示,写了默认关闭路径,下一次使用要重新打开路径
-
pen.beginPath():打开新的路径
-
pen.arc(x,y,r,start,end,bool):画圆弧,x,y为圆心坐标,r是圆半径,start是起始弧度,end是结束弧度,bool指是否逆时针;设置起始弧度为0,结束弧度为2PI,可以画圆,再设置lineWidth可以画出小圆点
-
pen.font:设置字体样式的符合属性,可以像css那样用
-
pen.fillText(text,x,y):填充文字,text指要填充的文字,x,y指填充开始位置
-
pen.textAlign:设置文字垂直和水平位置
-
pen.textBaseline:设置基线,即文字中间位置线
使用画笔画出一个矩形的四种方法:
方法 | 描述 |
---|---|
pen.rect(x,y,width,height) | x,y为矩形左上角坐标,可以用fill填充颜色并且有边框不透明 |
pen.fillRect(x,y,width,height) | x,y为矩形左上角坐标,无边框只有填充不透明 |
pen.fillRect(x,y,width,height) | x,y为矩形左上角坐标,只有边框没有填充色,无法使用fill填充颜色,并且透明重合在其他颜色上面时可以看到下面的颜色 |
lineTo(x,y) | 通过计算坐标值画出矩形 |
二、canvas应用实例
1、使用LineTo()或moveTo()画个小红旗:
<canvas width="500" height="500"></canvas>
<script type="text/javascript">
let canvas = document.querySelector('canvas');
let pen = canvas.getContext('2d');
pen.lineTo(100,50);
//绘制时会将上一个点当做起点
pen.lineTo(150,100);
pen.lineTo(100,100);
pen.lineTo(100,50);
pen.lineTo(100,300);
pen.lineTo(80,300);
pen.lineTo(50,330);
pen.lineTo(150,330);
pen.lineTo(120,300);
pen.lineTo(100,300);
pen.strokeStyle = 'red';
pen.stroke();
</script>
2、使用canvas画个简单的折线图:
<canvas width="500" height="500" style="border: 1px solid black;"></canvas>
<script type="text/javascript">
let canvas = document.querySelector('canvas');
let pen = canvas.getContext('2d');
let data = [
{x: 20, y: 80},
{x: 60, y: 20},
{x: 100, y: 40},
{x: 140, y: 200},
{x: 180, y: 90},
{x: 220, y: 130},
{x: 260, y: 50},
{x: 300, y: 70}
]
let step1 = 10;
//画出表格,每个小格子宽度10
for(let i = 0; i <= canvas.width/step1; i++){
pen.moveTo(0,i*step1);
pen.lineTo(canvas.width,i*step1);
pen.moveTo(i*step1,0);
pen.lineTo(i*step1,canvas.width);
}
pen.strokeStyle = 'lightgray';
pen.stroke();
pen.beginPath();
let step2 = 50;
//隔50画出表格标重线
for(let i = 0; i <= canvas.width/step2; i++){
pen.moveTo(0,i*step2);
pen.lineTo(canvas.width,i*step2);
pen.moveTo(i*step2,0);
pen.lineTo(i*step2,canvas.width);
}
pen.strokeStyle = 'grey';
pen.stroke();
pen.beginPath();
//画出折线
for(let i = 0; i < data.length; i++){
pen.lineTo(data[i].x,data[i].y);
}
pen.strokeStyle = 'burlywood';
pen.lineWidth = 5;
pen.stroke();
let deg = Math.PI/180;
//画出每个转折点圆圈
for(let i = 0; i < data.length; i++){
pen.beginPath();
pen.arc(data[i].x,data[i].y,5,0,360*deg);
pen.closePath();
pen.fillStyle = 'burlywood';
pen.fill();
pen.stroke();
}
</script>
3、使用canvas画出扇形图:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<canvas width="500" height="500" style="border: 1px solid black;"></canvas>
<script>
let consume = [
{
name: "电子产品",
money: 5003
},
{
name: "美妆",
money: 1500
},
{
name: "日用品",
money: 2050
},
{
name: "蔬菜水果",
money: 4300
},
{
name: "服装",
money: 6700
}
]
let canvas = document.querySelector('canvas');
let pen = canvas.getContext('2d');
let deg = Math.PI/180;
consume.sort(function(a, b){return b.money - a.money});
let sumMoney = consume.reduce((pre,next) => {
return {
money: pre.money + next.money
};
})
function showRotate(pointX, pointY, r){
let start = 30*deg;
for(let i = 0; i < consume.length; i++){
let end = consume[i].money/sumMoney.money*360*deg + start;
console.log(end)
let x = Math.cos(start)*r + pointX;
let y = Math.sin(start)*r + pointY;
pen.beginPath();
pen.moveTo(pointX,pointY);
pen.lineTo(x,y);
pen.arc(pointX,pointY,r,start,end);
let random = Math.random().toString(16).substr(-6);
pen.fillStyle = '#' + random;
pen.fill();
pen.stroke();
// 画矩形框表示每一个扇形所代表的含义
pen.fillRect(400, 100+i*30, 20, 20);
// 绘制文本表示含义
pen.beginPath();
pen.font = "14px 楷体";
pen.textAlign = "left";
pen.textBaseline = "middle";
pen.fillStyle = "#333";
pen.fillText(consume[i].name, 430, 110+i*30)
// 在扇形内部绘制文本表示百分比
let mid = (end - start)/2 + start; //获取扇形中间那个弧度
let midX = Math.cos(mid)*r/2 + pointX;
let midY = Math.sin(mid)*r/2 + pointY;
pen.beginPath();
let text = (consume[i].money/sumMoney.money * 100).toFixed(2) + "%";
pen.fillStyle = "red";
pen.font = "16px 楷体";
pen.textAlign = "center";
pen.textBaseline = "middle";
pen.fillText(text, midX, midY);
start = end;
}
}
showRotate(200,200,100);
// showRotate(100,400,100);
</script>
</body>
</html>
4、画一个评分五角星:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
canvas {
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="canvas" width="200" height="40"></canvas>
<script type="text/javascript">
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let deg = Math.PI/180;
let r = 20;
paintstar(r, 0);
canvas.onclick = function(e) {
paintstar(r, Math.ceil(e.pageX/(2*r)));
}
function paintstar(r, rank) {
for(let i =0; i < canvas.width/(2*r); i++) {
if(i < rank) {
strokestar(i*2*r+r, r, "yellow");
} else {
strokestar(i*2*r+r, r, "grey");
}
}
}
function strokestar(x, r, color="grey") {
let angle = 72*deg; //以五角星上面的点为起点,每个角之间的角度是72°
let orgin = {x, y: canvas.height/2}; //表示五角星所在圆心点的坐标,y轴位置不变
let absx = (num) => orgin.x + Math.cos(-90*deg + angle*num)*r;
let absy = (num) => orgin.y + Math.sin(-90*deg + angle*num)*r
let p1 = {x: absx(0), y: absy(0)};
let p2 = {x: absx(1), y: absy(1)};
let p3 = {x: absx(2), y: absy(2)};
let p4 = {x: absx(3), y: absy(3)};
let p5 = {x: absx(4), y: absy(4)};
// 绘制五角星
ctx.beginPath();
ctx.lineTo(p1.x, p1.y);
ctx.lineTo(p3.x, p3.y);
ctx.lineTo(p5.x, p5.y);
ctx.lineTo(p2.x, p2.y);
ctx.lineTo(p4.x, p4.y);
ctx.closePath();
ctx.fillStyle = color; //设置填充颜色
ctx.fill();
ctx.strokeStyle = color; //设置线条颜色
ctx.stroke()
}
</script>
</body>
</html>