如何实现可视化大屏——基于VChart

news2024/11/25 14:27:20

引言

在大屏产品中,可视化扮演着信息展示和传达、用户体验和互动、数据分析和决策支持、品牌展示和差异化、故事叙述和信息呈现等至关重要的角色。作为可视化图表的重要载体之一,大屏与智能BI产品不管是在产品设计,还是可视化设计的侧重点都有很大不同。

数据大屏产品

本文以 DataWind 数据大屏产品为例,为您揭示如何建设令人叹为观止的数据大屏。

场景化的主题色彩配置

为不同行业的数据大屏使用不同的颜色主题可以提高数据可视化效果、增强数据传达的意义、提高品牌识别度和满足用户需求,从而更好地呈现数据。

图表库能够支持场景化的主题色彩配置,这意味着用户可以根据不同的行业需求来选择不同的主题色彩,以更好地呈现数据。在不同的行业中,用户对于数据可视化的需求和期望可能会有所不同,因此场景化的主题色彩配置可以帮助用户更好地满足其特定的需求。

例如,在金融行业中,用户可能更注重数据的准确性和可靠性,因此金融行业的图表库可能需要提供更加严肃和专业的主题色彩配置;而在广告行业中,用户更注重图表的视觉效果和吸引力,因此广告行业的图表库可能需要提供更加鲜艳和夸张的主题色彩配置。

不同场景下的案例效果

分析场景

金融场景

文旅场景

实现揭秘

从上述案例中,我们可以注意到大屏可视化色彩设计有两个明显的特点:1、行业相关联的颜色主题;2、图元渐变着色。

颜色主题注册和切换

主题色板的构造基于于语义化及美观设计原则,即结合使用场景(保证大屏主题的场景表现力)、配色公式(保证图元在美观度、差异度等方面的配色效果和信息表达力)等逻辑进行设计。而针对大屏业务场景,我们沉淀出一套色彩方案,涵盖党建、金融、科技、文旅等行业,结合 VChart 主题注册和切换能力,做到开箱即用。

色板的具体信息开放出来供大家参考: https://github.com/VisActor/VChart/blob/develop/docs/assets/themes/colors.json

核心代码

const response = await fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json');
const colorTheme = await response.json();

// 注册主题
const theme = {};
for (const colorKey in colorTheme) {
  const colorName = colorTheme[colorKey].name;
  theme[colorName] = {
    colorScheme: {
      default: colorTheme[colorKey].colors
    }
  };
  VChart.ThemeManager.registerTheme(colorKey, theme[colorName]);
}

// 主题切换
  VChart.ThemeManager.setCurrentTheme('volcanoBlue');

在线示例:https://www.visactor.io/vchart/guide/tutorial_docs/Theme/Customize_Theme

渐变效果实现

纯色到渐变色的转换:纯色 => 图元填充渐变 + 图元描边边渐变。

示例地址: https://codesandbox.io/s/bar-gradient-ycr8m8

核心代码

const gradientCallback = (datum, ctx, type) => {
  return {
    gradient: "linear",
    x0: 0,
    y0: 0,
    x1: 0,
    y1: 1,
    stops: [
      {
        offset: 0,
        fillOpacity: 0,
        color: hexToRgba(ctx.seriesColor(datum.type), 1),
      },
      {
        offset: 1,
        fillOpacity: 1,
        color: hexToRgba(ctx.seriesColor(datum.type), 0),
      }
    ]
  };
};

// 以同样的方式在主题中注册和切换
const theme = {
    series: {
      bar: {
        bar: {
          style: {
            fill: (datum, ctx) => gradientCallback(datum, ctx, "fill"),
            stroke: (datum, ctx) => gradientCallback(datum, ctx, "stroke"),
            lineWidth: 2
          }
        }
      }
    }
}

VChart.ThemeManager.registerTheme(theme, 'gradient');
VChart.ThemeManager.setCurrentTheme('gradient');

渐变色详细说明参考:https://www.visactor.io/vchart/guide/tutorial_docs/Chart_Concepts/Series/Mark

最终效果

最终呈现的图表视觉效果不管是在提高吸引力,引流观众方面,还是在提升场景辨识度上都颇具成效。

在线Demo

在这里插入图片描述

示例地址:https://www.visactor.io/vchart/demo/theme/theme-style

更多主题教程见: https://www.visactor.io/vchart/guide/tutorial_docs/Theme/Theme

高度定制化的辅助装饰

