常用Canvas实例

1,926 阅读23分钟

一.什么是Canvas?

HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。

画布是一个矩形区域,您可以控制其每一像素。

canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

二.创建Canvas元素

向 HTML5 页面添加 canvas 元素。

规定元素的 id、宽度和高度:

    <canvas id="myCanvas" width="200" height="100"></canvas>

Canvas坐标系

通过JavaScript来绘制

    /*获取元素*/
    var myCanvas = document.querySelector('#myCanvas');
    /*获取绘图工具*/
    var context = myCanvas.getContext('2d');
    /*设置绘图的起始位置*/
    context.moveTo(100,100);
    /*绘制路径*/
    context.lineTo(200,200);
    /*描边*/
    context.stroke();

三.Canvas的基本使用

1.图形绘制

需要理解些概念:

  • 路径的概念
  • 路径的绘制
    • 描边 stroke()
    • 填充 fill()
  • 闭合路径
    • 手动闭合
    • 程序闭合 closePath()
  • 填充规则(非零环绕)
  • 开启新的路径 beginPath()

2.设置样式

  • 画笔的状态
    • lineWidth 线宽,默认1px
    • lineCap 线末端类型:(butt默认)、round、square
    • lineJoin 相交线的拐点 miter(默认)、round、bevel
    • strokeStyle 线的颜色
    • fillStyle 填充颜色
    • setLineDash() 设置虚线
    • getLineDash() 获取虚线宽度集合
    • lineDashOffset 设置虚线偏移量(负值向右偏移)

四.Canvas图形绘制

1.矩形绘制

  • rect(x,y,w,h) 没有独立路径
  • strokeRect(x,y,w,h) 有独立路径,不影响别的绘制
  • fillRect(x,y,w,h) 有独立路径,不影响别的绘制
  • clearRect(x,y,w,h) 擦除矩形区域

2.圆弧绘制

  • 弧度概念
  • arc()
    • x 圆心横坐标
    • y 圆心纵坐标
    • r 半径
    • startAngle 开始角度
    • endAngle 结束角度
    • anticlockwise 是否逆时针方向绘制(默认false表示顺时针;true表示逆时针)

3.绘制文本

  • ctx.font = '微软雅黑' 设置字体
  • strokeText()
  • fillText(text,x,y,maxWidth)
    • text 要绘制的文本
    • x,y 文本绘制的坐标(文本左下角)
    • maxWidth 设置文本最大宽度,可选参数
  • ctx.textAlign文本水平对齐方式,相对绘制坐标来说的
    • left
    • center
    • right
    • start 默认
    • end
    • direction属性css(rtl ltr) start和end于此相关
      • 如果是ltr,start和left表现一致
      • 如果是rtl,start和right表现一致
  • ctx.textBaseline 设置基线(垂直对齐方式 )
    • top 文本的基线处于文本的正上方,并且有一段距离
    • middle 文本的基线处于文本的正中间
    • bottom 文本的基线处于文本的证下方,并且有一段距离
    • hanging 文本的基线处于文本的正上方,并且和文本粘合
    • alphabetic 默认值,基线处于文本的下方,并且穿过文字
    • ideographic 和bottom相似,但是不一样
  • measureText() 获取文本宽度obj.width

五.做动画

1.绘制图片

  • drawImage()
    • 三个参数drawImage(img,x,y)
      • img 图片对象、canvas对象、video对象
      • x,y 图片绘制的左上角
    • 五个参数drawImage(img,x,y,w,h)
      • img 图片对象、canvas对象、video对象
      • x,y 图片绘制的左上角
      • w,h 图片绘制尺寸设置(图片缩放,不是截取)
    • 九个参数drawImage(img,x,y,w,h,x1,y1,w1,h1)
      • img 图片对象、canvas对象、video对象
      • x,y,w,h 图片中的一个矩形区域
      • x1,y1,w1,h1 画布中的一个矩形区域

2.序列帧动画

  • 绘制精灵图
  • 动起来
  • 控制边界
  • 键盘控制

3.坐标变换

  • 平移 移动画布的原点
    • translate(x,y) 参数表示移动目标点的坐标
  • 缩放
    • scale(x,y) 参数表示宽高的缩放比例
  • 旋转
    • rotate(angle) 参数表示旋转角度

六.常用实例

1.体验canvas绘图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas{
            border: 1px solid #ccc;
            /*不建议在 样式设置尺寸*/
            /*width: 600px;
            height: 400px;*/
        }
    </style>
