Canvas简介
  1. canvas 最早由Apple引入WebKit,用于Mac OS X 的 Dashboard,后来又在Safari和Google Chrome被实现。
  2. 基于 Gecko 1.8的浏览器,比如 Firefox 1.5,同样支持这个元素
  3. canvas元素是WhatWG Web applications 1.0规范的一部分,也包含于HTML 5中
体验Canvas
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #canvas{
            border: 1px solid #ccc;
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="600" height="400"></canvas>
<script>
    // 1. 获取画布
    let canvas = document.querySelector('#canvas');
    // 2. 获取上下文 绘制的工具箱
    let ctx = canvas.getContext('2d');
    // 3. 移动画笔
    ctx.moveTo(100, 100);
    // 4. 绘制直线
    ctx.lineTo(300, 100);
    // 5. 描边
    ctx.stroke();
</script>
</body>
</html>

运行结果:
HTML:canvas简述_2d

什么是Canvas?

  1. HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。
  2. 画布是一个矩形区域,我们可以控制其每一像素。
  3. canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

创建Canvas元素?

  1. 向 HTML5 页面添加 canvas 元素
  2. 规定元素的 id、宽度和高度
  3. 代码示例
    <canvas id="myCanvas" width="200" height="100"></canvas>
    

Canvas坐标系?

HTML:canvas简述_2d_02

JavaScript绘制?

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

Canvas的基本使用?

  1. 路径的绘制
    1)描边 stroke()
    2)填充 fill()
    3)图示

  2. 开启新的路径
    多场景绘制的之后,一定要开启新的路径:beginPath()

  3. 闭合路径
    手动闭合
    程序闭合 closePath()

绘制坐标系
  1. 不同场景绘制开启新的路径beginPath()
  2. 绘制其实就是一个点到一个点,最后填充或描边
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        #canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
    // 1. 获取画布
    let canvas = document.querySelector('#canvas');

    // 2. 获取上下文 绘制的工具箱
    let ctx = canvas.getContext('2d');

    // 3.变量
    let space = 20, arrowSize = 10;
    let cWidth = ctx.canvas.width;
    let cHeight = ctx.canvas.height;
    // console.log(cWidth, cHeight);
    // 起始点
    let x0 = space, y0 = cHeight - space;

    // 4. 绘制x轴
    ctx.beginPath();
    ctx.moveTo(x0, y0);
    ctx.lineTo(cWidth - space, y0);
    // 箭头
    ctx.lineTo(cWidth - space - arrowSize, y0 + arrowSize / 2);
    ctx.lineTo(cWidth - space - arrowSize, y0 - arrowSize / 2);
    ctx.lineTo(cWidth - space, y0);
    // 填充
    ctx.fill();
    // 描边
    ctx.stroke();

    // 5. 绘制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>

运行结果:
HTML:canvas简述_html_03

绘制矩形
  1. rect(x,y,w,h) 没有独立路径
  2. strokeRect(x,y,w,h) 有独立路径,不影响别的绘制
  3. fillRect(x,y,w,h) 有独立路径,不影响别的绘制
  4. learRect(x,y,w,h) 擦除矩形区域
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
    // 1. 获取画布
    let canvas = document.querySelector('#canvas');

    // 2. 获取上下文 绘制的工具箱
    let ctx = canvas.getContext('2d');

    // 3. 绘制矩形
    /*
    ctx.rect(100, 100, 200, 100);
    ctx.fillStyle = 'blue';
    ctx.stroke();
    ctx.fill();
    */

    // 4. 其它方式
    // ctx.fillRect(100, 100, 200, 100);
    ctx.strokeRect(100, 100, 200, 100);

    // 5. 清空矩形
    // ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

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

运行结果:
HTML:canvas简述_C_04

绘制渐变色矩形
  1. createLinearGradient(x,y,x1,y1)渐变方案
  2. addColorStop()增加中途渐变色
  3. ctx.fillStyle = linearGradient 将渐变方案应用在填充上
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #box{
            width: 400px;
            height: 200px;
            background: linear-gradient(to right, yellow, purple);
        }
        #canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
   <div id="box"></div>
   <canvas id="canvas" width="600" height="400"></canvas>
