【Canvas学习笔记】基础篇(一)

一、写在前面

  最近在项目中遇到一个绘制雷达图的需求,以前我都是直接使用echarts来进行一些图表的绘制,但是这个项目中的雷达图非常的简单,而且整个项目中只有这一处需要进行类似的图形绘制,为了这个小小的雷达图而引入 echarts感觉有点不划算,哈哈。所以我决定直接使用canvas元素进行绘制,以前也看过canvas的一些使用方法,但是一直没有用过,因此有些遗忘,所以趁着这次雷达图的开发,把canvas的基础使用进行一个记录。

二、<canvas>元素简介

  HTML5添加了一些新的元素,其中就有<canvas>。使用<canvas>元素,我们可以在页面中设定一个指定大小的区域,然后在这个区域中通过JavaScript动态绘制图形。与<canvas>相关的有一组API,我们就是通过各种花式操作这些API来完成我们各种图形的绘制,比如最基本的:路径、盒、弧、字符以及添加图像。

  当然啦,不是所有的浏览器都支持canvas元素,下面表格中列出了各浏览器支持<canvas>元素的第一个版本号。

  

  支持<canvas>元素的浏览器会只渲染<canvas>标签,而忽略出现<canvas>开始和结束标签中的内容,不支持的浏览器则会直接渲染<canvas>开始和结束标签中的内容,因此对于那些不支持<canvas>元素的浏览器,我们可以使用在<canvas>标签中添加内容的方式,在相应的区域展示替代内容(优雅降级)。

  比如使用文本替代:

<canvas id="my-canvas" width="300" height="300">your browser can not support 'canvas' element</canvas>

   注意:<canvas>标签的结束标签</canvas>不可以省略,如果省略了,那么文档中的其余部分都会被认为是替代内容,在支持<canvas>元素的浏览器中将不会展示。

  从上面的代码中我们可以看到,<canvas>元素有两个特殊属性:width、height,这两个属性都是可选的,如果没有设置width和height属性。则默认width为300,height为150,单位都是px。当然,也可以通过css属性来设置宽高,但是如果宽高属性和初始比例(2:1)不一致,会出现扭曲。所以,建议不要使用css属性来设置<canvas>元素的宽高。

  除了具备特殊的width和height属性之外,<canvas>标签也支持HTML中的全局属性和事件属性。

三、2D上下文

1、获取2D上下文对象

  canvas就像一块画布,要想在画布上绘图,除了需要画布,我们还需要画笔,即绘图上下文,通过绘图上下文来绘制和处理要展示在画布中的内容。

  通过调用getContext()方法并传入上下文类型,就可以取得绘图上下文对象的引用,比如传入“2d”,就可以取得2D上下文对象(本笔记只讲述2D上下文)。

1     <script>
2         // 获取画布
3         var canvas = document.getElementById('my-canvas');
4         // 判断浏览器是否支持<canvas>元素
5         if (canvas.getContext) {
6             // 获取绘图上下文(画笔)
7             var ctx = canvas.getContext('2d');
8         }
9     </script>

 2、Canvas坐标

  我们可以把Canvas画布看成一个二维坐标系,坐标系原点位于画布左上角的顶点,表示为(0, 0),如下图,所有坐标值都是基于原点进行计算,x值越大表示越靠右,y值越大表示越靠左。2D上下文的初始位置位于坐标系的原点。

  