</head>
<body>
<!--1.准备画布-->
<!--1.1 画布是白色的 而且默认300*150-->
<!--1.2 设置画布的大小  width="600" height="400" -->
<canvas width="600" height="400" ></canvas>
<!--2.准备绘制工具-->
<!--3.利用工具绘图-->
<script>
    /*1.获取元素*/
    var myCanvas = document.querySelector('canvas');
    /*2.获取上下文 绘制工具箱 */
    /*是否有3d 暂时没有*/
    var ctx = myCanvas.getContext('2d'); /*web gl 绘制3d效果的网页技术*/
    /*3.移动画笔*/
    ctx.moveTo(100,100);
    /*4.绘制直线 (轨迹,绘制路径)*/
    ctx.lineTo(200,100);
    /*5.描边*/
    ctx.stroke();
</script>
</body>
</html>

2.绘制平行线

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*画平行线*/
    ctx.moveTo(100,100.5);
    ctx.lineTo(300,100.5);

    ctx.moveTo(100,200);
    ctx.lineTo(300,200);

    /*描边*/
    ctx.stroke();


    /*关于线条的问题*/
    /*1.默认的宽度是多少   1px*/
    /*2.默认的颜色是什么   黑色*/
    /*产生原因  对齐的点是线的中心位置  会把线分成两个0.5px 显示的是会不饱和增加宽度*/
    /*解决方案  前后移动0.5px */

</script>
</body>
</html>

3.绘制三条不同颜色和宽度的平行线

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*画平行线*/
    ctx.beginPath();/*Kai*/
    /*蓝色  10px*/
    ctx.moveTo(100,100);
    ctx.lineTo(300,100);
    ctx.strokeStyle = 'blue';
    ctx.lineWidth = 10;
    /*描边*/
    ctx.stroke();


    /*红色 20px*/
    ctx.moveTo(100,200);
    ctx.lineTo(300,200);
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 20;
    /*描边*/
    ctx.stroke();


    /*绿色 30px*/
    ctx.moveTo(100,300);
    ctx.lineTo(300,300);
    ctx.strokeStyle = 'green';
    ctx.lineWidth = 30;
    /*描边*/
    ctx.stroke();


</script>
</body>
</html>

4.绘制一个填充的三角形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*1.绘制一个三角形*/
    ctx.moveTo(100,100);
    ctx.lineTo(200,100);
    ctx.lineTo(200,200);
    /*起始点和lineTo的结束点无法完全闭合缺角*/
    /*使用canvas的自动闭合 */
    //ctx.lineTo(100,100);
    /*关闭路径*/
    ctx.closePath();


    ctx.lineWidth = 10;
    /*2.描边*/
    ctx.stroke();
    /*3.填充*/
    //ctx.fill();

</script>
</body>
</html>

5.绘制一个镂空正方形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*1.绘制两个正方形 一大200一小100 套在一起*/
    ctx.moveTo(100,100);
    ctx.lineTo(300,100);
    ctx.lineTo(300,300);
    ctx.lineTo(100,300);
    ctx.closePath();

    ctx.moveTo(150,150);
    
    ctx.lineTo(150,250);
    ctx.lineTo(250,250);
    ctx.lineTo(250,150);
    ctx.closePath();

    /*2.去填充*/
    //ctx.stroke();
    ctx.fillStyle = 'red';
    ctx.fill();

    /*在填充的时候回遵循非零环绕规则*/
</script>
</body>
</html>

6.和线相关的属性和方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*画平行线*/
    ctx.beginPath();
    ctx.moveTo(100,100);
    ctx.lineTo(200,20);
    ctx.lineTo(300,100);
    ctx.strokeStyle = 'blue';
    ctx.lineWidth = 10;
    ctx.lineCap = 'butt';
    ctx.lineJoin = 'miter';
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(100,200);
    ctx.lineTo(200,120);
    ctx.lineTo(300,200);
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 20;
    ctx.lineCap = 'square';
    ctx.lineJoin = 'bevel';
    ctx.stroke();


    ctx.beginPath();
    ctx.moveTo(100,300);
    ctx.lineTo(200,220);
    ctx.lineTo(300,300);
    ctx.strokeStyle = 'green';
    ctx.lineWidth = 30;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    ctx.stroke();


</script>
</body>
</html>

7.绘制虚线

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*画线*/
    ctx.moveTo(100,100.5);
    ctx.lineTo(300,100.5);
    /*[5,10] 数组是用来描述你的排列方式的*/
    ctx.setLineDash([20]);
    /*获取虚线的排列方式 获取的是不重复的那一段的排列方式*/
    console.log(ctx.getLineDash());

    /*如果是正的值 往后偏移*/
    /*如果是负的值 往前偏移*/
    ctx.lineDashOffset = -20;

    ctx.stroke();

</script>
</body>
</html>