<script>
    // 1. 获取画布
    let canvas = document.querySelector('#canvas');
    // 2. 获取上下文 绘制的工具箱
    let ctx = canvas.getContext('2d');
    // 3. 渐变方案
    let linearGradient = ctx.createLinearGradient(100, 100, 400, 400);
    linearGradient.addColorStop(0, 'red');
    linearGradient.addColorStop(0.5, 'purple');
    linearGradient.addColorStop(1, 'yellow');
    // 4. 绘制
    ctx.fillStyle = linearGradient;
    ctx.fillRect(100, 100, 400, 400);

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

运行结果:
HTML:canvas简述_html_05

圆弧绘制

arc() context.arc(x,y,r,sAngle,eAngle,counterclockwise);

  • x 圆心横坐标
  • y 圆心纵坐标
  • r 半径
  • startAngle 开始角度
  • endAngle 结束角度
  • anticlockwise 是否逆时针方向绘制(默认false表示顺时针;true表示逆时针)
  • 角度以π为单位,90°为0.5π
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
   <canvas id="canvas" width="600" height="400"></canvas>
<script>
    // 1. 获取画布
    let canvas = document.querySelector('#canvas');
    // 2. 获取上下文 绘制的工具箱
    let ctx = canvas.getContext('2d');

    /*
    圆弧
    */
    let w = ctx.canvas.width;
    let h = ctx.canvas.height;
    ctx.arc(w/2, h/2, 100, 0, 2 * Math.PI, false);
    ctx.stroke();
</script>
</body>
</html>

HTML:canvas简述_C_06