在图表图元上做细微的装饰不仅可以提高视觉吸引力,增加图表的美感和吸引力,使得读者更愿意阅读和理解数据;更重要地,它还可以增加品牌识别度,帮助提高品牌识别度和专业感,使得数据大屏更具个性化和品牌化。

在图表中,图元负责实现数据到图形的映射,比如:数值的大小映射为矩形的高度,数值的类型映射为矩形的颜色等。而组件则负责数据的数值标记、图元的交互,比如:坐标轴以标签和刻度的形式标记某个高度对应的具体数值大小。

辅助装饰通常围绕着图元和组件展开,对图元的辅助装饰负责突出数据,对组件的装饰则负责个性化展示。

实现揭秘

图元装饰

由于装饰的位置强依赖于图元,在大屏侧无法准确定位并添加。通过VChart提供拓展Mark配置能力可以直接渲染出依附于既有图元的装饰图元,完美解决这一问题。

示例地址: https://codesandbox.io/s/line-with-halo-j54hv8


示例地址: https://codesandbox.io/s/line-with-halo-forked-xccmvq?file=/src/index.ts

核心代码

extensionMarks: [
    {
        name: 'markSymbol', // 拓展mark名称
        type: 'symbol', // 拓展mark类型
        from: {
            mark: 'symbol' // 当前图表的既有图元
        },
        spec: { // 拓展mark样式
            normal: {
                size: 10,
                fillOpacity: 0.1,
                fill: '#FFF',
                strokeOpacity: 0.5,
                stroke: {
                  gradient: 'conical', // // 锥形渐变,startAngle 代表起始弧度,endAngle 代表结束弧度,x, y 为坐标,取值范围 0 - 1
                  x: 0.5,
                  y: 0.5,
                  startAngle: 0,
                  endAngle: 6.283185307179586,
                  stops: [
                    { offset: 0, color: 'red' },      // 0% 处的颜色
                    { offset: 0.2, color: 'blue' },   // 20% 处的颜色
                    { offset: 0.4, color: 'orange' }, // 40% 处的颜色
                    { offset: 0.6, color: 'pink' },   // 60% 处的颜色
                    { offset: 0.8, color: 'green' },  // 80% 处的颜色
                    { offset: 1, color: 'purple' }    // 100% 处的颜色
                  ],
                }
            }
        }
    }
]

通过VChart 自定义渲染能力,还可以支持更多图元的纹理装饰。

组件装饰

为了标记出坐标轴的覆盖范围,我们需要增加轴辅助装饰。用VChart的轴tick回调函数可以实现这一效果。实现原理是,根据回调中的index判断tick是否是第一个或最后一个,如果是的话则设置为可见,不是的话则隐藏。

示例地址: https://codesandbox.io/s/axes-with-tick-sign-9n9jtf

核心代码

axes: [{
  // ...
    tick: {
      size: 4,
      normal: {
        strokeWidth: 2,
        stroke: tickStroke,
        visible: (...args) => {
          return args[0].index === 0 || args[0].index === 1
        },
      },
    }
}]

丰富灵活的动画效果

从数据场景而言,大屏通常用于展示实时数据、动态信息和即时反馈。通过动态效果,可以更好地呈现和展示这些数据的动态变化和趋势,使观众能够及时了解最新的数据情况。

从现实场景而言,大屏通常在公共场所或会议展览等场合使用,需要通过瞬间的视觉冲击来吸引人们的注意,使他们停下来观看。

在这里插入图片描述

不同图表的动画效果

设计动画的前提是明确动画的目标,不同的目标可能需要不同类型、频率和复杂程度的动画实现。显而易见,贯穿大屏数据可视化场景的动画目标如下:

  1. 强调数据重点和变换,通过设计合适的过渡和动作,可以使关键数据或信息在动画中突出显示。重点和关键变化的动画应该被放在视觉的焦点位置,使其更易于观察和理解。
  2. 吸引观众的注意,通过炫酷的动态效果可以迅速抓人眼球,但同时又需要控制速度和流畅度,以免影响观感。

根据目标在大屏中可以总结出数据更新动画、高亮动画和氛围动画,不同图元的动画效果各不相同。

柱图数据更新动画

示例地址: https://codesandbox.io/s/animation-bar-yypwgs?file=/src/index.ts

柱图氛围动画

示例地址: https://www.visactor.io/vchart/guide/tutorial_docs/extend/custom_animation

面积图数据更新动画

示例地址: https://codesandbox.io/s/animation-line-6nlpd4?file=/src/index.ts

除上述图表外,还有饼图、散点图等基本图表类型对应的动画,在此不一一赘述。

实现揭秘