8.绘制一个从黑到白的渐变矩形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*绘制一个矩形*/
    /*线是由点构成的*/
    /*ctx.moveTo(100,100);
    ctx.lineTo(355,100);
    ctx.lineWidth = 30;*/
    /*颜色的填充*/
    //ctx.strokeStyle = '#fff';
    /*黑到白的渐变颜色*/
   /* ctx.stroke();*/

    /*线是由点构成的*/
    ctx.lineWidth = 30;
    for (var i = 0; i < 255; i++) {
        ctx.beginPath();
        ctx.moveTo(100+i-1,100);
        ctx.lineTo(100+i,100);
        ctx.strokeStyle = 'rgb('+i+',0,0)';
        ctx.stroke();
    }

</script>
</body>
</html>

9.绘制网格

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*1.绘制网格*/
    /*2.网格的大小*/
    var gridSize = 10;
    var canvasHeight = ctx.canvas.height;
    var canvasWidth = ctx.canvas.width;
    /*3.画多少条X轴方向的线 横线的条数  画布高度*/
    /*var canvasHeight = myCanvas.height;
    var canvasWidth = myCanvas.width;
    console.log(canvasHeight);
    console.log(canvasWidth);*/
    /*console.log(ctx.canvas.width);
    console.log(ctx.canvas.height);*/
    var xLineTotal = Math.floor(canvasHeight / gridSize);
    for (var i = 0; i <= xLineTotal; i++) {
        ctx.beginPath();
        ctx.moveTo(0, i * gridSize - 0.5 );
        ctx.lineTo(canvasWidth, i * gridSize - 0.5);
        ctx.strokeStyle = '#eee';
        ctx.stroke();
    }
    /*4.画多少条Y轴方向的线*/
    var yLineTotal = Math.floor(canvasWidth / gridSize);
    for (var i = 0; i <= yLineTotal; i++) {
        ctx.beginPath();
        ctx.moveTo(i*gridSize - 0.5 ,0);
        ctx.lineTo(i*gridSize - 0.5 ,canvasHeight);
        ctx.strokeStyle = '#eee';
        ctx.stroke();
    }
    /*5.遍历的形式去画*/
</script>
</body>
</html>

10.绘制坐标系

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*1.绘制坐标系*/
    /*2.确定原点*/
    /*3.确定距离画布旁边的距离*/
    /*4.确定坐标轴的长度*/
    /*5.确定箭头的大小  是个等腰三角形  10 */
    /*6.绘制箭头填充*/

    var space = 20;
    var arrowSize = 10;

    /*计算原点*/
    var canvasWidth = ctx.canvas.width;
    var canvasHeight = ctx.canvas.height;

    var x0 = space;
    var y0 = canvasHeight - space;

    /*绘制x轴*/
    ctx.beginPath();
    ctx.moveTo(x0, y0);
    ctx.lineTo(canvasWidth - space, y0);
    /*箭头*/
    ctx.lineTo(canvasWidth - space - arrowSize, y0 + arrowSize / 2);
    ctx.lineTo(canvasWidth - space - arrowSize, y0 - arrowSize / 2);
    ctx.lineTo(canvasWidth - space, y0);
    ctx.fill();
    ctx.stroke();

    /*绘制y轴*/
    ctx.beginPath();
    ctx.moveTo(x0, y0);
    ctx.lineTo(space, space);
    /*箭头*/
    ctx.lineTo(space + arrowSize / 2, space + arrowSize);
    ctx.lineTo(space - arrowSize / 2, space + arrowSize);
    ctx.lineTo(space, space);
    ctx.fill();
    ctx.stroke();


</script>
</body>
</html>

11.绘制点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*1.绘制点*/
    /*2.点的尺寸*/
    /*3.以坐标中心绘制点*/

    /*点坐标*/
    var coordinate = {
        x:100,
        y:100
    }
    /*点尺寸*/
    var dottedSize = 10;

    ctx.moveTo(coordinate.x - dottedSize / 2,coordinate.y - dottedSize / 2);
    ctx.lineTo(coordinate.x + dottedSize / 2,coordinate.y - dottedSize / 2);
    ctx.lineTo(coordinate.x + dottedSize / 2,coordinate.y + dottedSize / 2);
    ctx.lineTo(coordinate.x - dottedSize / 2,coordinate.y + dottedSize / 2);
    ctx.closePath();
    ctx.fill();



</script>
</body>
</html>

