目录

一、初识canvas

1.1 基本使用

1.2 示例

1.1 注意点

二、canvas线条相关属性

2.1 常用属性

2.2 示例

2.3 绘制多根线条

c.示例:

三、canvas绘制简单图形

3.1 绘制三角形

3.2  路径绘制

3.3 矩形绘制

3.4 绘制虚线

3.5 绘制表格

3.6 绘制坐标系

3.7 绘制数据点

3.8 绘制折线图

3.9 绘制柱状图

四、渐变背景颜色

4.1 设置图形渐变背景颜色步骤

4.2 绘制圆弧

4.3 绘制饼状图

4.4 绘制文字

4.5 图片绘制

五、绘制动画

六、canvs形变

七、事件绑定


一、初识canvas

Canvas是H5新增的一个标签, 我们可以通过JS在这个标签上绘制各种图案

Canvas 拥有多种绘制路径、矩形、圆形、字符以及图片的方法

Canvas可以替换像flash等其他做动画或游戏的插件的一个标签,能够大大减小页面的结构大小。让页面加载速度变快。

1.1 基本使用

  • canvas标签可以理解为一个‘div’

只不过div是存放元素的,而canvas则是提供了一个区域用来绘制图形。

  • canvas标签习惯上在标签内部对其大小进行设置,例如:

<canvas  width=’300’  height=’300’>您的浏览器不支持canvas标签,请变更支持cnavas标签的浏览器</canvas>

  • canvas标签本身就是一个普通的画板,除此之外没有任何多余的功能

内部的所有内容或图形都需要通过js脚本来完成。

首先,创建canvas画布,在body标签中创建一个canvas标签

其次,进行相关样式设置

最后,如果想要在画布上进行操作,则需要通过脚本来创建一个‘画家’,来帮助我们进行内容绘制。

1.2 示例

        *{margin: 0;padding: 0;}canvas{background: red;}
<canvas>您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
    // 2.通过js代码拿到canvas标签let oCanvas = document.querySelector("canvas");// 3.从canvas标签中获取到绘图工具let oCtx = oCanvas.getContext("2d");// 4.通过绘图工具在canvas标签上绘制图形// 4.1设置路径的起点oCtx.moveTo(50, 50);// 4.2设置路径的终点oCtx.lineTo(200, 50);// 4.3告诉canvas将这些点连接起来oCtx.stroke();

1.1 注意点

  • canvas标签有默认的宽度和高度:默认的宽度是300px;默认的高度是150px
  • 不能通过CSS设置画布的宽高:通过CSS设置画布宽高会在默认宽高的基础上拉伸,如果需要设置canvas宽高请通过元素行内属性width和height设置

<canvas width="500" height="500"></canvas>

  • 线条默认宽度和颜色:通过canvas绘制的线条默认宽度是1px, 颜色是纯黑色;但是由于默认情况下canvas会将线条的中心点和像素的底部对齐,所以会导致显示效果是2px和非纯黑色问题

二、canvas线条相关属性

2.1 常用属性

  • 线型宽度:ctx.lineWith=数值;
  • 设置端点:ctx.lineCap='端点类型';

butt  无端点    round圆角端点    square方块端点

  • 设置连接:ctx.lineJoin='连接类型';

round圆弧连接    bevel截面连接     miter直角连接

  • 设置虚线:ctx.setLineDash([第一段长度,第二段长度...]);
        *{margin: 0;padding: 0;}canvas{background: red;}
<canvas width="300" height="200">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>

2.2 示例

示例1:

        //拿到画布let oCanvas = document.querySelector("canvas");//拿到绘制工具let ctx = oCanvas.getContext("2d");//修改线条高度ctx.lineWidth = 10;//修改线条颜色ctx.strokeStyle = "#fff";//修改线条两端样式// ctx.lineCap="";// ctx.lineCap="square";ctx.lineCap="round";//设置虚线ctx.setLineDash([10,5,20]);//利用后置工具绘制直线// 设置起始位置ctx.moveTo(50,50.5);// 设置路径上的点ctx.lineTo(200,50.5);ctx.lineTo(200,150.5);ctx.lineTo(50,150.5);ctx.lineTo(50,50.5);// 绘制已定义的路径ctx.stroke();

示例2:

var huaban = document.querySelector('canvas');
var ctx = huaban.getContext('2d');
ctx.beginPath(); //开始
ctx.moveTo(40, 80); //起始位置
ctx.lineTo(230, 80);
ctx.lineTo(230, 180);
ctx.lineWidth = 5; //线型宽度
ctx.lineCap = 'butt'; //端点类型  无端点
ctx.lineJoin = 'miter'; //设置连接 直角连接
ctx.setLineDash([10, 5, 20]); //设置虚线 第一段长度,第二段长度,第三段长度...
ctx.stroke();
ctx.closePath(); //结束

2.3 绘制多根线条

a.多根线条注意点:

  • 如果是同一个路径, 那么路径样式会被重用(第二次绘制会复用第一次的样式)
  • 如果是同一个路径, 那么后设置的路径样式会覆盖先设置的路径样式

b.如何给每根线条单独设置路径样式?

每根线条都开启一个新的路径即可

