数据可视化-Canvas

164 阅读5分钟

一、邂逅Canvas

1. 什么是Canvas

  • HTML5新增元素。
  • Canvas提供了非常多的JavaScript绘图API,与canvas元素可以绘制各种2D图形。

2. Canvas的应用场景

  • 可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。

3. Canvas优点

  • Canvas提供的功能更原始,适合像素处理,动态渲染和数据量大的绘制,如:图片编辑、热力图、炫光尾迹特效等。
  • Canvas非常适合图像密集型的游戏开发,适合频繁重绘许多的对象。
  • Canvas能够以.png或.jpg格式保存结果图像,适合对图片进行像素级的处理。

4. Canvas缺点

  • 在移动端可能会因为Canvas数量多,而导致内存占用超出了手机的承受能力,导致浏览器崩溃。
  • Canvas绘图只能通过JavaScript脚本操作。
  • Canvas是由一个个像素点构成的图形,放大会使图形变得颗粒状和像素化,导致模糊。

5. Canvas的使用

  • canvas标签只有两个属性:width和height。当没有设置宽度和高度时,canvas会初始化宽为300px和高为150px。
  • 测试canvas.getContext()方法的存在,可以检测浏览器是否支持Canvas。

二、Canvas绘图

1. Canvas网格和坐标空间

  • canvas元素默认被网格所覆盖。
  • 通常来说网格的一个单元相当于canvas元素中的一像素。
  • 该网格的原点位于坐标(0,0)的左上角。所有元素都相对于该原点位置。
  • 网格也可以理解为坐标空间,坐标原点位于canvas元素的左上角,被称为初始坐标系。