12.折线图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    /*1.构造函数*/
    var LineChart = function (ctx) {
        /*获取绘图工具*/
        this.ctx = ctx || document.querySelector('canvas').getContext('2d');
        /*画布的大小*/
        this.canvasWidth = this.ctx.canvas.width;
        this.canvasHeight = this.ctx.canvas.height;
        /*网格的大小*/
        this.gridSize = 10;
        /*坐标系的间距*/
        this.space = 20;
        /*坐标原点*/
        this.x0 = this.space;
        this.y0 = this.canvasHeight - this.space;
        /*箭头的大小*/
        this.arrowSize = 10;
        /*绘制点*/
        this.dottedSize = 6;
        /*点的坐标 和数据有关系  数据可视化*/
    }
    /*2.行为方法*/
    LineChart.prototype.init = function (data) {
        this.drawGrid();
        this.drawAxis();
        this.drawDotted(data);
    };
    /*绘制网格*/
    LineChart.prototype.drawGrid = function () {
        /*x方向的线*/
        var xLineTotal = Math.floor(this.canvasHeight / this.gridSize);
        this.ctx.strokeStyle = '#eee';
        for (var i = 0; i <= xLineTotal; i++) {
            this.ctx.beginPath();
            this.ctx.moveTo(0, i * this.gridSize - 0.5);
            this.ctx.lineTo(this.canvasWidth, i * this.gridSize - 0.5);
            this.ctx.stroke();
        }
        /*y方向的线*/
        var yLineTotal = Math.floor(this.canvasWidth / this.gridSize);
        for (var i = 0; i <= yLineTotal; i++) {
            this.ctx.beginPath();
            this.ctx.moveTo(i * this.gridSize - 0.5, 0);
            this.ctx.lineTo(i * this.gridSize - 0.5, this.canvasHeight);
            this.ctx.stroke();
        }
    };
    /*绘制坐标系*/
    LineChart.prototype.drawAxis = function () {
        /*X轴*/
        this.ctx.beginPath();
        this.ctx.strokeStyle = '#000';
        this.ctx.moveTo(this.x0, this.y0);
        this.ctx.lineTo(this.canvasWidth - this.space, this.y0);
        this.ctx.lineTo(this.canvasWidth - this.space - this.arrowSize, this.y0 + this.arrowSize / 2);
        this.ctx.lineTo(this.canvasWidth - this.space - this.arrowSize, this.y0 - this.arrowSize / 2);
        this.ctx.lineTo(this.canvasWidth - this.space, this.y0);
        this.ctx.stroke();
        this.ctx.fill();
        /*Y轴*/
        this.ctx.beginPath();
        this.ctx.strokeStyle = '#000';
        this.ctx.moveTo(this.x0, this.y0);
        this.ctx.lineTo(this.space, this.space);
        this.ctx.lineTo(this.space + this.arrowSize / 2, this.space + this.arrowSize);
        this.ctx.lineTo(this.space - this.arrowSize / 2, this.space + this.arrowSize);
        this.ctx.lineTo(this.space, this.space);
        this.ctx.stroke();
        this.ctx.fill();
    };
    /*绘制所有点*/
    LineChart.prototype.drawDotted = function (data) {
        /*1.数据的坐标 需要转换 canvas坐标*/
        /*2.再进行点的绘制*/
        /*3.把线连起来*/
        var that = this;
        /*记录当前坐标*/
        var prevCanvasX = 0;
        var prevCanvasY = 0;
        data.forEach(function (item, i) {
            /* x = 原点的坐标 + 数据的坐标 */
            /* y = 原点的坐标 - 数据的坐标 */
            var canvasX = that.x0 + item.x;
            var canvasY = that.y0 - item.y;
            /*绘制点*/
            that.ctx.beginPath();
            that.ctx.moveTo(canvasX - that.dottedSize / 2, canvasY - that.dottedSize / 2);
            that.ctx.lineTo(canvasX + that.dottedSize / 2, canvasY - that.dottedSize / 2);
            that.ctx.lineTo(canvasX + that.dottedSize / 2, canvasY + that.dottedSize / 2);
            that.ctx.lineTo(canvasX - that.dottedSize / 2, canvasY + that.dottedSize / 2);
            that.ctx.closePath();
            that.ctx.fill();
            /*点的连线*/
            /*当时第一个点的时候 起点是 x0 y0*/
            /*当时不是第一个点的时候 起点是 上一个点*/
            if(i == 0){
                that.ctx.beginPath();
                that.ctx.moveTo(that.x0,that.y0);
                that.ctx.lineTo(canvasX,canvasY);
                that.ctx.stroke();
            }else{
                /*上一个点*/
                that.ctx.beginPath();
                that.ctx.moveTo(prevCanvasX,prevCanvasY);
                that.ctx.lineTo(canvasX,canvasY);
                that.ctx.stroke();
            }
            /*记录当前的坐标,下一次要用*/
            prevCanvasX = canvasX;
            prevCanvasY = canvasY;
        });
    };
    /*3.初始化*/
    var data = [
        {
            x: 100,
            y: 120
        },
        {
            x: 200,
            y: 160
        },
        {
            x: 300,
            y: 240
        },
        {
            x: 400,
            y: 120
        },
        {
            x: 500,
            y: 80
        }
    ];
    var lineChart = new LineChart();
    lineChart.init(data);
</script>
</body>
</html>