VChart动画的实现依赖于VRender绘图引擎与VGrammar可视化语法。从实现分工而言,VRender提供任意图形的形变能力,VGrammar负责控制形变动画的流程,VChart进行上层封装并将配置以简洁易用的方式暴露给用户。

对于上述动画,VChart层的实现主要依赖于对VGrammar 动画语法的封装

柱图数据更新动画

示例地址:https://codesandbox.io/s/bar-update-animation-7jkd3j?file=/src/index.ts

核心代码

animationUpdate: {
     type: 'moveIn',
    duration: 500
  }

柱图数据高亮动画

在这里插入图片描述

示例地址: https://codesandbox.io/s/animation-highlight-j6d4f2?file=/src/index.ts

核心代码

animationNormal: {
    bar: [
      {
        loop: true,
        startTime: 100,
        oneByOne: 100,
        timeSlices: [
          {
            delay: 1000,
            effects: {
              channel: {
                fillOpacity: { to: 0.5 }
              },
              easing: "linear"
            },
            duration: 500
          },
          {
            effects: {
              channel: {
                fillOpacity: { to: 1 }
              },
              easing: "linear"
            },
            duration: 500
          }
        ]
      }
    ]
  }

柱图氛围动画

示例地址: https://www.visactor.io/vchart/guide/tutorial_docs/extend/custom_animation

核心代码

animationNormal: {
    bar: {
      loop: 100,
      duration: 1500,
      easing: 'quadIn',
      custom: VRender.StreamLight,
      customParameters: {
        attribute: {
          fillColor: '#bcdeff',
          opacity: 0.3,
          blur: 20,
          shadowColor: '#bcdeff',
          width: 160
        }
      }
    }
}

图表功能的可拓展性

除了提供多种预定义的图表类型,如柱状图、折线图、饼图等,我们还支持用户根据自己的数据特点和展示需求,创建和自定义各种类型的图表。使用VGranmar图形语法,你可以完成数据到图形的自定义映射,画布的自定义布局,动画效果和流程的自定义编排以及交互功能的自定义配置。

比如在大屏新增的排行榜组件并非VChart既有图表类型,而是通过图形语法VGrammar完全自定义实现。

实现揭秘

自定义映射

首先,要区分构成排行榜需要的图元类型,它们分别是矩形、标题、标签、装饰点。其次,需要确定图元的属性与数据的对应关系。

以如下数据为例:

const data = [
  { category: '吉林', value: 50 },
  { category: '内蒙古', value: 40 },
  { category: '河北', value: 30 },
  { category: '湖南', value: 30 },
  { category: '江西', value: 24 },
]

图元及数据与数据的映射关系:
在这里插入图片描述

映射结果

在线示例: https://codesandbox.io/s/vgrammar-ranking-list-hk8d43?file=/src/index.ts

核心代码

marks: [
      // 矩形
      {
        type: 'rect',
        from: { data: chartSpec.data[0].id },
        dependency: ['viewBox', 'xScale', 'yScale'],
        encode: {
          update: (datum, element, params) => {
            return {
              x: params.xScale.scale(dataMin), // 根据xScale做数据映射计算
              y: params.yScale.scale(datum['category']), // 根据yScale做数据映射计算
              width: params.xScale.scale(datum['value']), // 根据xScale做数据映射计算
              height: barWidth,
              // ...省略其他属性
            }
          },
        },
      },
      // 装饰点
      {
        type: 'symbol', 
        from: { data: chartSpec.data[0].id },
        dependency: ['viewBox', 'yScale', 'xScale'],
        encode: {
          update: (datum, element, params) => {
            return {
              x: params.xScale.scale(replaceNilDatum(datum, 'value', dataMin)),
              y: params.yScale.scale(datum['category']),
              // ...省略其他属性
            }
          },
        },
      },
      // 标题
      {
        type: 'text',
        from: { data: chartSpec.data[0].id },
        dependency: ['viewBox', 'yScale', 'xScale'],
        encode: {
          update: (datum, element, params) => {
            return {
              text: leftTextFormatMethod(datum['category']),
              x: params.xScale.scale(dataMin),
              y: params.yScale.scale(datum['category']),
              // ...省略其他属性
            }
          },
        },
      },
      // 标签
      {
        type: 'text',
        from: { data: chartSpec.data[0].id },
        dependency: ['viewBox', 'yScale'],
        encode: {
          update: (datum, element, params) => {
            return {
              text: rightTextFormatMethod(datum['value']),
              x: params.viewBox.x2,
              y: params.yScale.scale(datum['category']),
              // ...省略其他属性
            }
          },
        },
      },
    ],