2. 绘制形状

  • 绘制矩形
    • rect(x, y, width, height):单纯的画出一个矩形框,调用stroke() 或 fill()后才会真正作用于画布。
    • fillRect(x, y, width, height):绘制一个填充的矩形。
    • strokeRect(x, y, width, height):绘制一个矩形的边框。
    • clearRect(x, y, width, height):清除指定矩形区域,让清除部分完全透明。
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        body {
          margin: 0;
          padding: 0;
        }
        canvas {
          background-color: rgba(255, 0, 0, 0.1);
        }
      </style>
    </head>
    <body>
      <canvas id="tutorial" width="300" height="300">
        你的浏览器不兼容Canvas,请升级您的浏览器!
      </canvas>
    
      <script>
        window.onload = function() {
          let canvasEl = document.getElementById("tutorial")
          if (!canvasEl.getContext) {
            return
          }
          let ctx = canvasEl.getContext("2d")
          // 1. 绘制了一个填充的矩形
          ctx.fillRect(0, 100, 100, 50)
          // 2. 绘制一个边框的矩形
          ctx.strokeRect(0, 200, 100, 50)
          // 3. 清除指定区域的矩形
          ctx.clearRect(0, 0, 100, 50)
        }
      </script>
    </body>
    </html>
    
  • 绘制路径
    • 使用路径绘制图形的步骤
      • 首先需要创建路径起始点(beginPath);
      • 然后使用画图命令去画路径(arc、lineTo);
      • 之后把路径闭合(closePath,不是必须);
      • 一旦路径生成,就能通过描边(stroke)或填充路径区域(fill)来渲染图形。
    • 绘制直线
      • moveTo:移动画笔
      • lineTo:绘制直线
      window.onload = function() {
        let canvasEl = document.getElementById("tutorial")
        if (!canvasEl.getContext) {
          return
        }
        let ctx = canvasEl.getContext("2d")
      
        ctx.lineWidth = 10
        // 1. 创建一个新的路径
        ctx.beginPath()
        // 2. 使用的绘图的命名(ctx对象中的属性和API)
        ctx.moveTo(10, 10)
        ctx.lineTo(100, 10)
        // 3. 闭合路径
        // ctx.closePath() // 不是必须的
        // 4. 描边或填充
        ctx.stroke() // 绘制线条只能用stroke填充,不能用fill
      }
      
    • 绘制三角形
      window.onload = function() {
        let canvasEl = document.getElementById("tutorial")
        if (!canvasEl.getContext) {
          return
        }
        let ctx = canvasEl.getContext("2d")
      
        ctx.beginPath()
        ctx.moveTo(50, 0)
        ctx.lineTo(100, 50)
        ctx.lineTo(50, 100)
        ctx.closePath()
        ctx.stroke()
      
        ctx.beginPath()
        ctx.moveTo(150, 0)
        ctx.lineTo(200, 50)
        ctx.lineTo(150, 100)
        ctx.fill() // 它会自动闭合路径
      }
      
    • 绘制圆
      • arc(x, y, radius, startAngle, endAngle, anticlockwise)
      • x、y:为绘制圆弧所在圆上的圆心坐标。
      • radius:为圆弧半径。
      • startAngle、endAngle:该参数用弧度定义了开始以及结束的弧度。这些都是以x轴为基准.
      • anticlockwise:为一个布尔值。为 true ,是逆时针方向,为false,是顺时针方向,默认为false。
      window.onload = function() {
        let canvasEl = document.getElementById("tutorial")
        if (!canvasEl.getContext) {
          return
        }
        let ctx = canvasEl.getContext("2d")
      
        ctx.beginPath()
        // x, y, R, startRad, endRad, 顺时针方向
        ctx.arc(50, 50, 25, 0, Math.PI * 2, false)
        ctx.stroke()
      }
      
    • 绘制圆弧
      window.onload = function() {
        let canvasEl = document.getElementById("tutorial")
        if (!canvasEl.getContext) {
          return
        }
        let ctx = canvasEl.getContext("2d")
      
        ctx.beginPath()
        ctx.arc(150, 150, 25, 0, Math.PI)
        ctx.stroke()
      }
      
    • 绘制矩形
      • rect(x, y, width, height)
      window.onload = function() {
        let canvasEl = document.getElementById("tutorial")
        if (!canvasEl.getContext) {
          return
        }
        let ctx = canvasEl.getContext("2d")
      
        // 1. 创建一个路径
        ctx.beginPath()
        // 2. 绘图指令
        ctx.moveTo(0, 0)
        ctx.rect(100, 100, 100, 50)
        // 3. 闭合路径
        ctx.closePath()
        // 4. 填充或描边
        ctx.fill()
      }
      
  • 样式属性
    • 色彩 Colors
      • fillStyle = color:设置图形的填充颜色,需在fill()函数前调用。
      • strokeStyle = color:设置图形轮廓颜色,需在stroke()。
        一旦设置了fillStyle或者strokeStyle的值,那么这个新值就会成为新绘制的图形的默认值。
    • 透明度 Transparency
      • globalAlpha
      • rgba:fillStyle和strokeStyle属性结合rgba
    • 线型 Line styles
      • lineWidth = value:设置线条宽度。
      • lineCap = type:设置线条末端样式。
        • butt —— 截断,默认是butt
        • round —— 圆形
        • square —— 正方形
      • lineJoin = type:设定线条与线条间接合处的样式。
        • round —— 圆形
        • bevel —— 斜角
        • miter —— 斜槽规,默认是miter
      • setLineDash() —— 设置虚线样式
      • lineDashoffset —— 虚线偏移
  • 绘制文本
    • fillText(text, x, y [, maxWdith])
    • strokeText(text, x, y [, maxWdith])
    • 有样式的文本(需在绘制文本前调用)
      • font = value:当前绘制文本的样式。默认的字体是 10px sans-serif。
      • textAlign = value:文本对齐选项,可选的值包括start,end,left,right和center。默认值是start。
      • textBaseline = value:基线对齐选项。可选的值包括top,hanging,middle,alphabetic,ideographic,bottom。默认值是alphabetic
  • 绘制图片
    • drawImage(image, x, y, width, height)

三、Canvas状态的保存和恢复

  • save():保存画布(canvas)的所有绘画状态
  • restore():恢复画布(canvas)的所有绘画状态
    绘画状态存储在栈中

四、Canvas变换坐标系统

  • Canvas和CSS3一样支持形变,可以将坐标原点移动到另一点,形变可以对网络进行旋转和缩放。

1. translate

  • translate(x, y)

2. rotate

  • rotate(deg)

3. scale

  • scale(x, y)

4. transform

  • transform(a, b, c, d, e, f)

五、Canvas动画

1. 认识canvas动画

  • canvas可能最大的限制就是图像一旦绘制了,就一直保持那样了。
  • 如需要执行动画,不得不对画布上所有图形进行一帧一帧的重绘。
  • 为了实现动画,Canvas有三种方法可以定期执行指定函数实现定时执行重绘的方法:setInterval、setTimeout和requestAnimationFrame。

2. 动画使用的基本步骤

  • 用clearRect方法清空canvas;
  • 保存canvas状态;
  • 绘制动画图形;
  • 恢复canvas状态。

3. 操控动画

  • setInterval
  • setTimeout
  • requestAnimationFrame
    • 告诉浏览器:你希望执行一个动画,并且要求浏览器在下次重绘之前调用该函数的回调函数来更新动画。
    • 该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
    • 若想在浏览器下次重绘之前继续更新下一帧动画,那么在回调函数自身必须再次调用requestAnimationFrame()。
    • 通常每秒钟回调函数执行60次左右,也有可能会被降低。