13.绘制矩形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*绘制矩形路径 不是独立路径*/
    /*ctx.rect(100,100,200,100);
    ctx.fillStyle = 'green';
    ctx.stroke();
    ctx.fill();*/

    /*绘制矩形  有自己的独立路径*/
    //ctx.strokeRect(100,100,200,100);
    ctx.fillRect(100,100,200,100);

    /*清除矩形的内容*/
    ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);

    //ctx.fillRect(100,100,200,100);

</script>
</body>
</html>

14.绘制一个渐变颜色的矩形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
/*        .linearGradient{
            width: 400px;
            height: 100px;
            background-image: linear-gradient(to right,pink,blue);
        }*/
    </style>
</head>
<body>
<div class="linearGradient"></div>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*fillStyle 'pink' '#000' 'rgb()' 'rgba()' */
    /*也可以使用一个渐变的方案了填充矩形*/
    /*创建一个渐变的方案*/
    /*渐变是由长度的*/
    /*x0y0 起始点 x1y1 结束点  确定长度和方向*/
    var linearGradient = ctx.createLinearGradient(100,100,500,400);
    linearGradient.addColorStop(0,'pink');
    //linearGradient.addColorStop(0.5,'red');
    linearGradient.addColorStop(1,'blue');

    ctx.fillStyle = linearGradient;

    ctx.fillRect(100,100,400,100);

    /*pink---->blue*/
    /*回想线性渐变---->要素 方向  起始颜色 结束颜色 */
    /*通过两个点的坐标可以控制 渐变方向*/
</script>
</body>
</html>

15.什么是弧度

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--
1.什么是弧度  是一种长度的描述单位
2.一个弧度怎么去描述  一个圆有多少个弧度  2 * π
3.一弧度有多长  一个弧度一个半径的长度


角度:一个圆是360度
半径:已一个点为中心多长为放射半径
周长:2 * π * r


最终的结论:一个角度等于多少弧度  π/180
-->
</body>
</html>

16.理解曲线的绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*1.体验曲线的绘制*/
    /*2.线是由点构成的*/
    /*3.曲线可以由数学公式得来*/

    /*公式:y = x/2 */
    /*公式:y = (x + 2) ^2  */
    /*公式:y = sin(x) */

    for(var i = 1 ; i < 600 ; i ++){
        var x = i;
        //var y = x/2;
        //var y = Math.pow(x/10-30,2);
        var y = 50*Math.sin(x/10) + 100;
        ctx.lineTo(x,y);
    }
    ctx.stroke();
</script>
</body>
</html>

17.绘制四分之一个圆弧

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*绘制圆弧*/
    /*确定圆心  坐标 x y*/
    /*确定圆半径  r */
    /*确定起始绘制的位置和结束绘制的位置  确定弧的长度和位置  startAngle endAngle   弧度*/
    /*取得绘制的方向 direction 默认是顺时针 false 逆时针 true */

    /*在中心位置画一个半径150px的圆弧左下角*/
    var w = ctx.canvas.width;
    var h = ctx.canvas.height;
    ctx.arc(w/2,h/2,150,Math.PI/2,Math.PI,true);
    ctx.stroke();


</script>
</body>
</html>

18.绘制一个右上角的四分之一的扇形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*在中心位置画一个半径150px的圆弧右上角 扇形  边  填充 */
    var w = ctx.canvas.width;
    var h = ctx.canvas.height;

    /*把起点放到圆心位置*/
    ctx.moveTo(w/2,h/2);

    ctx.arc(w/2,h/2,150,0,-Math.PI/2,true);

    /*闭合路径*/
    //ctx.closePath();

    ctx.fill();
</script>
</body>
</html>

19.绘制一个圆分成六等分颜色随机

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    var w = ctx.canvas.width;
    var h = ctx.canvas.height;

    /*分成几等分*/
    var num = 360;
    /*一份多少弧度*/
    var angle = Math.PI * 2 / num;

    /*原点坐标*/
    var x0 = w / 2;
    var y0 = h / 2;

    /*获取随机颜色*/
    var getRandomColor = function () {
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    }

    /*上一次绘制的结束弧度等于当前次的起始弧度*/
    //var startAngle = 0;
    for (var i = 0; i < num; i++) {
        var startAngle = i * angle;
        var endAngle = (i + 1) * angle;
        ctx.beginPath();
        ctx.moveTo(x0, y0);
        ctx.arc(x0, y0, 150, startAngle, endAngle);
        /*随机颜色*/
        ctx.fillStyle = getRandomColor();
        ctx.fill();
    }
</script>
</body>
</html>