3、填充和描边

  2D上下文的两种基本绘图操作是填充fill()和描边stroke()。

  填充,就是指使用指定的样式(颜色、渐变或者图像)来填充某个图形,就像绘画中的上色;描边,就是指沿着图形的边缘画线,就像绘画中的勾勒。大部分2D上下文操作都需要使用填充或者描边来完成路径的渲染,从而将图形展示到页面上。填充和描边操作的结果依赖fillStyle和strokeStyle这两个属性。这两个属性的值可以是字符串、渐变对象或模式对象,默认值为'#000000',如果需要将这两个属性的值表示为颜色,可以使用css中指定颜色值的任何格式,比如颜色名、十六进制码、rgb.......

 1     <script>
 2         // 获取画布
 3         var canvas = document.getElementById('my-canvas');
 4         // 判断浏览器是否支持<canvas>元素
 5         if (canvas.getContext) {
 6             // 获取绘图上下文(画笔)
 7             var ctx = canvas.getContext('2d');
 8             // 设置填充色
 9             ctx.fillStyle = "red";
10             // 设置描边色
11             ctx.strokeStyle = "#999";
12         }
13     </script>

  上面的代码中,设置了fillStyle为'red',设置了strokeStyle为'#999',后面所有涉及到fill()和stroke()的操作都将使用这两个样式,直到重新设置了这两个值。

4、绘制矩形

  矩形是唯一一个可以直接绘制的形状。与绘制矩形相关的有三个方法:

  • fillRect(x, y, width, height):绘制实心矩形(自带填充操作),矩形颜色由fillStyle指定
  • strokeRect(x, y, width, height):绘制空心矩形(自带描边操作),矩形边框颜色由strokeStyle指定
  • clearRect(x, y, width, height):清除指定位置、指定大小的矩形区域

  以上三个方法都有四个参数,分别表示:矩形的x坐标,矩形的y坐标、矩形的宽度、矩形的高度,且,这些参数的单位都是px。注意哦,(x, y)这个坐标表示的是矩形左上角顶点的位置。

 1         var canvas = document.getElementById('my-canvas');
 2         if (canvas.getContext) {
 3             var ctx = canvas.getContext('2d');
 4             // 设置填充色
 5             ctx.fillStyle = "red";
 6             // 设置描边色
 7             ctx.strokeStyle = "#999";
 8             // 绘制实心矩形
 9             ctx.fillRect(10, 10, 100, 50);
10             // 绘制空心矩形
11             ctx.strokeRect(150, 10, 100, 50);
12         }

 如上图,绘制了一个红色的实心矩形和一个灰色边框的矩形,接下来调用clearRect()方法清除指定区域

ctx.clearRect(20, 20, 30, 30)

5、绘制路径

  图形的基本元素是路径。路径由线段或者曲线相连接形成的不同形状的点的集合。每一个路径都是闭合的。使用路径绘制图形不同于矩形绘制,他需要一些额外的步骤:

  • 创建路径起始点
  • 调用绘制方法绘制路径
  • 封闭路径
  • 通过填充或者描边路径区域来渲染图形

  下面是涉及到的方法:

  • beginPath():表示要开始绘制新路径
  • moveTo(x, y):将画笔移动到指定坐标(x,y),相当于设置路径的起始点坐标,此时不画线
  • lineTo(x, y):绘制一条从当前位置到(x, y)的直线
  • arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x, y)为圆心,绘制一条半径为radius的弧线,且弧的起始角度为startAngle,结束角度为endAngle。counterclockwise表示是否逆时针绘制,默认值为false(顺时针)
  • arcTo(x1, y1, x2, y2, radius):以radius为半径,从当前位置绘制一条弧到(x2, y2),且当前位置以及(x2, y2) 与(x1, y1)的连线分别与弧相切
  • quadraticCurveTo(cx, cy, x, y):绘制二次贝塞尔曲线
  • bezierCurveTo(cx1, cy1, cx2, cy2, x, y):绘制三次贝塞尔曲线
  • closePath():闭合路径,此时图形绘制命令又重新指向到上下文中。
  • fill():填充
  • stroke():描边

下面是一些具体的栗子

5.1 绘制线段