自定义动画

排行榜组件的动画分为:入场动画、数据更新动画和退场动画。

入场动画时,所有元素的y属性从画布外,变为正常状态。

数据更新时,矩形图元的width属性从0变为正常状态。

退场动画时,所有元素的y属性从正常状态变为画布外。

在线示例: https://codesandbox.io/s/vgrammar-ranking-list-hk8d43?file=/src/index.ts

核心代码

// 以矩形图元为例

// 入场动画
enter: [
    {
      delay: 0,
      duration: durationTime,
      channel: {
        dy: {
          from: (datum, element, params) => {
            return params.viewBox.y2
          },
          to: 0,
        },
      },
    },
  ],
  
  // 更新动画
  enter: [
    {
      delay: 0,
      duration: durationTime,
      channel: {
        width: {
          from: 0,
          to: (datum, element, params) => {
            return params.xScale.scale(datum['value'])
          }
        }
      }
  ],
  
  // 退场动画
  exit: [
    {
      delay: 0,
      duration: durationTime,
      channel: {
        dy: {
          from: 0,
          to: (datum, element, params) => {
            return params.viewBox.y2
          },
        },
      },
    },
  ],
自定义交互

在VChart中,每个内置图表都有对应的图元点击事件用于数据联动。为了对齐这个能力,自定义图表排行榜也需要增加图元点击事件。依赖于vgrammr的事件注册能力,只需要在实例上调用addEventListener即可实现。

在这里插入图片描述

在线示例: https://codesandbox.io/s/vgrammar-ranking-list-hk8d43?file=/src/index.ts

核心代码

this.chartInstance.addEventListener('pointerdown', this.clickEventHandler)

结语

本文以 DataWind 数据大屏产品为例,详细介绍了实现一个优秀的数据大屏在技术和设计上要考虑的内容和实现方法,希望对您有所启发。

联系 与体验 方式

火山引擎DataWind: https://www.volcengine.com/product/datawind

VisActor 项目官网:https://www.visactor.io/

微信公众号:

今夜无月,期待你点亮星空,感谢Star:

github:https://github.com/VisActor/VChart

更多参考:

  1. 探索 VChart 图表库:简单、易用、强大、炫酷的可视化利器
  2. VTable——不只是高性能的多维数据分析表格,开源,免费,百万数据秒级渲染
  3. GPT遇到可视化——一句话生成图表、图片和视频
  4. 魔力之帧(上):前端图表库动画实现原理 - 掘金
  5. 火山引擎DataWind产品可视化能力揭秘
  6. VisActor——面向叙事的智能可视化解决方案
  7. 基于 VTable 的多维数据展示的原理与实践 - 掘金

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1206593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Animate 2024 for mac动画制作软件

Animate 2024是一款由Adobe公司开发的强大动画制作软件,它能帮助用户轻松制作出各种精美的动画作品。Animate 2024拥有强大而直观的设计工作流程,能够让用户自由地构建动画场景、绘制精美的图形,并轻松添加动态效果。无论是传统手绘风格还是骨…

Qt基础 QT QTextEdit自动滑动

目录 1.吐槽那些写文章不动脑子的人,不带脑子就别写,误人子弟 2.问题解决: 1.吐槽那些写文章不动脑子的人,不带脑子就别写,误人子弟 最近公司在做一个提词项目,本来对这里功能难易感觉属于一般的,谁知道碰到一个很简单问题,搞了半天,先喷一下百度浏览器 不知道是…

上机实验四 图的最小生成树算法设计 西安石油大学数据结构

实验名称:图的最小生成树算法设计 (1)实验目的: 掌握最小生成树算法,利用kruskal算法求解最小生成树。 (2)主要内容: 利用kruskal算法求一个图的最小生成树,设计Krus…

Stable Diffusion 是否使用 GPU?

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 3D数字孪生场景编辑器 Stable Diffusion 已迅速成为最流行的生成式 AI 工具之一,用于通过文本到图像扩散模型创建图像。但是,它需…

软件外包开发的需求整理

提高软件需求描述的准确度是确保项目成功的关键一步。以下是一些建议,可以帮助提高需求描述的准确度,希望对大家有所帮助。 1.深入了解业务: 在开始编写需求之前,充分了解业务流程和业务目标。与业务团队密切合作,确保…

数字化转型时代,商业智能BI到底是什么?

据国际数据公司(IDC)预测,2025年时中国产生的数据量预计将达48.6ZB,在全球中的比例为27.8%。商业智能BI这一专为企业提供服务的数据类解决方案,仅2021年上半年在中国商业智能BI市场规模就达到了3.2亿美元,商…

idea生成代码(一):实现java语言的增删改查功能(基于EasyCode插件)支持自定义模板【非常简单】

idea生成代码(一):实现java语言的增删改查功能(基于EasyCode插件)支持自定义模板【非常简单】 idea生成代码(二):实现java语言的增删改查功能(基于mybatis-plus代码生成器…

(七)Spring源码解析:Spring事务

对于事务来说,是我们平时在基于业务逻辑编码过程中不可或缺的一部分,它对于保证业务及数据逻辑原子性立下了汗马功劳。那么,我们基于Spring的声明式事务,可以方便我们对事务逻辑代码进行编写,那么在开篇的第一部分&…

Banana Pi BPI-M5 Boot Log 导出说明

准备: Preparation: 1、 一块bpi的开发板,一根ttl的串口线,以及一张烧录好镜像的sd/tf卡(烧录到eMMC也行)。 1. A BPI development board, a TTL serial port cable, and an SD/TF card with a burned image (it ca…

基于ssm的学生档案管理系统(有报告)。Javaee项目,ssm项目。

演示视频: 基于ssm的学生档案管理系统(有报告)。Javaee项目,ssm项目。 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 项目介绍&#xff…

海外ASO优化之谷歌商店的评论优化

应用商店中的评分和评论,显示我们的应用程序的受欢迎程度以及用户对该应用程序的看法。评分和评论是以前或者是现在的用户分享的经验和公开的反馈。 1、提高应用评分评论。 高评分的应用可以从应用商店内的搜索流量中获得更多的点击量,通过推荐和推荐获…

基于单片机智能浇花系统仿真设计

**单片机设计介绍, 基于单片机智能浇花系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的智能浇花系统可以实现自动化浇水、测土湿度和温度等功能,以下是一个基本的仿真设计步骤&am…

CRM销售管理软件哪个好,该如何选择?(一)

销售团队对于任何一家企业来说都是重中之重,因此我们说一款可以辅助销售人员维护好客户的工具是企业发展的刚需。那么CRM销售管理软件哪个好,该如何选择,从从哪里方面去入手?来看看这两点吧: 功能方面 完整的功能可以…

ARPG----C++学习记录05 Section10 碰撞,重叠事件

collision碰撞 Query only 仅查询。包括请求,扫描和重叠,扫描两个物体知否存在重叠Physics Only 仅物理。重力,反弹等物理计算都开启 按下“~”输入show collision可以查看碰撞 给石块添加碰撞,Query可以阻挡人物过去,…

提升自动化测试:Apifox 产品更新全解析!

Apifox 新版本上线啦! 看看本次版本更新主要涵盖的重点内容,有没有你所关注的功能特性: 自动化测试 新增 ForEach 循环组件数据库连接支持 MongoDB前/后置操作模块能力升级 支持使用 pm.executeAsync 异步执行外部程序支持自定义外部程序的…

【原创分享】DC-DC电源PCB设计要点

DC-DC电源是一种用于将直流(DC)电压转换为不同电压级别的电源。它通过内部的电路和拓扑结构,将输入电压调整为所需的输出电压,并提供稳定的电力供应。 DC-DC电源通常包括输入端子、输出端子、开关元件(如开关管&#…

人工智能基础_机器学习027_L2正则化_岭回归_非稀疏性_原理解读_公式推导---人工智能工作笔记0067

然后我们再来看一下岭回归,也就是第二范数对吧, 他的公式,平方以后,加和然后开平方.L2的公式是 可以看到L2公式,也是有个阿尔法,惩罚项对吧. 可以看到因为L2带有平方,所以他的图形是个圆形 我们可以把L2范数,进行画出来看看 这里我们先看L2的公式,这里我们让 这个公式写成1 …

第四章mlp

生成数据集 读取数据集 data.TensorDataset(*data_arrays)mlp训练 loss nn.CrossEntropyLoss(reductionnone)我要掌握所有人脖颈上的绳 权重衰减 简单概述就是在标准意义的loss函数(label值和计算值的差别)中再加上一个 惩罚项,为什么要…

Java实现深拷贝的方式

文章目录 1. 实现 Cloneable 接口并重写 clone() 方法2. 使用序列化和反序列化实现深拷贝3. 第三方工具(1) Apache Commons BeanUtils 库(2) Apache Commons Lang 库(3) Spring Framework(4) Kryo 序列化库(5) FST 序列化库 1. 实现 Cloneable 接口并重写 clone() 方法 在 Jav…