20.绘制一个根据数据的饼图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*1.根据37期的年龄分布绘制饼图*/
    /*2.准备统计的数据*/
    /*15-20岁 6个*/
    /*20-25岁 30个*/
    /*25-30岁 10个*/
    /*30-35岁 8个*/
    var data = [6, 30, 10, 8];
    /*3.在饼图表示出来*/
    /*4.需要把数据转出弧度*/
    var angleList = [];
    var total = 0;
    data.forEach(function (item, i) {
        total += item;
    });
    console.log(total);
    /*第二是转换成弧度的时候就可以去绘制扇形 减少一次遍历*/
    data.forEach(function (item, i) {
        var angle = Math.PI * 2 * (item/total);
        angleList.push(angle);
    });
    console.log(angleList);
    /*5.根据弧度绘制扇形*/

    var w = ctx.canvas.width;
    var h = ctx.canvas.height;
    var x0 = w/2;
    var y0 = h/2;
    /*获取随机颜色*/
    var getRandomColor = function () {
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    }


    var startAngle = 0;
    angleList.forEach(function (item,i) {
        /*上一次绘制的结束弧度等于当前次的起始弧度*/
        var endAngle = startAngle + item;
        ctx.beginPath();
        ctx.moveTo(x0,y0);
        ctx.arc(x0,y0,150,startAngle,endAngle);
        ctx.fillStyle = getRandomColor();
        ctx.fill();
        /*记录当前的结束位置作为下一次的起始位置*/
        startAngle = endAngle;
    });

</script>
</body>
</html>

21.绘制在画布中心的一段文字

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 100px auto;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*1.在画布的中心绘制一段文字*/
    /*2.申明一段文字*/
    var str = '您吃-,了吗';
    /*3.确定画布的中心*/
    var w = ctx.canvas.width;
    var h = ctx.canvas.height;
    /*4.画一个十字架在画布的中心*/
    ctx.beginPath();
    ctx.moveTo(0, h / 2 - 0.5);
    ctx.lineTo(w, h / 2 - 0.5);
    ctx.moveTo(w / 2 - 0.5, 0);
    ctx.lineTo(w / 2 - 0.5, h);
    ctx.strokeStyle = '#eee';
    ctx.stroke();
    /*5.绘制文本*/
    ctx.beginPath();
    ctx.strokeStyle = '#000';
    var x0 = w/2;
    var y0 = h/2;
    /*注意:起点位置在文字的左下角*/
    /*有文本的属性  尺寸 字体  左右对齐方式  垂直对齐的方式*/
    ctx.font = '40px Microsoft YaHei';
    /*左右对齐方式 (center left right start end) 基准起始坐标*/
    ctx.textAlign = 'center';
    /*垂直对齐的方式 基线 baseline(top,bottom,middle) 基准起始坐标*/
    ctx.textBaseline = 'middle';
    //ctx.direction = 'rtl';
    //ctx.strokeText(str,x0,y0);
    ctx.fillText(str,x0,y0);
    /*6.画一个下划线和文字一样长*/
    ctx.beginPath();
    /*获取文本的宽度*/
    console.log(ctx.measureText(str));
    var width = ctx.measureText(str).width;
    ctx.moveTo(x0-width/2,y0 + 20);
    ctx.lineTo(x0+width/2,y0 + 20);
    ctx.stroke();

</script>
</body>
</html>