c.示例:

      //拿到画布let oCanvas = document.querySelector("canvas");//拿到绘制工具let ctx = oCanvas.getContext("2d");// //修改线条两端样式// // ctx.lineCap="";// // ctx.lineCap="square";// ctx.lineCap="round";//设置虚线// ctx.setLineDash([10,5,20]);//利用后置工具绘制直线// 设置起始位置ctx.moveTo(50, 50);// 设置路径上的点ctx.lineTo(200, 50);// 修改线条高度ctx.lineWidth = 20;//修改线条颜色ctx.strokeStyle = "blue";// 绘制已定义的路径ctx.stroke();ctx.beginPath(); // 重新开启一个路径ctx.moveTo(50, 100);ctx.lineTo(200, 100);ctx.lineWidth = 10; // 重新设置当前路径样式ctx.strokeStyle = "white";ctx.stroke();ctx.beginPath(); // 重新开启一个路径ctx.moveTo(50, 150);ctx.lineTo(200, 150);ctx.lineWidth = 15; // 重新设置当前路径样式ctx.strokeStyle = "green";ctx.stroke();


三、canvas绘制简单图形

3.1 绘制三角形

closePath():自动创建从当前点回到起始点的路径

lineJoin():设置相交线的拐点样式 miter(默认)、round、bevel

如果通过lineTo()来闭合图形, 那么是不能很好的闭合

默认情况下不会自动从最后一个点连接到起点

      * {margin: 0;padding: 0;}canvas {background: red;display: block;margin: 0 auto;}
  <canvas width="300" height="240">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
      //拿到画布let oCanvas = document.querySelector("canvas");//拿到绘制工具let ctx = oCanvas.getContext("2d");ctx.moveTo(50,50);ctx.lineTo(200,50);ctx.lineTo(200,200);// ctx.lineTo(50,50);ctx.closePath(); // 自动创建从当前点回到起始点的路径ctx.lineWidth = 10;// 设置相交线的拐点样式 miter(默认)、round、bevelctx.lineJoin = "round"; ctx.stroke();


3.2  路径绘制

  • 设置笔触(落笔)点坐标:ctx.moveTo(横,纵);
  • 设置笔触路径:ctx.lineTo(横,纵);
  • 设置笔触颜色:ctx.strokeStyle='颜色';
  • 笔触的绘制:ctx.stroke();
  • 设置填充颜色:ctx.fillStyle='颜色';
  • 设置封闭图形填充:ctx.fill();
  • 开启路径绘制:ctx.beignPath()
  • 结束路径绘制:ctx.closePath()
<canvas width="300" height="300">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
 canvas {border: 1px solid;}
<script>var huaban = document.querySelector('canvas');var ctx = huaban.getContext('2d');//保证有效的图形能够独立ctx.beginPath(); //开启路径绘制ctx.moveTo(50, 50); //设置笔触(落笔)点坐标ctx.lineTo(100, 50); //设置笔触路径ctx.lineTo(75, 100); //设置笔触路径ctx.lineTo(50, 50); //设置笔触路径ctx.fillStyle = 'orange';ctx.fill(); //设置封闭图形填充ctx.closePath(); //结束路径绘制ctx.beginPath(); //开启路径绘制ctx.moveTo(60, 120); //设置笔触(落笔)点坐标ctx.lineTo(150, 190); //设置笔触路径ctx.lineTo(230, 190); //设置笔触路径ctx.lineTo(60, 120); //设置笔触路径ctx.fillStyle = 'blue';ctx.fill(); //设置封闭图形填充ctx.closePath(); //结束路径绘制
</script>


3.3 矩形绘制

      * {margin: 0;padding: 0;}canvas {background: red;display: block;margin: 0 auto;}
<canvas width="500" height="500"></canvas>
      let oCanvas = document.querySelector("canvas");let oCtx = oCanvas.getContext("2d");oCtx.moveTo(100, 100);oCtx.lineTo(300, 100);oCtx.lineTo(300, 300);oCtx.lineTo(100, 300);oCtx.closePath();oCtx.moveTo(250, 150);oCtx.lineTo(150, 150);oCtx.lineTo(150, 250);oCtx.lineTo(250, 250);oCtx.closePath();/*注意点: 只要没有手动开启新的路径, 那么使用的都是默认路径如果都是默认路径, 那么设置的样式在同一个路径中都是有效的* */oCtx.fill();/*对于同一路径,在填充的时候会遵循非零环绕规则从当前的区域拉出一条直线, 遇到顺时针相交的线就+1, 遇到逆时针相交的线就-1最终计算的结果如果是0就不填充, 如果不是0就填充* */

绘制填充矩形:ctx.fillRect(横,纵,宽,高);

绘制描边矩形:ctx.strokeRect(横,纵,宽,高);

擦除矩形区域:ctx.clearRect(横,纵,宽,高);

ctx.fillStyle='blue';
ctx.fillRect(50,70,50,50);
ctx.strokeRect(150,70,50,50);
ctx.clearRect(75,70,100,50);


3.4 绘制虚线

setLineDash():设置

lineDashOffset():设置偏移位

      //拿到画布let oCanvas = document.querySelector("canvas");//拿到绘制工具let ctx = oCanvas.getContext("2d");ctx.moveTo(20,120);ctx.lineTo(280,120);ctx.lineWidth = 2;ctx.strokeStyle = "white";// ctx.setLineDash([2,8]);ctx.setLineDash([2,8,10]);// console.log(ctx.getLineDash());//设置虚线的偏移位 ctx.lineDashOffset = -200;ctx.stroke();


