echarts+vue动态生成可配置的桑基(sankey)图

效果展示

在这里插入图片描述

实现思路

  1. 桑基图实现的本质也是一条条source-target,节点与节点之间的连线
  2. 做到完全可配置化,需抽离出大量可配置的属性
  3. 无数据的节点要进行隐藏,因此需要加是否有数据的判断
  4. 节点颜色和线条颜色通过设置itemStyle和lineStyle来配置
  5. 分辨率自适应则需要设置函数来动态计算

实现代码

//now-size.js
let nowClientWidth = document.documentElement.clientWidth;
export function nowSize(val, initWidth = 1920) {
  return val * (nowClientWidth / initWidth);
}

在这里插入图片描述

<template>
  <div class="situation-visit-relation" ref="chart"></div>
</template>

<script>
import { nowSize } from "@/utils/now-size"
import { getAppRelation } from "@/service/situation-service"
import { PAGE_URL_WEBAPP } from "@/constant/page-url-constants"
export default {
  data() {
    return {
      PAGE_URL_WEBAPP,
      isLoading: false,
      linkMap: {},//连线数据
      itemMap: {},//节点-名称映射表
      itemList: {},//节点枚举列表
      colorMap: {},//连线颜色枚举列表
      labelMap: {},//节点-标签名映射表
      sourceList: {},//源节点枚举列表
      targetList: {},//目标节点枚举列表
      itemColorMap: {}//节点-颜色映射表
    }
  },
  mounted() {
    this.init();
  },
  methods: {
    // 初始化
    async init() {
      await getAppRelation().then(res => {
        this.itemMap = res.data.itemMap;
        this.labelMap = res.data.labelMap;
        this.linkMap = res.data.linkMap;
        this.sourceList = res.data.sourceList;
        this.targetList = res.data.targetList;
        this.itemList = res.data.itemList;
        this.colorMap = res.data.colorMap;
        this.itemColorMap = Object.assign(res.data.sourceColorMap, res.data.targetColorMap);
      }).catch(() => {
        this.$message.error("获取应用访问关系数据失败")
      });
      this.paintChart();
    },
    // 获取图表数据
    getChartData() {
      let chartData = {
        linkData: [],
        itemData: [],
      };
      let itemDataTmp = [];
      for (let i = 0; i < 3; i++) {
        for (let j = 0; j < 3; j++) {
          if (this.linkMap[`${this.sourceList[i]}2${this.targetList[j]}`] !== 0) {
            if (itemDataTmp.indexOf(this.sourceList[i]) === -1) {
              itemDataTmp.push(this.sourceList[i]);
            }
            if (itemDataTmp.indexOf(this.targetList[j]) === -1) {
              itemDataTmp.push(this.targetList[j]);
            }
            chartData.linkData.push({
              source: this.sourceList[i],
              target: this.targetList[j],
              value: this.linkMap[`${this.sourceList[i]}2${this.targetList[j]}`],
              lineStyle: {
                color: this.colorMap[`${this.sourceList[i]}2${this.targetList[j]}`],
              },
              tooltip: {
                show: true,
                formatter: (params) => {
                  return `${this.itemMap[params.data.target]}访问${this.itemMap[params.data.source]
                    }应用个数:${this.linkMap[
                      `${params.data.source}2${params.data.target}`
                    ]?.toLocaleString()}`;
                },
              },
            });
          }
        }
      }
      itemDataTmp.forEach((item) => {
        let index = this.itemList.indexOf(item);
        if (index !== -1) {
          chartData.itemData.push({
            name: item,
            itemStyle: {
              color: this.itemColorMap[item],
              borderColor: this.itemColorMap[item]
            },
            tooltip: {
              show: false,
            },
          });
        }
      });
      return chartData;
    },
    // 绘制图表
    paintChart() {
      let chartData = this.getChartData();
      let linkData = chartData.linkData;
      let itemData = chartData.itemData;
      let chartDom = this.$echarts.init(this.$refs.chart);
      if (chartDom) {
        let option = {
          tooltip: {
            show: true,
          },
          series: {
            type: "sankey",
            layout: "none",
            top: nowSize(75),
            left: nowSize(30),
            right: nowSize(100),
            nodeWidth: 15,
            draggable: false,
            emphasis: {
              focus: "adjacency",
            },
            label: {
              color: "#fff",
              formatter: (params) => {
                return this.labelMap[params.name];
              },
              fontSize: nowSize(12),
              size: nowSize(10)
            },
            data: itemData,
            links: linkData,
          },
        };
        chartDom && chartDom.setOption(option);
        chartDom.on('click', (params) => {
          let query = {};
          if (params.data.name) {
            if (params.data.name[0] === "v") {
              query = {
                tab: "list",
                visitDomains: this.labelMap[params.data.name],
              };
            } else {
              query = {
                tab: "list",
                deployDomains: this.labelMap[params.data.name],
              };
            }
            this.$linkTo({
              path: PAGE_URL_WEBAPP,
              query: query,
            });
          }
          if (params.data.source) {
            this.$linkTo({
              path: PAGE_URL_WEBAPP,
              query: {
                tab: "list",
                deployDomains: this.labelMap[params.data.source],
                visitDomains: this.labelMap[params.data.target],
              },
              type: "_blank"
            });
          }
        });
        let sizeFun = () => {
          chartDom.resize();
        };
        window.addEventListener("resize", sizeFun);
        this.$once("hook:beforeDestroy", function () {
          this.$echarts.dispose(chartDom);
        });
      }
    },
  }
}
</script>

<style lang="less">
.situation-visit-relation {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
}
</style>

ECharts是一款基于JavaScript的开源可视化表库,而Vue是一套用于构建用户界面的渐进式JavaScript框架。结合使用EChartsVue可以创建各种交互式的数据可视化表。 一个常见的ECharts Vue案例是在Vue项目中使用ECharts来展示特定数据集的柱状。以下是该案例的简要实现步骤: 1. 安装ECharts:使用npm或yarn命令在Vue项目中安装ECharts。例如,可以执行以下命令来安装ECharts: ``` npm install echarts --save ``` 2. 导入ECharts库:在需要使用EChartsVue组件中导入ECharts库。例如,可以在script标签中添加以下代码: ```javascript import echarts from 'echarts' ``` 3. 创建表容器:在Vue组件中创建一个div元素作为表的容器。例如,可以在template标签中添加以下代码: ```html <template> <div id="chartContainer"></div> </template> ``` 4. 初始化表实例:在Vue组件的mounted生命周期钩子函数中通过ECharts初始化表的实例。例如,可以在script标签中添加以下代码: ```javascript mounted() { const chartContainer = document.getElementById('chartContainer') const chart = echarts.init(chartContainer) } ``` 5. 配置表选项:通过设置ECharts实例的option属性来配置表的选项。例如,可以在mounted函数中添加以下代码: ```javascript mounted() { const chartContainer = document.getElementById('chartContainer') const chart = echarts.init(chartContainer) chart.setOption({ xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [{ data: [120, 200, 150, 80, 70, 110, 130], type: 'bar' }] }) } ``` 6. 渲染表:通过调用ECharts实例的render方法将表渲染到页面中。例如,可以在mounted函数中最后添加以下代码: ```javascript mounted() { const chartContainer = document.getElementById('chartContainer') const chart = echarts.init(chartContainer) chart.setOption({ // 配置表选项 }) chart.render() } ``` 以上就是一个简单的ECharts Vue案例的实现步骤。通过按照以上步骤,可以在Vue项目中使用ECharts来展示各种类型的可视化表,包括折线、饼、雷达等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值