22.绘制饼状图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 100px auto;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    /*var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');*/

    /*1.绘制饼状态图*/
    /*1.1 根据数据绘制一个饼图*/
    /*1.2 绘制标题 从扇形的弧中心伸出一条线在画一条横线在横线的上面写上文字标题*/
    /*1.3 在画布的左上角 绘制说明 一个和扇形一样颜色的矩形 旁边就是文字说明*/

    var PieChart = function (ctx) {
        /*绘制工具*/
        this.ctx = ctx || document.querySelector('canvas').getContext('2d');
        /*绘制饼图的中心*/
        this.w = this.ctx.canvas.width;
        this.h = this.ctx.canvas.height;
        /*圆心*/
        this.x0 = this.w / 2 + 60;
        this.y0 = this.h / 2;
        /*半径*/
        this.radius = 150;
        /*伸出去的线的长度*/
        this.outLine = 20;
        /*说明的矩形大小*/
        this.rectW = 30;
        this.rectH = 16;
        this.space = 20;
    }
    PieChart.prototype.init = function (data) {
        /*1.准备数据*/
        this.drawPie(data);
    };
    PieChart.prototype.drawPie = function (data) {
        var that = this;
        /*1.转化弧度*/
        var angleList = this.transformAngle(data);
        /*2.绘制饼图*/
        var startAngle = 0;
        angleList.forEach(function (item, i) {
            /*当前的结束弧度要等于下一次的起始弧度*/
            var endAngle = startAngle + item.angle;
            that.ctx.beginPath();
            that.ctx.moveTo(that.x0, that.y0);
            that.ctx.arc(that.x0, that.y0, that.radius, startAngle, endAngle);
            var color = that.ctx.fillStyle = that.getRandomColor();
            that.ctx.fill();
            /*下一次要使用当前的这一次的结束角度*/
            /*绘制标题*/
            that.drawTitle(startAngle, item.angle, color , item.title);
            /*绘制说明*/
            that.drawDesc(i,item.title);
            startAngle = endAngle;
        });
    };
    PieChart.prototype.drawTitle = function (startAngle, angle ,color , title) {
        /*1.确定伸出去的线 通过圆心点 通过伸出去的点  确定这个线*/
        /*2.确定伸出去的点 需要确定伸出去的线的长度*/
        /*3.固定伸出去的线的长度*/
        /*4.计算这个点的坐标*/
        /*5.需要根据角度和斜边的长度*/
        /*5.1 使用弧度  当前扇形的起始弧度 + 对应的弧度的一半 */
        /*5.2 半径+伸出去的长度 */
        /*5.3 outX = x0 + cos(angle) * ( r + outLine)*/
        /*5.3 outY = y0 + sin(angle) * ( r + outLine)*/
        /*斜边*/
        var edge = this.radius + this.outLine;
        /*x轴方向的直角边*/
        var edgeX = Math.cos(startAngle + angle / 2) * edge;
        /*y轴方向的直角边*/
        var edgeY = Math.sin(startAngle + angle / 2) * edge;
        /*计算出去的点坐标*/
        var outX = this.x0 + edgeX;
        var outY = this.y0 + edgeY;
        this.ctx.beginPath();
        this.ctx.moveTo(this.x0, this.y0);
        this.ctx.lineTo(outX, outY);
        this.ctx.strokeStyle = color;
        /*画文字和下划线*/
        /*线的方向怎么判断 伸出去的点在X0的左边 线的方向就是左边*/
        /*线的方向怎么判断 伸出去的点在X0的右边 线的方向就是右边*/
        /*结束的点坐标  和文字大小*/
        this.ctx.font = '14px Microsoft YaHei';
        var textWidth = this.ctx.measureText(title).width ;
        if(outX > this.x0){
            /*右*/
            this.ctx.lineTo(outX + textWidth,outY);
            this.ctx.textAlign = 'left';
        }else{
            /*左*/
            this.ctx.lineTo(outX - textWidth,outY);
            this.ctx.textAlign = 'right';
        }
        this.ctx.stroke();
        this.ctx.textBaseline = 'bottom';
        this.ctx.fillText(title,outX,outY);

    };
    PieChart.prototype.drawDesc = function (index,title) {
        /*绘制说明*/
        /*矩形的大小*/
        /*距离上和左边的间距*/
        /*矩形之间的间距*/
        this.ctx.fillRect(this.space,this.space + index * (this.rectH + 10),this.rectW,this.rectH);
        /*绘制文字*/
        this.ctx.beginPath();
        this.ctx.textAlign = 'left';
        this.ctx.textBaseline = 'top';
        this.ctx.font = '12px Microsoft YaHei';
        this.ctx.fillText(title,this.space + this.rectW + 10 , this.space + index * (this.rectH + 10));
    };
    PieChart.prototype.transformAngle = function (data) {
        /*返回的数据内容包含弧度的*/
        var total = 0;
        data.forEach(function (item, i) {
            total += item.num;
        });
        /*计算弧度 并且追加到当前的对象内容*/
        data.forEach(function (item, i) {
            var angle = item.num / total * Math.PI * 2;
            item.angle = angle;
        });
        return data;
    };
    PieChart.prototype.getRandomColor = function () {
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    };

    var data = [
        {
            title: '15-20岁',
            num: 6
        },
        {
            title: '20-25岁',
            num: 30
        },
        {
            title: '25-30岁',
            num: 10
        },
        {
            title: '30以上',
            num: 8
        }
    ];

    var pieChart = new PieChart();
    pieChart.init(data);

</script>
</body>
</html>

23.绘制图片

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<!--<img src="image/01.jpg" alt="">-->
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*1.加载图片到内存即可*/
    /*var img = document.createElement('img');
    img.src = 'image/01.jpg';*/
    /*创建对象*/
    var image = new Image();
    /*绑定加载完成事件*/
    image.onload = function () {
        /*实现图片绘制*/
        console.log(image);
        /*绘制图片的三种方式*/

        /*3参数*/
        /*图片对象*/
        /*绘制在画布上的坐标 x y*/
        //ctx.drawImage(image,100,100);


        /*5个参数*/
        /*图片对象*/
        /*绘制在画布上的坐标 x y*/
        /*是图片的大小  不是裁剪  是缩放*/
        //ctx.drawImage(image,100,100,100,100);


        /*9个参数*/
        /*图片对象*/
        /*图片上定位的坐标  x y */
        /*在图片上截取多大的区域  w h*/
        /*绘制在画布上的坐标 x y*/
        /*是图片的大小  不是裁剪  是缩放*/
        ctx.drawImage(image,400,400,400,400,200,200,100,100);

    };
    /*设置图片路径*/
    image.src = 'image/02.jpg';