3.5 绘制表格

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
<canvas width="500" height="400">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
      //拿到画布let oCanvas = document.querySelector("canvas");//拿到绘制工具let ctx = oCanvas.getContext("2d");//定义变量,保存小方格的尺寸let gridSize = 10;//拿到 canvas 的宽高let canvasWidth = ctx.canvas.width;let canvasHeight = ctx.canvas.height;// 计算在垂直和水平方向可以画多少条横线let row = Math.floor(canvasHeight / gridSize);let col = Math.floor(canvasWidth / gridSize);//绘制垂直方向的横线for (let i = 0; i < row; i++) {ctx.beginPath();ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点ctx.stroke();}//绘制水平方向的横线for (let i = 0; i < col; i++) {ctx.beginPath();ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点ctx.stroke();}


3.6 绘制坐标系

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
<canvas width="500" height="400">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
      //拿到画布let oCanvas = document.querySelector("canvas");//拿到绘制工具let ctx = oCanvas.getContext("2d");//定义变量,保存小方格的尺寸let gridSize = 50;//拿到 canvas 的宽高let canvasWidth = ctx.canvas.width;let canvasHeight = ctx.canvas.height;// 计算在垂直和水平方向可以画多少条横线let row = Math.floor(canvasHeight / gridSize);let col = Math.floor(canvasWidth / gridSize);//绘制垂直方向的横线for (let i = 0; i < row; i++) {ctx.beginPath();ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点ctx.strokeStyle = "#ccc";ctx.stroke();}//绘制水平方向的横线for (let i = 0; i < col; i++) {ctx.beginPath();ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点ctx.strokeStyle = "#ccc";ctx.stroke();}//计算坐标系原点的位置let originX = gridSize;let originY = canvasHeight - gridSize;//计算X轴终点位置let endX = canvasWidth - gridSize;//绘制X轴ctx.beginPath();ctx.moveTo(originX,originY);ctx.lineTo(endX,originY);ctx.strokeStyle = "#f40";ctx.stroke();//绘制X轴的箭头ctx.lineTo(endX -10,originY + 5);ctx.lineTo(endX -10,originY - 5);ctx.lineTo(endX,originY);ctx.fill();//计算Y轴终点位置let endY = gridSize;//绘制Y轴ctx.beginPath();ctx.moveTo(originX,originY);ctx.lineTo(originX,endY);ctx.strokeStyle = "#f40";ctx.stroke();//绘制Y轴的箭头ctx.lineTo(originX -5,endY + 10);ctx.lineTo(originX +5,endY + 10);ctx.lineTo(originX,endY);ctx.fill();


3.7 绘制数据点

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
<canvas width="500" height="400">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
      //拿到画布let oCanvas = document.querySelector("canvas");//拿到绘制工具let ctx = oCanvas.getContext("2d");//定义变量,保存小方格的尺寸let gridSize = 50;//拿到 canvas 的宽高let canvasWidth = ctx.canvas.width;let canvasHeight = ctx.canvas.height;// 计算在垂直和水平方向可以画多少条横线let row = Math.floor(canvasHeight / gridSize);let col = Math.floor(canvasWidth / gridSize);//绘制垂直方向的横线for (let i = 0; i < row; i++) {ctx.beginPath();ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点ctx.strokeStyle = "#ccc";ctx.stroke();}//绘制水平方向的横线for (let i = 0; i < col; i++) {ctx.beginPath();ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点ctx.strokeStyle = "#ccc";ctx.stroke();}//计算坐标系原点的位置let originX = gridSize;let originY = canvasHeight - gridSize;//计算X轴终点位置let endX = canvasWidth - gridSize;//绘制X轴ctx.beginPath();ctx.moveTo(originX, originY);ctx.lineTo(endX, originY);ctx.strokeStyle = "#f40";ctx.stroke();//绘制X轴的箭头ctx.lineTo(endX - 10, originY + 5);ctx.lineTo(endX - 10, originY - 5);ctx.lineTo(endX, originY);ctx.fill();//计算Y轴终点位置let endY = gridSize;//绘制Y轴ctx.beginPath();ctx.moveTo(originX, originY);ctx.lineTo(originX, endY);ctx.strokeStyle = "#f40";ctx.stroke();//绘制Y轴的箭头ctx.lineTo(originX - 5, endY + 10);ctx.lineTo(originX + 5, endY + 10);ctx.lineTo(originX, endY);ctx.fill();// 拿到服务器返回数据let list = [{x: 100,y: 300,},{x: 200,y: 200,},{x: 300,y: 250,},{x: 400,y: 100,},];let dotLocation = {x: 100,y: 300,};let dotSize = 20;for (let i = 0; i < list.length; i++) {ctx.beginPath();ctx.moveTo(list[i].x - dotSize / 2, list[i].y - dotSize / 2);ctx.lineTo(list[i].x + dotSize - dotSize / 2, list[i].y - dotSize / 2);ctx.lineTo(list[i].x + dotSize - dotSize / 2,list[i].y + dotSize - dotSize / 2);ctx.lineTo(list[i].x - dotSize / 2, list[i].y + dotSize - dotSize / 2);ctx.closePath();ctx.fill();}


