1.定义
Canvas API(画布)是在HTML5中新增的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap)。
Canvas 对象表示一个 HTML 画布元素 -<canvas>。它没有自己的行为,但是定义了一个 API 支持脚本化客户端绘图操作。
2.我们用来可以做什么
制作web网页游戏(但是如果代码写的不咋的游戏可能会非常卡)
数据可视化(这么说你可能不明白,但我告诉你echarts就是基于canvas)
广告banner的动态效果非常适合用canvas制作
canvas还可以用来内嵌一些网页
3.注意点
切记不要在css中定义canvas的宽高 在css中设置宽高属性和初始比例不一致 会出现扭曲
canvas在不添加宽高的情况下 默认为 300 * 150
当浏览器遇到canvas标签会进行解析 , 如果解析不了 就会显示canvas标签中的内容
4.画布中的方法
Var ctx = Canvas.getContext(‘2d’) 获取canvas上下文对象
Ctx.lineWidth = 5; 设置画笔宽度
Ctx.strokeStyle = red; 设置画笔颜色
Ctx.fillStyle = red; 设置填充颜色
Ctx.moveTo(x,y); 画笔的起始点
Ctx.lineTo(x,y); 画笔的连接点
Ctx.closePath() 闭合路径
Ctx.stroke(); 开始绘制
Ctx.rect(x,y,w,h); 绘制矩形
Ctx.fillRect(x,y,w,h) 绘制填充矩形
Ctx.fill() 开始填充
Ctx.beginPath() 绘制新路径的方法 绘制新路径的时候默认会使用上一个路径的样式 通过
beginPath方法使新路径的样式只能在当前路径中使用
Ctx.lineJoin = 'round'; 将每条路径的连接处变圆
Ctx.lineCap = "round"; 将开始点 和 结束点 变为圆角
Ctx.arc(x,y,r,startangle,endangle,true/false) 绘制圆形
ctx.font = "50px 宋体";
ctx.textAlign = "center"; 文字的x轴在起始点上的位置 center:文字的中间在起始点上right:文字右边在起始点 left:文字左边在起始点
ctx.textBaseline = 'middle'; top middle bottom 文字的y轴在起始点上的位置
Ctx.fillText(x,y,text); 绘制实心文字
Ctx.storkeText(x,y,text) 绘制空心文字
ctx.shadowColor = 'black'; 设置阴影的颜色
ctx.shadowBlur = 3; 设置阴影的模糊度
ctx.shadowOffsetX = 0; 设置 阴影在x轴上坐标
ctx.shadowOffsetY = 0; 设置 阴影在y轴上坐标
ctx.save(); 保存当前状态
ctx.restore(); 恢复上一次保存的状态
Ctx.clip() 裁剪
Ctx.rotate() 方法旋转当前的绘图
Ctx.translate(x,y) 重新映射画布上的 (x,y) 位置。
Ctx.scale() 缩放当前绘图至更大或更小。
requestAnimationFrame(move) 动画 和setInterval() 类似 自动调用函数
ctx.globalCompositeOperation = 'destination-out';
属性值:
source-over:默认值,表示新图覆盖在旧图之上
source-atop:只绘制旧图和重叠的部分,其他透明
source-in:只绘制新图的重叠部分,其他透明
source-out:只绘制新图没有重叠部分,重叠部分和旧图透明
destination-over:表示旧图覆盖在新图之上
destination-atop:只绘制旧图重叠的部分及新图未重叠部分,其他透明
destination-in:只绘制旧图的重叠部分,其他透明
destination-out:只绘制旧图,重叠部分和新图透明
lighter:旧图与新图都绘制,重叠部分混色处理
xor:旧图和新图重叠处做透明处理
copy:只绘制新图形,不绘制旧图形
ctx.drawImage(img,x,y,w,h,dx,dy,dw,dh); img:需要绘制的图片 x,y:图片的坐标 w,h:绘制图片的宽度、高度 dx,dy:裁剪完之后 图片的坐标 dw,dh:裁剪完之后 图片的 高度和宽度
5.贝塞尔曲线
ctx.quadraticCurveTo(sx,sy,x,y) 二次贝塞尔曲线(一个控制点) sx,sy:控制点坐标 x,y结束点坐标
ctx.bezierCurveTo(sx1,sy1,sx2,sy2,x,y) 三次贝塞尔曲线(两个控制点)
6.清除画布
ctx.clearRect(0,0,canvas.width,canvas.height) 清除画布的方法
canvas.width = canvas.width;
canvas.height = canvas.height;
7.使用画布绘制图形
1).饼状图
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
<script>
canvas.width = 500;
canvas.height = 500;
canvas.style.border = '1px solid #000';
var data = [
{
value:.3,
title:'30%',
color:'red',
text:'英雄联盟'
},
{
value:.26,
title:'26%',
color:'yellow',
text:'穿越火线'
},
{
value:.1,
title:'10%',
color:'blue',
text:'QQ飞车'
},
{
value:.15,
title:'15%',
color:'pink',
text:'地下城与勇士'
},
{
value:.19,
title:'19%',
color:'green',
text:'王者荣耀'
}
]
move(canvas,-90,data,{x:250,y:250},100)
function move(canvas,jd,data,obj,r){
var ctx = canvas.getContext('2d');
for(var i = 0; i < data.length; i++){
//开始绘制饼状图
//开辟新路径
ctx.beginPath();
//初始点坐标
ctx.moveTo(obj.x,obj.y);
//获取到一个数据的结束角度 (每个的占比乘以360)
var sa = data[i].value * 360;
//开始画圆 //开始角度 jd 结束角度 = (sa + jd)
ctx.arc(obj.x,obj.y,r,jd*Math.PI/180,(sa+jd)*Math.PI/180);
//设置填充颜色
ctx.fillStyle = data[i].color;
//开始填充
ctx.fill();
ctx.stroke();
//绘制文字
ctx.beginPath();
ctx.fillStyle = 'black';
//文字角度 = 开始角度 + 结束角度 / 2 因为我们想要文字在这个扇形的中 所以需要除以2
var txtjd = jd + sa / 2;
//有了角度 根据公式 进行 计算
// 角度 * 半径 + 圆心位置
var x = Math.cos(txtjd * Math.PI/180)* (r/2) + obj.x;
var y = Math.sin(txtjd * Math.PI/180)* (r/2) + obj.y;
ctx.fillText(data[i].title,x,y)
//每次绘制完成 让开始角度 等于 这次的结束角度 (为了开启下一次的绘制 因为下一次绘制的开始角度等于上一个的结束角度)
jd = jd + sa;
}
}
</script>
</html>
2).柱状图
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
<script>
canvas.width = 1000;
canvas.height = 1000;
var data = [
{
title:2011,
zg:50,
arr:[
.15,
.15,
.2,
.15,
.2,
.15
]
},
{
title:2012,
zg:75,
arr:[
.15,
.15,
.2,
.15,
.2,
.15
]
},
{
title:2013,
zg:125,
arr:[
.15,
.15,
.2,
.15,
.2,
.15
]
},
{
title:2014,
zg:200,
arr:[
.15,
.15,
.2,
.15,
.2,
.15
]
},
{
title:2015,
zg:320,
arr:[
.15,
.15,
.2,
.15,
.2,
.15
]
},
{
title:2016,
zg:475,
arr:[
.15,
.15,
.2,
.15,
.2,
.15
]
}
]
var ctx = canvas.getContext('2d');
var arr = [0,50,100,150,200,250,300,350,400,450,500];
for(var i = 0; i < arr.length; i++){
ctx.moveTo(50,500-arr[i]);
ctx.lineTo(canvas.width,500-arr[i])
ctx.textBaseline = 'middle';
ctx.fillText(arr[i],30,500-arr[i])
}
ctx.stroke();
var arrcolor = ['pink','red','blue','orange','gray','yellow']
//对数据进行循环
for(var i = 0; i < data.length ; i++){
//当前矩形距离顶部的值 = 500 - 当前矩形的高度
var topNum = 500 - data[i].zg;
//对数据中的 数组进行循环
for(var j = 0; j < data[i].arr.length; j++){
//开辟新路径
ctx.beginPath();
//定义颜色
ctx.fillStyle = arrcolor[j];
//绘制矩形
ctx.fillRect(i*100+100,topNum,50,data[i].zg*data[i].arr[j])
//绘制完成 让 距离顶部的距离为 topNum + 当前绘制矩形的高度 (因为 第二个矩形距离顶部的值 等于 第一个距离顶部的值 + 第一个高度)
topNum = topNum + data[i].zg*data[i].arr[j];
ctx.stroke();
}
ctx.beginPath();
ctx.font = '20px 宋体';
ctx.fillStyle = 'black'
ctx.fillText(data[i].title,i*100+105,520)
}
</script>
</html>