绘制一个圆等分颜色随机
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
    // 1. 获取画布
    let canvas = document.querySelector('#canvas');
    // 2. 获取上下文 绘制的工具箱
    let ctx = canvas.getContext('2d');
    let w = ctx.canvas.width;
    let h = ctx.canvas.height;

    // 3. 分成多少份
    let num = 50;
    // 4. 一份多少弧度
    let angle = 2 * Math.PI / num;

    // 5. 圆点
    let x0 = w / 2;
    let y0 = h / 2;

    // 6. 获取随机颜色
    let getRandomColor = () => {
        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})`;
    };

    // 7. 绘制
    for (let i = 0; i < num; i++) {
       // 7.1 起始角度
        let startAngle = i * angle;
       // 7.2 结束角度
        let endAngle = (i+1) * angle;
        ctx.beginPath();
        ctx.moveTo(x0, y0);
        ctx.arc(x0, y0, 180, startAngle, endAngle, false);
        // 随机颜色
        ctx.fillStyle = getRandomColor();
        ctx.fill();
    }
</script>
</body>
</html>

运行结果:
HTML:canvas简述_html_07

绘制图片

drawImage()

  1. 三个参数drawImage(img,x,y)
    img 图片对象、canvas对象、video对象
    x,y 图片绘制的左上角
  2. 五个参数drawImage(img,x,y,w,h)
    img 图片对象、canvas对象、video对象
    x,y 图片绘制的左上角
    w,h 图片绘制尺寸设置(图片缩放,不是截取)
  3. 九个参数drawImage(img,x,y,w,h,x1,y1,w1,h1)
    img 图片对象、canvas对象、video对象
    x,y,w,h 图片中的一个矩形区域
    x1,y1,w1,h1 画布中的一个矩形区域
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
<img src="img/s1.jpg" alt="">
<canvas id="canvas" width="600" height="400"></canvas>
<script>
    // 1. 获取画布
    let canvas = document.querySelector('#canvas');
    // 2. 获取上下文 绘制的工具箱
    let ctx = canvas.getContext('2d');

    // 3. 内存中创建图片标签
    /*let img = document.createElement('img');
    img.src = 'img/s1.jpg';*/

    let image = new Image();
    image.src = 'img/s1.jpg';
    image.addEventListener('load', ()=>{
        // console.log(image);
        // 3.1 绘制图片到画布 3个参数
        // ctx.drawImage(image, 100, 100);

        // 5个参数
        /*
          图片对象
          起始点 x, y
          绘制图片的宽度和高度 不是裁剪而是缩放
        */
        // ctx.drawImage(image, 100, 100, 300, 300);

        // 9个参数
        /*
          image: CanvasImageSource,

          sx: number, 截取起始点
          sy: number, 截取起始点
          sw: number, 截取图片的多大区域 width
          sh: number, 截取图片的多大区域 height

          dx: number, 绘制起始点
          dy: number, 绘制起始点
          dw: number, 绘制图片的宽度和高度 不是裁剪而是缩放
          dh: number  绘制图片的宽度和高度 不是裁剪而是缩放
        */
         ctx.drawImage(image, 100, 100, 600, 800, 100, 100, 200, 200);
    });


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

运行结果:
HTML:canvas简述_C_08

绘制文字
  1. strokeText()、fillText()两种方式绘制
  2. textAlign 设置水平对齐方式
  3. textBaseline设置基准对齐方式
  4. font 设置字体
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="800" height="600"></canvas>
<script>
    // 1. 获取画布
    let canvas = document.querySelector('#canvas');
    // 2. 获取上下文 绘制的工具箱
    let ctx = canvas.getContext('2d');

    // 3. 文字
    let str = '喜欢IT, 就来撩课!';

    // 4. 画布的尺寸
    let w = ctx.canvas.width;
    let h = ctx.canvas.height;

    // 5. 画十字架在画布的最中间
    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 = '#ccc';
    ctx.stroke();

    // 6. 绘制文本
    ctx.beginPath();
    let x0 = w/2;
    let y0 = h/2;
    ctx.strokeStyle = 'purple';
    /*
      text: string,
      x: number,
      y: number,
      maxWidth?: number
    */
    // 设置字体
    ctx.font = '60px Microsoft YaHei';
    // 设置水平居中 left right
    ctx.textAlign = 'center'; // "start" | "end" | "left" | "right" | "center"
    // 设置垂直居中
    ctx.textBaseline = 'middle'; // "top" | "hanging" | "middle" | "alphabetic" | "ideographic" | "bottom"
    // ctx.strokeText(str, x0, y0);
    ctx.fillStyle = 'blue';
    ctx.fillText(str, x0, y0);
</script>
</body>
</html>

运行结果:
HTML:canvas简述_2d_09

图片的旋转

canvas中图片的旋转是基于上下文的,也就是说旋转的话是整体旋转。
因此,在旋转的时候,要重新规划上下文。
用到两个方法。
save()和restore()。

save()

  1. 用来保存Canvas的状态。
  2. save之后,可以调用Canvas的平移、缩放、旋转、错切、裁剪等操作。

restore()

  1. 用来恢复Canvas之前保存的状态。
  2. 防止save后对Canvas执行的操作对后续的绘制有影响。

使用理由

  1. 在Canvas中,特定元素的旋转平移等操作实际上是对整个画布进行了操作
  2. 如果不对canvas进行save以及restore操作,那么每一次糊涂都会在上一次的基础上进行操作,最后导致错位。
  3. 比如如果相对于起始点每次30°递增旋转:30、60、90.如果不使用save以及restore,就会变成30、90、150.每一次在前一次的基础上进行了旋转。
  4. save是入栈,restore是出栈。
translate:移动canvas坐标系位置
<script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    ctx.lineWidth = 10;
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(0,20);
    ctx.stroke();
</script>

HTML:canvas简述_html_10

<script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    ctx.translate(canvas.width /2,canvas.height /2);
    ctx.lineWidth = 10;
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(0,20);
    ctx.stroke();
</script>

HTML:canvas简述_2d_11

rotate()旋转
<script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    ctx.rotate(-90 / 180 * Math.PI);
    ctx.lineWidth = 10;
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(0,20);
    ctx.stroke();
</script>

HTML:canvas简述_C_12