</script>
</body>
</html>

24.帧动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<!--<img src="image/01.jpg" alt="">-->
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    var image = new Image();
    image.onload = function () {
        /*图片加载完成*/
        /*动态的去获取当前图片的尺寸*/
        var imageWidth = image.width;
        var imageHeight = image.height;
        /*计算出每一个小人物的尺寸*/
        var personWidth = imageWidth/4;
        var personHeight = imageHeight/4;
        /*位截取图片*/
        /*帧动画  在固定的时间间隔更换显示的图片  根据图片的索引*/
        var index = 0;

        /*绘制在画布的中心*/
        /*图片绘制的起始点*/
        var x0 = ctx.canvas.width /2 - personWidth / 2;
        var y0 = ctx.canvas.height /2 - personHeight / 2;

        ctx.drawImage(image,0,0,personWidth,personHeight,x0,y0,personWidth,personHeight);
        setInterval(function () {
            index ++;
            ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
            ctx.drawImage(image,index * personWidth,0,personWidth,personHeight,x0,y0,personWidth,personHeight);
            if(index >= 3){
                index = 0;
            }
        },1000);
    };
    image.src = 'image/04.png';
</script>
</body>
</html>

25.方向键控制的行走的小人

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>

    var Person = function (ctx) {
        /*绘制工具*/
        this.ctx = ctx || document.querySelector('canvas').getContext('2d');
        /*图片路径*/
        this.src = 'image/04.png';
        /*画布的大小*/
        this.canvasWidth = this.ctx.canvas.width;
        this.canvasHeight = this.ctx.canvas.height;

        /*行走相关参数*/
        this.stepSzie = 10;
        /* 0 前  1 左  2 右  3 后  和图片的行数包含的图片对应上*/
        this.direction = 0;
        /*x轴方向的偏移步数*/
        this.stepX = 0;
        /*y轴方向的偏移步数*/
        this.stepY = 0;

        /*初始化方法*/
        this.init();
    };

    Person.prototype.init = function () {
        var that = this;
        /*1.加载图片*/
        this.loadImage(function (image) {
            /*图片的大小*/
            that.imageWidth = image.width;
            that.imageHeight = image.height;
            /*人物的大小*/
            that.personWidth = that.imageWidth / 4;
            that.personHeight = that.imageHeight / 4;
            /*绘制图片的起点*/
            that.x0 = that.canvasWidth / 2 - that.personWidth / 2;
            that.y0 = that.canvasHeight / 2 - that.personHeight / 2;
            /*2.默认绘制在中心位置正面朝外*/
            that.ctx.drawImage(image,
                0,0,
                that.personWidth,that.personHeight,
                that.x0,that.y0,
                that.personWidth,that.personHeight);

            /*3.能通过方向键去控制人物行走*/
            that.index = 0;
            document.onkeydown = function (e) {
                if(e.keyCode == 40){
                    that.direction = 0;
                    that.stepY ++;
                    that.drawImage(image);
                    /*前*/
                }else if(e.keyCode == 37){
                    that.direction = 1;
                    that.stepX --;
                    that.drawImage(image);
                    /*左*/
                }else if(e.keyCode == 39){
                    that.direction = 2;
                    that.stepX ++;
                    that.drawImage(image);
                    /*右*/
                }else if(e.keyCode == 38){
                    that.direction = 3;
                    that.stepY --;
                    that.drawImage(image);
                    /*后*/
                }
            }
        });
    }
    /*加载图片*/
    Person.prototype.loadImage = function (callback) {
        var image = new Image();
        image.onload = function () {
            callback && callback(image);
        };
        image.src = this.src;
    };
    /*绘制图片*/
    Person.prototype.drawImage = function (image) {
        this.index ++;
        /*清除画布*/
        this.ctx.clearRect(0,0,this.canvasWidth,this.canvasHeight);
        /*绘图*/
        /*在精灵图上的定位 x  索引*/
        /*在精灵图上的定位 y  方向*/
        this.ctx.drawImage(image,
            this.index * this.personWidth,this.direction * this.personHeight,
            this.personWidth,this.personHeight,
            this.x0 + this.stepX * this.stepSzie ,this.y0 + this.stepY * this.stepSzie,
            this.personWidth,this.personHeight);
        /*如果索引超出了 变成0*/
        if(this.index >= 3){
            this.index = 0;
        }
    };
    new Person();
</script>
</body>
</html>

26.认识canvas的转换

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');
    //ctx.translate(100,100);
    //ctx.scale(0.5,1);
    //ctx.rotate(Math.PI/6);
    var startAngle = 0;
    ctx.translate(150,150);
    setInterval(function () {
        startAngle += Math.PI/180;
        ctx.rotate(startAngle);
        ctx.strokeRect(-50,-50,100,100);
    },500);
</script>
</body>
</html>