canvas是什么就不介绍了,我是怎么了解到canvas的我自己都不记得了,我只知道开始学习了解之后感觉就是欲罢不能啊,这东西很酷也很强大,而我喜欢的原因就是它能够进行画画!当然它主要的用途是进行数据可视化,echarts就是canvas写的。不多说了,这里分两部分,第一部分是简单的入门,第二部分是绘制一个动态饼图。
入门
使用canvas你就理解为画画就好了,画画需要画布、画笔(或者说是工具箱,工具箱中有画笔这些),有了这两样东西就可以画画了,画画需要确定开始位置、结束位置,开始位置和结束位置之间如何连线的问题,然后是关注画笔的笔头形状,画笔颜色,填充颜色。基本上使用canvas就是这样一个思路了
<style>
canvas{
border:1px solid #ccc;
}
</style>
<!--
不要通过css进行画布大小的设置,canvas默认大小是300*150,如果通过css
设置大小,其实是设置画布内容区域的大小,这会导致内容被拉大或缩小
-->
<canvas width="600" height="400"></canvas>
//获取画板
var myCanvas=document.querySelector('canvas');
//获取上下文,(工具箱)
var ctx=myCanvas.getContext('2d');
//开启新路径,这样防止被其他未关闭的路径的影响
ctx.beginPath();
//移动到点(100,100)开始位置
ctx.moveTo(100,100);
//画到点(100,200)结束位置
ctx.lineTo(100,200);
//线条颜色
ctx.strokeStyle="red";
//线条宽度
ctx.lineWidth=10;
//描边,上面是进行画画的初始定义,stroke方法才是真正将线条画在画布上
ctx.stroke();
上面就是一个最基本的东西,了解一个最简单的线段应该如何画,剩下的画圆、矩形、曲线等,都可以通过工具箱ctx
找得到对应的工具进行绘制,查看canvas文档就可以。
注意:这里有线模糊的问题,原因是在进行绘制的时候是从线的中间画的,而显示器处理不了0.5这种问题,导致线变大变模糊,详细的东西自己去查查就知道了
路径闭合的问题
起始点moveTo和移动点lineTo的结束点无法完全闭合,会产生缺角的问题
如果确定要闭合路径,可以使用canvas的自动闭合办法,在描边之前闭合
ctx.closePath();
填充区域和非零环绕
对于闭合路径之间区域的填充问题,主要与路径轨迹的方向相关,这里会用到非零环绕原则,我个人的简记是顺加逆减
通过一张图来进行非零环绕原则的理解,图是来自简书上的,地址
对于S1区域,从该区域内部向外拉一条线L1,方向随意,可以看到与L1相交的路径轨迹只有一条,方向是逆时针,减1,则相交轨迹总和为-1,不等于0,所以S1区域被填充。
对于S2区域,与L2相交的轨迹为两条,方向都为逆时针,相交轨迹总和为-2,不等于0,所以S2被填充
对于S3区域,与L3相加的轨迹为两条,一条为逆时针,减1,一条为顺时针,加1,则相交轨迹总和为0,所以S3区域不填充
绘制动态饼图
一般来说工作上使用canvas很多是用来做数据可视化(当然一般使用已有的库),也有用来做一些简单动画的,这里写的demo是参考了别人的写法进行的,原文见这里,我这里只写了如何进行动态效果的实现。节流没做到,有一个已知bug。效果图如下:
源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>动态饼图</title>
<style>
canvas {
border: 1px solid #000;
/* background-color: rgb(54, 252, 120); */
}
.draw {
display: inline-block;
left: 50%;