当前位置: 首页 > news >正文

Canvas进阶-2、可视化应用

前言

Canvas 可以用来创建各种 数据可视化 图表和图形,通过绘制不同的形状、线条和颜色来展示数据的特征和趋势。

数据可视化的基本原理是将数据转化为可视化的图形元素,以便人们更容易理解和分析数据。这涉及到以下几个方面:

  • 数据映射:将数据值映射到可视化元素的属性上,如位置、大小、颜色等。例如,将数值映射到柱状图的高度、折线图的点坐标或饼图的扇形角度。
  • 视觉编码:选择合适的可视化元素和属性来传达数据的特征。例如,使用不同的颜色来区分不同的数据类别,使用线条的粗细来表示数据的大小。
  • 布局和排版:合理安排可视化元素在画布上的位置,以提高可读性和美观度。例如,在柱状图中保持柱子之间的间距均匀,在折线图中使线条清晰可辨。
  • 交互性:为可视化添加交互功能,如鼠标悬停显示数据值、缩放和平移等,以增强用户对数据的探索和理解。

柱状图

  • 首先,确定数据和图表的尺寸。假设我们有一组数据表示不同类别的数量 Canvas 上绘制柱状图。
  • 然后,计算每个柱子的宽度和间距。如果有 n 个数据点,那么柱子的宽度可以是画布宽度除以数据点数量,再减去一些间距。
  • 接着,根据数据值计算每个柱子的高度。可以将数据值映射到画布的高度范围内,例如,数据值的最大值对应画布的高度,其他数据值按比例缩放。
  • 最后,使用 fillRect() 方法在 Canvas 上绘制每个柱子。可以为不同的柱子设置不同的颜色,以区分不同的数据类别。

请添加图片描述

以下是一个简单的用 Canvas 绘制柱状图的示例代码:

    // 可视化(柱状图)
    init() {
      var canvas = document.getElementById('myCanvas')
      var ctx = canvas.getContext('2d')
      var data = [100, 200, 150, 250, 220, 140]
      var width = canvas.width
      var height = canvas.height
      var barWidth = width / data.length - 10 // 柱子宽度,减去一些间距
      var maxDataValue = Math.max(...data)

      for (var i = 0; i < data.length; i++) {
        var barHeight = (data[i] / maxDataValue) * height - 20
        ctx.fillStyle = '#3e7bfa'
        ctx.fillRect(i * (barWidth + 10) + 5, height - barHeight, barWidth, barHeight)
      }
    },

饼图

  • 首先,确定数据和图表的尺寸。假设我们有一组数据表示不同类别的数量以及相对应的颜色。
  • 然后,计算canvas中心点绘制起始点,确定饼图半径,方便绘制圆形。
  • 接着,根据数据值计算每个数据占比。可以将数据值映射到画布的圆半径范围内,例如,数据值的最大值对应原型占比大小,其他数据值按比例缩放。
  • 最后,使用 arc() 方法在 Canvas 上绘制每个弧度边框。可以为不同的饼图区域设置不同的颜色,以区分不同的数据类别,用fill()填充完成饼图绘制。

请添加图片描述

以下是一个简单的用 Canvas 绘制柱状图的示例代码:

 // 可视化(饼图)
    init1() {
      var canvas = document.getElementById('myCanvas1')
      var ctx = canvas.getContext('2d')

      var data = [30, 40, 20, 10, 50, 10, 55]
      var colors = ['#FF5733', '#33FF57', '#3357FF', '#F333FF', '#33FFF5', '#F533FF', '#FF3357']
      var total = data.reduce((a, b) => a + b, 0)
      var startAngle = 0

      for (var i = 0; i < data.length; i++) {
        var endAngle = startAngle + (data[i] / total) * 2 * Math.PI
        ctx.fillStyle = colors[i] // 不同的颜色表示不同的数据部分
        ctx.beginPath()
        ctx.moveTo(canvas.width / 2, canvas.height / 2)
        ctx.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2 - 20, startAngle, endAngle)
        ctx.closePath()
        ctx.fill()

        ctx.lineWidth = 1 // 边框宽度
        ctx.strokeStyle = '#fff' // 边框颜色
        ctx.stroke() // 绘制边框

        startAngle = endAngle
      }
    },