3.8 绘制折线图

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
      class LineChart {constructor(width = 300, height = 150) {// 1.创建canvasthis.canvas = document.createElement("canvas");this.canvas.width = width;this.canvas.height = height;document.body.appendChild(this.canvas);// 2.拿到绘图工具this.ctx = this.canvas.getContext("2d");}//画小格子drawGrid(gridSize = 20) {let ctx = this.ctx;//拿到 canvas 的宽高let canvasWidth = ctx.canvas.width;let canvasHeight = ctx.canvas.height;// 计算在垂直和水平方向可以画多少条横线let row = Math.floor(canvasHeight / gridSize);let col = Math.floor(canvasWidth / gridSize);//绘制垂直方向的横线for (let i = 0; i < row; i++) {ctx.beginPath();ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点ctx.strokeStyle = "#ccc";ctx.stroke();}//绘制水平方向的横线for (let i = 0; i < col; i++) {ctx.beginPath();ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点ctx.strokeStyle = "#ccc";ctx.stroke();}}//画坐标系drawCoor(gridSize = 20) {let ctx = this.ctx;let canvasWidth = this.ctx.canvas.width;let canvasHeight = this.ctx.canvas.height;//计算坐标系原点的位置let originX = gridSize;let originY = canvasHeight - gridSize;//计算X轴终点位置let endX = canvasWidth - gridSize;//绘制X轴ctx.beginPath();ctx.moveTo(originX, originY);ctx.lineTo(endX, originY);ctx.strokeStyle = "#f40";ctx.stroke();//绘制X轴的箭头ctx.lineTo(endX - 10, originY + 5);ctx.lineTo(endX - 10, originY - 5);ctx.lineTo(endX, originY);ctx.fill();//计算Y轴终点位置let endY = gridSize;//绘制Y轴ctx.beginPath();ctx.moveTo(originX, originY);ctx.lineTo(originX, endY);ctx.strokeStyle = "#f40";ctx.stroke();//绘制Y轴的箭头ctx.lineTo(originX - 5, endY + 10);ctx.lineTo(originX + 5, endY + 10);ctx.lineTo(originX, endY);ctx.fill();}//绘制数据点drawDot(list, dotSize = 10) {let ctx = this.ctx;for (let i = 0; i < list.length; i++) {ctx.beginPath();ctx.moveTo(list[i].x - dotSize / 2, list[i].y - dotSize / 2);ctx.lineTo(list[i].x + dotSize - dotSize / 2,list[i].y - dotSize / 2);ctx.lineTo(list[i].x + dotSize - dotSize / 2,list[i].y + dotSize - dotSize / 2);ctx.lineTo(list[i].x - dotSize / 2,list[i].y + dotSize - dotSize / 2);ctx.closePath();ctx.fill();}}//绘制折线drawLine(list) {let ctx = this.ctx;ctx.beginPath();for (let i = 0; i < list.length; i++) {if (i === 0) {ctx.moveTo(list[i].x, list[i].y);} else {ctx.lineTo(list[i].x, list[i].y);}}ctx.stroke();}}// 拿到服务器返回数据let list = [{x: 100,y: 300,},{x: 200,y: 200,},{x: 300,y: 250,},{x: 400,y: 100,},];let dotLocation = {x: 100,y: 300,};let lineChart = new LineChart(500, 400);lineChart.drawGrid(50);lineChart.drawCoor(50);lineChart.drawDot(list, 20);lineChart.drawLine(list);


3.9 绘制柱状图

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
      class LineChart {constructor(width = 300, height = 150) {// 1.创建canvasthis.canvas = document.createElement("canvas");this.canvas.width = width;this.canvas.height = height;document.body.appendChild(this.canvas);// 2.拿到绘图工具this.ctx = this.canvas.getContext("2d");}//画小格子drawGrid(gridSize = 20) {let ctx = this.ctx;//拿到 canvas 的宽高let canvasWidth = ctx.canvas.width;let canvasHeight = ctx.canvas.height;// 计算在垂直和水平方向可以画多少条横线let row = Math.floor(canvasHeight / gridSize);let col = Math.floor(canvasWidth / gridSize);//绘制垂直方向的横线for (let i = 0; i < row; i++) {ctx.beginPath();ctx.moveTo(0, i * gridSize - 0.5); //设置路径的起点ctx.lineTo(canvasWidth, i * gridSize - 0.5); //设置路径的终点ctx.strokeStyle = "#ccc";ctx.stroke();}//绘制水平方向的横线for (let i = 0; i < col; i++) {ctx.beginPath();ctx.moveTo(i * gridSize - 0.5, 0); //设置路径的起点ctx.lineTo(i * gridSize - 0.5, canvasHeight); //设置路径的终点ctx.strokeStyle = "#ccc";ctx.stroke();}}//画坐标系drawCoor(gridSize = 20) {let ctx = this.ctx;let canvasWidth = this.ctx.canvas.width;let canvasHeight = this.ctx.canvas.height;//计算坐标系原点的位置let originX = gridSize;let originY = canvasHeight - gridSize;//计算X轴终点位置let endX = canvasWidth - gridSize;//绘制X轴ctx.beginPath();ctx.moveTo(originX, originY);ctx.lineTo(endX, originY);ctx.strokeStyle = "#f40";ctx.stroke();//绘制X轴的箭头ctx.lineTo(endX - 10, originY + 5);ctx.lineTo(endX - 10, originY - 5);ctx.lineTo(endX, originY);ctx.fill();//计算Y轴终点位置let endY = gridSize;//绘制Y轴ctx.beginPath();ctx.moveTo(originX, originY);ctx.lineTo(originX, endY);ctx.strokeStyle = "#f40";ctx.stroke();//绘制Y轴的箭头ctx.lineTo(originX - 5, endY + 10);ctx.lineTo(originX + 5, endY + 10);ctx.lineTo(originX, endY);ctx.fill();}//绘制矩形drawRectangle(list,gridSize=20) {let ctx = this.ctx;let canvasHeight = this.ctx.canvas.height;let originY = canvasHeight - gridSize;//绘制矩形for (let i = 0; i < list.length; i++) {let barHeight = originY - list[i].y;ctx.fillRect(list[i].x, list[i].y, gridSize, barHeight);}}}// 拿到服务器返回数据let list = [{x: 100,y: 300,},{x: 200,y: 200,},{x: 300,y: 250,},];let dotLocation = {x: 100,y: 300,};let lineChart = new LineChart(500, 400);lineChart.drawGrid(50);lineChart.drawCoor(50);lineChart.drawRectangle(list,50);


四、渐变背景颜色

和普通标签一样我们也可以给填充的图形设置线性渐变和径向渐变的背景颜色

4.1 设置图形渐变背景颜色步骤

  1. 通过绘图工具创建渐变背景颜色
  2. 指定渐变的范围
  3. 将渐变背景颜色设置给对应的图形
      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
    <canvas width="500" height="400">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
      let canvas = document.querySelector("canvas");let ctx = canvas.getContext("2d");/* 1.创建渐变方案可以通过x0,y0 / x1,y1确定渐变的方向和渐变的范围* */let linearGradient = ctx.createLinearGradient(100, 100, 300, 300);//  ctx.createRadialGradient();//径向渐变/*2.指定渐变的范围第一个参数是一个百分比 0~1第二个参数是一个颜色* */linearGradient.addColorStop(0, "green");linearGradient.addColorStop(0.5, "yellow");linearGradient.addColorStop(1, "blue");/*3.将渐变背景颜色设置给对应的图形**/ctx.fillStyle = linearGradient;ctx.fillRect(100, 100, 200, 200);


4.2 绘制圆弧

a.基本概念(请翻开初中数学课本)  哈哈~

角度: 一个圆360度, 一个半圆是180度

弧度: 一个圆2π, 一个半圆π

b.角度转换弧度公式:

∵ 180角度 = π弧度

∴ 1角度 = π/180;

∴ 弧度 = 角度 * π/180;

90角度 * π/180 = π/2

c.弧度转换角度公式:

∵ π弧度 = 180角度

∴ 1弧度 = 180/π

∴ 角度 = 弧度 * 180/π

π/2 * 180/π = 180/2 = 90度

ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);

ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,true);

false就是顺时针绘制, true就是逆时针绘制

false先开始后结束, true是先结束后开始,都是顺时针方向画弧

 示例1:画圆和半圆

 canvas {border: 1px solid;}
<canvas width="300" height="300">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
var huaban = document.querySelector('canvas');
var ctx = huaban.getContext('2d');
ctx.beginPath(); //开始落脚
//ctx.arc(150, 150, 50, 0 * Math.PI, 1 * Math.PI, false);//半圆
ctx.arc(150, 150, 50, 0 * Math.PI, 2 * Math.PI, false);//圆
// ctx.stroke();
ctx.fillStyle = 'skyblue'; //填充
ctx.fill();
ctx.closePath(); //结束

 示例1:绘制扇形

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
<canvas width="500" height="400"></canvas>
      // 1.拿到canvaslet canvas = document.querySelector("canvas");// 2.从canvas中拿到绘图工具let ctx = canvas.getContext("2d");//设置起点ctx.moveTo(100,100);//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);ctx.arc(100,100,100,0,Math.PI/2);ctx.closePath();// ctx.stroke();ctx.fill();


4.3 绘制饼状图

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
<canvas width="500" height="400"></canvas>
      // 1.拿到canvaslet canvas = document.querySelector("canvas");// 2.从canvas中拿到绘图工具let ctx = canvas.getContext("2d");//计算圆心的位置let rx = ctx.canvas.width / 2;let ry = ctx.canvas.height / 2;/*//绘制第一个扇形//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);ctx.moveTo(rx, ry);ctx.arc(rx, ry, 100, 0, Math.PI / 2);ctx.fillStyle = randomColor();ctx.fill();//绘制第二个扇形//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);ctx.beginPath(); // 开启新路径ctx.moveTo(rx, ry);ctx.arc(rx, ry, 100, Math.PI / 2, Math.PI);ctx.fillStyle = randomColor();ctx.fill();//绘制第三个扇形//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);ctx.beginPath(); // 开启新路径ctx.moveTo(rx, ry);ctx.arc(rx, ry, 100, Math.PI, Math.PI + Math.PI / 2);ctx.fillStyle = randomColor();ctx.fill();//绘制第四个扇形//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);ctx.beginPath(); // 开启新路径ctx.moveTo(rx, ry);ctx.arc(rx, ry, 100, Math.PI + Math.PI / 2, Math.PI * 2);ctx.fillStyle = randomColor();ctx.fill();*/let startAngle = 0;//开始的弧度for (let i = 1; i <= 4; i++) {// 结束的弧度let endAngle = i * Math.PI / 2;//ctx.arc(圆心x,圆心y,半径r,开始弧度,结束弧度,false);ctx.beginPath(); // 开启新路径ctx.moveTo(rx, ry);ctx.arc(rx, ry, 100, startAngle, endAngle);ctx.fillStyle = randomColor();ctx.fill();// 上一次结束的角度是下一次的起始角度startAngle = endAngle; }//随机生成圆弧填充颜色function randomColor() {let r = Math.floor(Math.random() * 256);let g = Math.floor(Math.random() * 256);let b = Math.floor(Math.random() * 256);return `rgb(${r},${g},${b})`;}


4.4 绘制文字

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
<canvas width="500" height="400"></canvas>
    // 1.拿到canvaslet canvas = document.querySelector("canvas");// 2.从canvas中拿到绘图工具let ctx = canvas.getContext("2d");//3.绘制参考线let canvasWidth = ctx.canvas.width;let canvasHeight = ctx.canvas.height;ctx.moveTo(0,canvasHeight / 2);ctx.lineTo(canvasWidth,canvasHeight / 2);ctx.stroke();ctx.moveTo(canvasWidth / 2,0);ctx.lineTo(canvasWidth / 2,canvasHeight);ctx.stroke();//4.绘制文字let str = '世界很大';//通过 font 属性可以设置文字的大小和样式ctx.font = "50px 微软雅黑";//textBaseline:修改文字垂直方向的对齐方式// 在对齐的时候是以绘制文字的y作为参考点进行对齐的//textBaseline = top/middle/bottomctx.textBaseline = "middle";//textAlign:修改文字水平方向对齐方式// 在对齐的时候是以文字的x作为参考点进行的//textAlign = star/end/centerctx.textAlign = "end";/*** ctx.strokeText(需要绘制的文字,绘制的位置);* 在绘制文字的时候是以文字的左下角作为参考点进行绘制*/// ctx.strokeText(str,canvasWidth / 2,canvasHeight / 2); 或// fillText()绘制的文字是实心;strokeText()绘制的文字是空心ctx.fillText(str,canvasWidth / 2,canvasHeight / 2);

4.5 图片绘制

描述:canvas中绘制图片必须等到图片完全加载成功之后再上屏,否则就会绘制失败。

方法:

ctx.drawImage();

语法:

  • ctx.drawImage(img对象,x,y)

如果只有三个参数, 那么第一个参数就是需要绘制的图片,后面的两个参数是指定图片从什么位置开始绘制

oCtx.drawImage(oImg, 100, 100);

  • ctx.drawImage(img对象,x,y,w,h)

如果只有五个参数, 那么第一个参数就是需要绘制的图片,第二和第三个参数是指定图片从什么位置开始绘制,第四、第五两个参数是指定图片需要拉伸到多大

oCtx.drawImage(oImg, 100, 100, 100, 100);

  • ctx.drawImage(img对象,裁切x,裁切y,裁切w,裁切h,绘制x,绘制y,绘制w,绘制h)

如果有九个参数, 那么第一个参数就是需要绘制的图片,第2~3个参数指定图片上定位的位置,第4~5个参数指定从定位的位置开始截取多大的图片,第6~7个参数指定图片从什么位置开始绘制,最后的两个参数是指定图片需要拉伸到多大

示例:

 canvas {border: 1px solid;}
 <canvas width="1300" height="600">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
var huaban = document.querySelector('canvas');
var ctx = huaban.getContext('2d');ctx.beginPath(); //开始//创建图片
var tempImage = new Image();//加载图片
tempImage.src = 'img/timg.jpg';//图片完全加载后再绘制
tempImage.onload = function() {//将加载的图片绘制到canvas上ctx.drawImage(tempImage, 190, 65, 210, 80, 50, 50, 80, 100);};ctx.closePath(); //结束


五、绘制动画

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
<canvas width="500" height="400"></canvas>
      // 1.拿到canvaslet canvas = document.querySelector("canvas");// 2.从canvas中拿到绘图工具let ctx = canvas.getContext("2d");//3.加载图片let oImg = new Image();oImg.onload = function (){//3.1计算每一张图片的宽高let imageWidth = oImg.width;let imageHeight = oImg.height;let personWidth = imageWidth / 4;let personHeight = imageHeight / 4;//3.2计算绘制的位置let canvasWidth = ctx.canvas.width;let canvasHeight = ctx.canvas.height;let originX = canvasWidth  / 2 - personWidth / 2;let originY = canvasHeight / 2 - personHeight / 2;//3.3绘制图片ctx.drawImage(oImg,0,personHeight *2,personWidth,personHeight,originX,originY,personWidth,personHeight);//3.4实现逐帧动画let index = 1;setInterval(function(){// 清除以前绘制的图片ctx.clearRect(0,0,canvasWidth,canvasHeight);//重新绘制ctx.drawImage(oImg,index * personWidth,personHeight *2,personWidth,personHeight,originX,originY,personWidth,personHeight);index++;if(index > 3){index = 0;}},50);};oImg.src = "images/person.png";

对上面的代码进行封装:

      // 1.拿到canvaslet canvas = document.querySelector("canvas");// 2.从canvas中拿到绘图工具let ctx = canvas.getContext("2d");/*面向对象思想:找到小人对象, 你给我画到指定的位置, 你给我走起来, 你给我停下来* */class Person {constructor(canvas, x, y) {this.canvas = canvas;this.x = x;this.y = y;this.ctx = this.canvas.getContext("2d");this.index = 1;this.timeId = null;// 0正面/1左面/2右面/3后面this.direction = 0;}//绘制render() {//1.加载图片let oImg = new Image();oImg.onload = () => {//1.1计算每一张图片的宽高let imageWidth = oImg.width;let imageHeight = oImg.height;let personWidth = imageWidth / 4;let personHeight = imageHeight / 4;//1.2绘制图片this.ctx.drawImage(oImg, // 需要绘制的图片0, //图片定位的位置this.direction * personHeight, //图片定位的位置personWidth, // 图片裁剪的大小personHeight, // 图片裁剪的大小this.x, // 图片绘制的位置this.y, // 图片绘制的位置personWidth, // 指定图片绘制大小personHeight // 指定图片绘制大小);this.oImg = oImg;this.personWidth = personWidth;this.personHeight = personHeight;};oImg.src = "images/person.png";}//运动方法run(stepX, stepY) {let canvasWidth = this.ctx.canvas.width;let canvasHeight = this.ctx.canvas.height;clearInterval(this.timeId);this.timeId = setInterval(() => {if (stepX !== 0) {this.x += stepX;}if (stepY !== 0) {this.y += stepY;}// 清除以前绘制的图片this.ctx.clearRect(0, 0, canvasWidth, canvasHeight);//重新绘制this.ctx.drawImage(this.oImg, // 需要绘制的图片this.index * this.personWidth, //图片定位的位置this.direction * this.personHeight, //图片定位的位置this.personWidth, // 图片裁剪的大小this.personHeight, // 图片裁剪的大小this.x, // 图片绘制的位置this.y, // 图片绘制的位置this.personWidth, // 指定图片绘制大小this.personHeight // 指定图片绘制大小);this.index++;if (this.index > 3) {this.index = 0;}}, 200);}moveDown() {this.direction = 0;this.run(0, 5);}moveUp() {this.direction = 3;this.run(0, -5);}moveLeft() {this.direction = 1;this.run(-5, 0);}moveRight() {this.direction = 2;this.run(5, 0);}//停止运动方法stop() {clearInterval(this.timeId);}}let person = new Person(canvas, 100, 100);person.render();// person.moveDown();// person.stop();window.onkeydown = function (e) {let key = e.key;// console.log(key);switch (key.toLowerCase()) {case "w":person.moveUp();break;case "s":person.moveDown();break;case "a":person.moveLeft();break;case "d":person.moveRight();break;}};


六、canvs形变

在canvas中所有的形变属性操作的都是坐标系, 而不是图形!!!

      * {margin: 0;padding: 0;}canvas {/* background: red; */display: block;margin: 0 auto;margin: 50px auto;}
<canvas width="500" height="400"></canvas>
      // 1.拿到canvaslet canvas = document.querySelector("canvas");// 2.从canvas中拿到绘图工具let ctx = canvas.getContext("2d");ctx.translate(100,0);//位移ctx.scale(.8,.6);//缩放ctx.rotate(Math.PI/6);//旋转// 3.绘制一个矩形ctx.strokeRect(100, 100, 200, 100);


七、事件绑定

因为整个canvas是一个标签, 所以只能通过监听鼠标在canvas上(事件只能绑定到canvas标签上)的位置来判断是否需要处理对应的图形,当然也可以通过第三方框架来解决交互问题,诸如: zrender.js / Knova.js /three.js / egret.js / pixi.js等等

isPointInPath方法如果开启了一个新的路径, 那么判断的就是该点是否在新的路径的图形中

示例:

        *{margin: 0;padding: 0;}canvas{display: block;margin: 0 auto;/* background: red; */margin: 50px auto;}
 <canvas width="500" height="400">您的浏览器不支持canvas标签,请更换支持canvas标签的浏览器</canvas>
    let oCanvas = document.querySelector("canvas");// 2.从canvas中拿到绘图工具let oCtx = oCanvas.getContext("2d");// 3.绘制矩形let rectX = 100;let rectY = 100;let rectWidth = 100;let rectHeight = 100;oCtx.rect(rectX, rectY, rectWidth, rectHeight);oCtx.fill();oCtx.beginPath();oCtx.rect(200, 200, 100, 100);oCtx.fill();// 4.添加点击事件oCanvas.onclick = function (event) {let x = event.offsetX;let y = event.offsetY;if(x >= rectX && x <= rectX + rectWidth &&y >= rectY && y <= rectY + rectHeight){console.log("矩形被点击了");}else{console.log("矩形没有被点击");}console.log(oCtx.isPointInPath(x, y));}

canvas--初识canvs、绘制:线型、简单图形、渐变背景颜色、绘制动画、canvs形变、事件绑定相关推荐

  1. html5怎么画坐标图,新手如何5分钟学会用canvas在HTML5上画简单图形

    HTML5中的另外一个新元素是标签.须要使用JavaScript来操做和绘制画布. canvas元素为脚本提供了一个依赖于分辨率的位图画布,它能够用于呈现图形.游戏图形或其余可视图像. 当一个更合适的 ...

  2. 新手如何5分钟学会用canvas在HTML5上画简单图形

    HTML5中的另一个新元素是标签.需要使用JavaScript来操作和绘制画布. canvas元素为脚本提供了一个依赖于分辨率的位图画布,它可以用于呈现图形.游戏图形或其他可视图像. 当一个更合适的元 ...

  3. android canvas画渐变背景,View绘制系列(13)-Canvas渐变属性绘制

    Canvas渐变属性绘制 五颜六色,七彩缤纷.有时候我们的UI设计稿也极尽色彩之能,比如下图这样: 这种渐变效果我们能画吗?不得不说,Android系统的基础构架还是很强大的,我们可以使用Linear ...

  4. 用python绘制漂亮的图形-用Python代码绘制漂亮的生日蛋糕,python

    #如何用python绘制生日蛋糕? 平时在经常在b站看到up主绘制生日蛋糕的精美图片.以前学过c.c++语言,也想着用C去绘制一些生日蛋糕,绘制一些女神喜欢的小礼物,不过实现起来比较麻烦,刚好学了一些 ...

  5. 思维导图绘制就是这样简单,手把手教你绘制一幅思维导图

    很多思维导图初学者往往看到别人能很容易的绘制出来各式各样的"高颜值"思维导图的时候,总会有一种羡慕嫉妒恨的心态,为什么自己就不会画呢,其实思维导图的绘制很简单,下面为大家分享绘制思 ...

  6. python绘制二维图形_使用python绘制二维图形示例

    我就废话不多说了,直接上代码吧! import matplotlib.pyplot as plt #也可以使用 import pylab as pl import matplotlib.font_ma ...

  7. 1、背景属性 背景颜色绘制区域——background-clip属性

    background-clip: border-box; 背景被裁剪到边框区域,在内容区.内填充区.边框区域显示,默认值 background-clip: padding-box; 背景被裁剪到内填充 ...

  8. python图形界面化编程GUI(三)事件绑定(鼠标和键盘、OptionMenu、scale、颜色、文件对话框、菜单和工具栏、ttk子模块)

    常用组件汇总 Tkinter类 名称 简介 Toplevel 顶层 容器类,可用于为其他组件提供单独的容器,类似于窗口 Button 按钮 代表按钮组件 Canvas 画布 提供绘图功能,包括直线.矩 ...

  9. matlab绘制螺旋线+隐藏坐标轴+更改背景颜色

    当进行使用螺旋线的图片时,可直接用matlab将螺旋线绘制出来,但是存在坐标轴与图片背景为灰色的情况.查阅资料,可用几句程序就可以实现. close all t=0:0.01:10*pi; x=10* ...

  10. php渐变背景颜色,css背景颜色渐变案例:线性渐变和径向渐变效果实例详解

    渐变是两种或多种颜色之间的平滑过渡.以前,必须使用图像来实现这些效果.但是,通过使用 CSS3 渐变(gradients),可以减少下载的事件和宽带的使用.此外,渐变效果的元素在放大时看起来效果更好, ...

最新文章

  1. 在温系统下制作马克系统引导安装镜像启动U盘安装马克OS
  2. 单目3D物体级SLAM | CubeSLAM: Monocular 3D Object SLAM
  3. SuSE sftp限制用户活动目录
  4. 透过浏览器看HTTP缓存(转)
  5. 标准化条件变量 -- condition_variable
  6. 硬核妹子的创意设计:舌头控制器
  7. 运行bat批处理文件不出现黑框
  8. Linux Shell脚本_设置时区并同步时间
  9. 诸如fluke等网络测试仪的工作原理简介
  10. mysql故障排查思路_Mysql高负载排查思路
  11. C语言基础函数(二)
  12. docker xware下载慢_win7环境下Docker快速构建及阿里云容器加速配置
  13. android开发JNI之高级篇
  14. opencv-python中文文档
  15. 数据库在一对一、一对多、多对多怎么设计表关系
  16. vscan Ineligible for use by VSAN
  17. 快速提升网站排名_使用快排优化的方法
  18. 滚动条 实现的细节代码 SCROLLINFO
  19. 卡方分布上侧α分位数的近似公式及其证明
  20. fofa第一个查找漏洞

热门文章

  1. 用C++开发的双人对战五子棋
  2. 计算机串口是232吗,RS232串口简介
  3. 广搜算法之翻转棋子游戏
  4. 智方8000系房地产进销存管理系统 v4.30 官网
  5. 如何关闭Windows 1011自动更新
  6. 服务器虚拟网卡驱动卸载,Win10安装和卸载万能网卡版驱动的方法
  7. 火狐浏览器去除广告插件
  8. Cholesky分解及一个例子
  9. 各种调试接口(SWD、JTAG、Jlink、Ulink、STlink)的区别
  10. 马尔可夫模型 Markov Model