1         var canvas = document.getElementById('my-canvas');
2         if (canvas.getContext) {
3             var ctx = canvas.getContext('2d');
4             ctx.beginPath(); // 新建一条path
5             ctx.moveTo(10, 30); // 画笔移动到(10, 30)
6             ctx.lineTo(100, 30); // 绘制一条从当前位置(10, 30)到(100, 30)的直线
7             ctx.closePath(); // 闭合路径
8             ctx.stroke(); // 绘制路径
9         }    

  

5.2 绘制三角形

 1         var canvas = document.getElementById('my-canvas');
 2         if (canvas.getContext) {
 3             var ctx = canvas.getContext('2d');
 4             ctx.beginPath();
 5             ctx.moveTo(10, 30);
 6             ctx.lineTo(100, 30);
 7             ctx.lineTo(10, 100);
 8             ctx.closePath(); // 虽然只绘制了两条线段,但是closePath会闭合路径。就形成了一个三角形
 9             ctx.stroke(); // 描边
10 
11             ctx.beginPath();
12             ctx.moveTo(120, 30);
13             ctx.lineTo(220, 30);
14             ctx.lineTo(120, 100);
15             ctx.closePath();
16             ctx.fill(); // 填充,实心三角形
17         }    

  

5.3 绘制圆弧

5.3.1 使用arc()绘制圆弧

  这个方法涉及到弧度取值问题,注意,是弧度,不是角度哦。

弧度计算公式:弧度 = 弧长 / 半径 = (n * π * r /180)  / r = (n * π) / 180 ,其中n为圆心角

  将上面的数学计算公式转换为JS表示的计算公式,可以得出:弧度 = Math.PI * (n / 180),其中n为圆心角,也就是我们通常所说的角度。因此如果是45度角,则弧度为Math.PI / 4。

确定好弧度之后,我们还需要知道画弧的起始点,如下图:

圆弧demo1

1         var canvas = document.getElementById('my-canvas');
2         if (canvas.getContext) {
3             var ctx = canvas.getContext('2d');
4             ctx.beginPath();
5             ctx.arc(100, 100, 100, 0, Math.PI / 2, false); // 以(100, 100)为圆心顺时针绘制一个半径为100像素的弧,开始和结束弧度分别为0、Math.PI/2
6             ctx.stroke(); // 没有调用closePath(),因此弧度不闭合
7         }    

       

 圆弧demo2

1         var canvas = document.getElementById('my-canvas');
2         if (canvas.getContext) {
3             var ctx = canvas.getContext('2d');
4             ctx.beginPath();
5             ctx.arc(100, 100, 100, 0, Math.PI / 2, true); // 以(100, 100)为圆心逆时针绘制一个半径为100的圆弧,开始和结束角度为0、Math.PI/2
6             ctx.stroke();
7         } 

 圆弧demo3

 1         var canvas = document.getElementById('my-canvas');
 2         if (canvas.getContext) {
 3             var ctx = canvas.getContext('2d');
 4             ctx.beginPath();
 5             ctx.arc(50, 50, 50, 0, 2 * Math.PI);
 6             ctx.closePath();
 7             ctx.stroke();
 8 
 9             ctx.beginPath();
10             ctx.arc(150, 50, 50, 0, 2 * Math.PI);
11             ctx.closePath();
12             ctx.fill();
13         }

5.3.2 使用arcTo()绘制圆弧

  arcTo(x1, y1, x2, y2, radius)是用来绘制两条切线之间的弧。两条切线分别是:当前位置与(x1, y1)的连线、(x2, y2)与(x1, y1)的连线。

1         var canvas = document.getElementById('my-canvas');
2         if (canvas.getContext) {
3             var ctx = canvas.getContext('2d');
4             ctx.beginPath();
5             ctx.moveTo(50, 50);
6             ctx.arcTo(200, 50, 200, 200, 100);
7             ctx.lineTo(200, 200);
8             ctx.stroke();
9         }

下一篇:【Canvas学习笔记】基础篇(二)

原文地址:https://www.cnblogs.com/jiafifteen/p/11657367.html