折线图

  • 首先,确定数据和图表的尺寸。假设我们有一组数据表示不同类别的数量Canvas 上绘制折线图起始坐标轴。
  • 然后,计算各个数据点位,绘制数据点。
  • 接着,根据数据值计算每个数据值至下个数据点位置绘制连接线
  • 最后,使用stroke()完成连线

请添加图片描述

  // 可视化(折线图)
    init2() {
      var canvas = document.getElementById('myCanvas2')
      var ctx = canvas.getContext('2d')

      var data = [0, 40, 20, 10, 50, 10, 55]
      var padding = 40 // 图表周围的填充
      var xStep = (canvas.width - 2 * padding) / (data.length - 1) // x轴上每一步的大小
      var maxY = Math.max(...data) // 数据中的最大值,用于缩放y轴

      // 绘制坐标轴
      ctx.beginPath()
      ctx.moveTo(padding, 0)
      ctx.lineTo(padding, canvas.height - 20)
      ctx.lineTo(canvas.width - padding, canvas.height - 20)
      ctx.stroke()

      // 绘制数据点
      for (var i = 0; i < data.length; i++) {
        var x = padding + i * xStep
        var y = canvas.height - 20 - (data[i] / maxY) * (canvas.height - 2 * padding)

        // 绘制数据点
        ctx.beginPath()
        ctx.arc(x, y, 2, 0, 2 * Math.PI)
        ctx.fillStyle = '#3357FF'
        ctx.fill()

        // 绘制连接线
        if (i > 0) {
          ctx.beginPath()
          ctx.moveTo(prevX, prevY)
          ctx.lineTo(x, y)
          ctx.strokeStyle = '#3357FF'
          ctx.lineWidth = 2
          ctx.stroke()
        }

        // 更新上一个点的坐标
        var prevX = x
        var prevY = y
      }
    }

到此canvas进阶可视化应用学习结束,道阻且长,行则将至。与诸君共勉。 ⭐️

相关文章:

  • C++ Primer 库-IO类
  • 解锁C#自定义属性:从0到1的深度实践指南
  • Nginx中$http_host、$host、$proxy_host的区别
  • 2025 vue3面试题汇总,通俗易懂
  • 微信小程序客服消息接收不到微信的回调
  • RT-Thread+STM32L475VET6实现呼吸灯
  • 【PLL】应用:同步
  • EasyRTC:轻量化SDK赋能嵌入式设备,开启智能硬件音视频通讯新篇章
  • 用 Python 构建简易操作系统:探索与实践
  • 在 Mac ARM 架构 (Apple Silicon,例如 M1, M2, M3 芯片) 上使用官方安装包安装 MySQL
  • 贴片式TF卡——雷龙CS SD NAND实测体验
  • shell编程总结
  • Leetcode 位计算
  • 【算法】------区间问题(贪心)
  • 本地部署DeepSeek大模型
  • ORM框架详解:为什么不直接写SQL?
  • MYSQL的第一次
  • C++中const T为什么少见?它有什么用途?
  • 使用 Docker 部署 Flask 应用
  • 【Android】Android 悬浮窗开发 ( 动态权限请求 | 前台服务和通知 | 悬浮窗创建 )
  • 伊朗港口爆炸已造成25人死亡,灭火行动已近尾声
  • 最高法报告重申保护创新主体权益:加大侵权损害赔偿力度
  • 体育公益之约跨越山海,雪域高原果洛孕育足球梦
  • “五一”假期云南铁路预计发送旅客超330万人次
  • 我国首次实现地月距离尺度卫星激光测距
  • 专访倪军:人要有终身学习能力,一张文凭无法像以往支撑那么多年