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

引言

在大屏产品中,可视化扮演着信息展示和传达、用户体验和互动、数据分析和决策支持、品牌展示和差异化、故事叙述和信息呈现等至关重要的角色。作为可视化图表的重要载体之一,大屏与智能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 的多维数据展示的原理与实践 - 掘金

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv8-seg 分割代码详解(二)Train

前言 本文主要以源码注释为主,可以了解到从模型的输出到损失计算这个过程每个步骤的具体实现方法。 流程梳理 一、选取有效 anchor   以 640x640 的输入为例,模型最终有8400个 anchor,每个 anchor 都有其对应的检测输出(4n&am…

管理类联考——数学——汇总篇——知识点突破——代数——函数、方程——记忆——一元二次方程

——一元二次方程——【核心为“根”:求根,根的多少/判别式,根与系数,根的正负,根的范围/区间】 一元二次方程:只含一个未知数,且未知数的最高次数是2的方程,“元”是指方程中所含未…

出入库管理系统vue2前端开发服务器地址配置

【精选】vue.config.js 的完整配置(超详细)_vue.config.js配置_web学生网页设计的博客-CSDN博客 本项目需要修改两处: 1、vue开发服务器地址:config\index.js use strict // Template version: 1.3.1 // see http://vuejs-templa…

2012年08月16日 Go生态洞察:优雅的代码组织之道

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

开源会议通知H5页面邀请函制作源码系统+自动翻页 带完整的搭建教程

现如今,线上活动越来越频繁,而会议邀请函也成为了活动组织者不可或缺的工具。然而,传统的邮件、短信等方式发送邀请函已经无法满足现代人的需求。因此,开发一款现代化的、功能丰富的会议邀请函系统势在必行。下面源码小编将来给大…

全网最全synchronized锁升级过程

一、前言 在面试题中经常会有这么一道面试题,谈一下synchronized锁升级过程? 之前背了一些,很多文章也说了,到底怎么什么条件才会触发升级,一直不太明白。 实践是检验真理的唯一标准,今天就和大家一起实…

kafka+ubuntu20.04+docker配置

记录一次配置过程 安装docker 参加下面链接的第一部分 Ubuntu20.04使用docker安装kafka服务-CSDN博客 安装zookeeper docker run -d --name zookeeper -p 2181:2181 -v /etc/localtime:/etc/localtime wurstmeister/zookeeper安装kafka服务 docker run -d --name kafka …

react路由安装配置react-router-dom/‘Switch‘ is not defined报错解决

1.安装 npm install --save react-router-dom安装完成 新建两个页面并导出 app.js import Nav from ./components/Nav import Home from ./components/Home import { Link, Route, Switch } from react-router-domfunction App() {return (<div><div><p>&…

【2021集创赛】Arm杯一等奖作品—基于 Cortex-M3 内核 SOC 的动目标检测与跟踪系统

本作品介绍参与极术社区的有奖征集|秀出你的集创赛作品风采,免费电子产品等你拿~ 团队介绍 参赛单位&#xff1a;北京理工大学 队伍名称&#xff1a;飞虎队 指导老师&#xff1a;李彬 参赛杯赛&#xff1a;Arm杯 参赛人员&#xff1a;余裕鑫 胡涵谦 刘鹏昀 获奖情况&#xff1…

使用责任链模式实现登录风险控制

责任链模式 责任链模式是是设计模式中的一种行为型模式。该模式下&#xff0c;多个对象通过next属性进行关系关联&#xff0c;从而形成一个对象执行链表。当发起执行请求时&#xff0c;会从首个节点对象开始向后依次执行&#xff0c;如果一个对象不能处理该请求或者完成了请求…

侧击雷如何检测预防

侧击雷是一种雷击的形式&#xff0c;指的是雷电从建筑物的侧面打来的直接雷击。侧击雷对高层建筑物的防雷保护提出了更高的要求&#xff0c;因为一般的避雷带或避雷针不能完全保护住建筑物的侧面。侧击雷可能会对建筑物的结构、设备和人员造成严重的损害&#xff0c;甚至引发火…

酷开科技丨酷开系统,带你进入惊喜不断的影视世界!

随着科技的迅速发展&#xff0c;智能电视已经成为家庭娱乐的重要组成部分。而要说到智能电视&#xff0c;就不得不提到酷开系统&#xff0c;作为一款智能电视操作系统&#xff0c;酷开系统以其独特的功能和出色的使用体验&#xff0c;让观众们看到了到惊喜不断的影视世界。 如…

CRM系统:助力数据服务企业,打造核心竞争力

近年来&#xff0c;数据服务企业开始走入大众视野。作为企业管理应用热门选手——CRM客户管理系统&#xff0c;可以助力企业实时数据应用先行者&#xff0c;提升业务转化与协同效率&#xff0c;进一步打造核心竞争力。下面我们说说&#xff0c;CRM系统对数据服务企业的作用。 …

Stable Diffusion 是否使用 GPU?

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

使用 Stable Diffusion Img2Img 生成、放大、模糊和增强

在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 3D数字孪生场景编辑器 Stable Diffusion 2022.1 Img5Img 于 2 年发布&#xff0c;是一款革命性的深度学习模型&#xff0c;正在重新定义和推动照片级真实…

云原生Kubernetes系列 | 通过容器互联搭建wordpress博客系统

云原生Kubernetes系列 | 通过容器互联搭建wordpress博客系统 通过容器互联搭建一个wordpress博客系统。wordpress系统是需要连接到数据库上的&#xff0c;所以wordpress和mysql的镜像都是需要的。wordpress在创建过程中需要指定一些参数。创建mysql容器时需要把mysql的数据保存…

linux系统下文件操作常用的命令

一、是什么 Linux 是一个开源的操作系统&#xff08;OS&#xff09;&#xff0c;是一系列Linux内核基础上开发的操作系统的总称&#xff08;常见的有Ubuntu、centos&#xff09; 系统通常会包含以下4个主要部分 内核shell文件系统应用程序 文件系统是一个目录树的结构&…

PyQt中QFrame窗口中的组件不显示的原因

文章目录 问题代码&#xff08;例&#xff09;原因和解决方法 问题代码&#xff08;例&#xff09; from PyQt5.QtWidgets import * from PyQt5.QtGui import QFont, QIcon, QCursor, QPixmap import sysclass FrameToplevel(QFrame):def __init__(self, parentNone):super().…

【Python基础篇】变量

博主&#xff1a;&#x1f44d;不许代码码上红 欢迎&#xff1a;&#x1f40b;点赞、收藏、关注、评论。 格言&#xff1a; 大鹏一日同风起&#xff0c;扶摇直上九万里。 文章目录 一 Python中变量的定义二 Python中变量的使用三 Python中变量的类型四 Python中变量的删除五 …

[数据结构大作业]HBU 河北大学校园导航

校园导航实验报告 问题描述&#xff1a; 以我校为例&#xff0c;设计一个校园导航系统&#xff0c;主要为来访的客人提供信息查询。系统有两类登陆账号&#xff0c;一类是游客&#xff0c;使用该系统方便校内路线查询&#xff1b;一类是管理员&#xff0c;可以使用该系统查询…