如何实现多分组柱状图以及按照分组维度高亮的交互?

问题描述

在工作中,有人问我,类似下面图里的柱状图如何实现:

  1. 期望两个分组通过颜色透明度进行样式上的区分;
  2. 当鼠标悬浮在一个柱子区块时,联动高亮相同颜色的所有区块;

交互示意:

解决方案

本人对字节跳动的图表库 VChart 比较熟,用这个举个例子。

  1. 需要 4 个数据字段:
  2. 3 个分组字段:x 轴上有 3 层分组,分别对应字段 xField: ['type', 'type1', 'type2'];
  3. 1 个系列字段:用于区分颜色系列, seriesField: 'color'
  1. 高亮交互:可以配置 VChart 内置 element-highlight-by-group交互,指定交互高亮状态名为 'highligh',从而在图元样式中,为柱子添加描边效果:
css 复制代码
  interactions:[
    {
       type: 'element-highlight-by-group',
       highlightState:'highlight'
    }
  ],
  bar:{
    state:{
      highlight:{
        stroke:"black",
        lineWidth:1,
        zIndex:100
      }
    }
  },

相关文档

附完整代码:

可以粘贴到 编辑器 上尝试一下:

less 复制代码
const spec = {
  type: 'bar',
  height:400,
  data: [
    {
      values: [
        { type: 'Category One', min: 80,  color: 'A', type1: 'p', type2: 'T' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p', type2: 'T' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p', type2: 'T' },
        { type: 'Category One', min: 75,  color: 'C', type1: 'p', type2: 'T' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p', type2: 'T' },

        { type: 'Category One', min: 70,  color: 'A', type1: 'p', type2: 'T1' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p', type2: 'T1' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p', type2: 'T1' },
        { type: 'Category One', min: 50,  color: 'C', type1: 'p', type2: 'T1' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p', type2: 'T1' },

        { type: 'Category One', min: 70,  color: 'A', type1: 'p', type2: 'T2' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p', type2: 'T2' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p', type2: 'T2' },
        { type: 'Category One', min: 50,  color: 'C', type1: 'p', type2: 'T2' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p', type2: 'T2' },

        { type: 'Category One', min: 70,  color: 'A', type1: 'p', type2: 'T3' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p', type2: 'T3' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p', type2: 'T3' },
        { type: 'Category One', min: 50,  color: 'C', type1: 'p', type2: 'T3' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p', type2: 'T3' },

        { type: 'Category One', min: 70,  color: 'A', type1: 'p', type2: 'T4' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p', type2: 'T4' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p', type2: 'T4' },
        { type: 'Category One', min: 50,  color: 'C', type1: 'p', type2: 'T4' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p', type2: 'T4' },
        
        { type: 'Category One', min: 80,  color: 'A', type1: 'p1', type2: 'T' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p1', type2: 'T' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p1', type2: 'T' },
        { type: 'Category One', min: 75,  color: 'C', type1: 'p1', type2: 'T' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p1', type2: 'T' },

        { type: 'Category One', min: 70,  color: 'A', type1: 'p1', type2: 'T1' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p1', type2: 'T1' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p1', type2: 'T1' },
        { type: 'Category One', min: 50,  color: 'C', type1: 'p1', type2: 'T1' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p1', type2: 'T1' },

        { type: 'Category One', min: 70,  color: 'A', type1: 'p1', type2: 'T2' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p1', type2: 'T2' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p1', type2: 'T2' },
        { type: 'Category One', min: 50,  color: 'C', type1: 'p1', type2: 'T2' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p1', type2: 'T2' },

        { type: 'Category One', min: 70,  color: 'A', type1: 'p1', type2: 'T3' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p1', type2: 'T3' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p1', type2: 'T3' },
        { type: 'Category One', min: 50,  color: 'C', type1: 'p1', type2: 'T3' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p1', type2: 'T3' },

        { type: 'Category One', min: 70,  color: 'A', type1: 'p1', type2: 'T4' },
        { type: 'Category One', min: 40,  color: 'B', type1: 'p1', type2: 'T4' },
        { type: 'Category One', min: 40,  color: 'D', type1: 'p1', type2: 'T4' },
        { type: 'Category One', min: 50,  color: 'C', type1: 'p1', type2: 'T4' },
        { type: 'Category One', min: 30,  color: 'E', type1: 'p1', type2: 'T4' },

        

        { type: 'Category Two', min: 76,  color: 'A', type1: 'p', type2: 'T' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p', type2: 'T' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p', type2: 'T' },
        { type: 'Category Two', min: 65,  color: 'C', type1: 'p', type2: 'T' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p', type2: 'T' },

        { type: 'Category Two', min: 70,  color: 'A', type1: 'p', type2: 'T1' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p', type2: 'T1' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p', type2: 'T1' },
        { type: 'Category Two', min: 50,  color: 'C', type1: 'p', type2: 'T1' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p', type2: 'T1' },

        { type: 'Category Two', min: 70,  color: 'A', type1: 'p', type2: 'T2' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p', type2: 'T2' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p', type2: 'T2' },
        { type: 'Category Two', min: 50,  color: 'C', type1: 'p', type2: 'T2' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p', type2: 'T2' },

        { type: 'Category Two', min: 70,  color: 'A', type1: 'p', type2: 'T3' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p', type2: 'T3' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p', type2: 'T3' },
        { type: 'Category Two', min: 50,  color: 'C', type1: 'p', type2: 'T3' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p', type2: 'T3' },

        { type: 'Category Two', min: 70,  color: 'A', type1: 'p', type2: 'T4' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p', type2: 'T4' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p', type2: 'T4' },
        { type: 'Category Two', min: 50,  color: 'C', type1: 'p', type2: 'T4' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p', type2: 'T4' },
        
        { type: 'Category Two', min: 80,  color: 'A', type1: 'p1', type2: 'T' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p1', type2: 'T' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p1', type2: 'T' },
        { type: 'Category Two', min: 75,  color: 'C', type1: 'p1', type2: 'T' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p1', type2: 'T' },

        { type: 'Category Two', min: 70,  color: 'A', type1: 'p1', type2: 'T1' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p1', type2: 'T1' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p1', type2: 'T1' },
        { type: 'Category Two', min: 50,  color: 'C', type1: 'p1', type2: 'T1' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p1', type2: 'T1' },

        { type: 'Category Two', min: 70,  color: 'A', type1: 'p1', type2: 'T2' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p1', type2: 'T2' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p1', type2: 'T2' },
        { type: 'Category Two', min: 50,  color: 'C', type1: 'p1', type2: 'T2' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p1', type2: 'T2' },

        { type: 'Category Two', min: 70,  color: 'A', type1: 'p1', type2: 'T3' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p1', type2: 'T3' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p1', type2: 'T3' },
        { type: 'Category Two', min: 50,  color: 'C', type1: 'p1', type2: 'T3' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p1', type2: 'T3' },

        { type: 'Category Two', min: 70,  color: 'A', type1: 'p1', type2: 'T4' },
        { type: 'Category Two', min: 40,  color: 'B', type1: 'p1', type2: 'T4' },
        { type: 'Category Two', min: 40,  color: 'D', type1: 'p1', type2: 'T4' },
        { type: 'Category Two', min: 50,  color: 'C', type1: 'p1', type2: 'T4' },
        { type: 'Category Two', min: 30,  color: 'E', type1: 'p1', type2: 'T4' },
      ]
    }
  ],
  interactions:[
    {
       type: 'element-highlight-by-group',
       highlightState:'highlight'
    }
  ],
  bar:{
    style:{
      fillOpacity:(data) => data.type1 === 'p' ? 1: 0.5
    },
    state:{
      highlight:{
        stroke:"black",
        lineWidth:1,
        zIndex:100
      }
    }
  },
  xField: ['type', 'type1', 'type2'],
  yField: 'min',
  seriesField: 'color',
  axes: [
    {
      orient:"left",
      label:{ visible: false},
      grid:{ style:{ lineDash:[4,4], stroke:'#dddddd'} }
    },
    {
      orient:"bottom",
      paddingInner:[0.1,0.05,0.5]
    }
  ],
  tooltip:{
      visible:false
  }
};

const vchart = new VChart(spec, { dom: CONTAINER_ID });
vchart.renderSync();

// Just for the convenience of console debugging, DO NOT COPY!
window['vchart'] = vchart;
相关推荐
kyriewen2 分钟前
React Hooks原理:为什么不能写在if里?揭开Hook的“魔法”面纱
前端·react.js·前端框架
敲代码的彭于晏5 分钟前
Claude Code Token 烧得太快?这8个方案帮你立省90%!
前端·ai编程·claude
可视之道7 分钟前
设备拓扑图中的实时状态映射与动画策略:告警闪烁、流向动画、质量码怎么共存
前端
涂兵兵_青石疏影8 分钟前
绘制图像-clip方法
前端
焦糖玛奇朵婷26 分钟前
解锁扭蛋机小程序的五大优势
java·大数据·服务器·前端·小程序
SwJieJie36 分钟前
windsurf的配置和项目规则、工作流、agent技巧使用
前端
白日梦想家6811 小时前
从基础入手,分清一次性定时器与永久定时器
前端
AIwork4me1 小时前
别再把 RAG 当知识库:用 AutoClaw 搭一套会进化的 Karpathy LLM Wiki
前端
彩票管理中心秘书长1 小时前
Git 归档与补丁命令大全(完整详解版)
前端
RePeaT1 小时前
【Nginx】前端项目部署与反向代理实战指南
前端·nginx