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

Vue2项目中使用 echarts(5.2.2)图表组件含代码(二)

1.图表预览

2.注释说明

Vue 的组件开发

  • 通过 props 定义外部传入的属性,例如 classNamewidthheightautoResizechartData 等。
  • 使用 Vue 的生命周期钩子函数 mounted 进行 ECharts 的实例化,确保组件加载完毕后才初始化图表。
  • 通过 watch 监听 chartData 数据的变化,自动更新图表。

ECharts 实例化和配置

  • 使用 echarts.init(this.$el) 创建图表实例,绑定到 Vue 组件的 DOM 元素上。
  • this.chart.setOption(option, true) 更新 ECharts 图表的配置。
  • 定义了自适应窗口大小的功能,监听 window.onresize,动态调整图表大小。

计算方法和自定义配置

  • fontSize(res) 根据窗口宽度动态计算字体大小,用于图表的响应式布局。
  • getPie3D(pieData, internalDiameterRatio)getParametricEquation() 是生成 3D 饼图的关键函数,使用数学公式构建 3D 饼图的曲面方程,并自定义了饼图的大小、半径、角度、选中效果等。
  • formatter 函数用于自定义图表的 legendtooltip 显示格式,返回带有富文本样式的字符串。

3.页面引入

<div class="com-view-body c-dis-flex-col c-hidden">
    <div class="c-width c-flex c-dis-flex-col c-hidden">
       <ChartView :chart-data="riskChartData"></ChartView>
    </div>
</div>

import { randomNum } from '@/utils/index.js'
import ChartView from '@/components/Charts/ChartView.vue'


 riskChartData: {
        name: "风险总数",
        color: ["#ED6F81", "#F3843D", "#4B64F7", "#34C294"],
        legend: ['二级风险', '三级风险', '四级风险', '五级风险'],
        data: [
          { name: "二级风险", value: 0, unit: "个" },
          { name: "三级风险", value: 0, unit: "个" },
          { name: "四级风险", value: 0, unit: "个" },
          { name: "五级风险", value: 0, unit: "个" },
        ],
},

4.图表组件 

<template>
  <div :class="className" :style="{ height: height, width: width }" />
</template>

<script>
import * as echarts from 'echarts'; // 导入 echarts 库
import "echarts-gl"; // 导入 echarts 的 3D 图表支持
import resize from '@/components/mixin/resize'; // 导入窗口 resize 相关的 mixin

export default {
  mixins: [resize], // 引入 mixin
  props: {
    className: {
      type: String,
      default: 'chart', // 默认样式名为 'chart'
    },
    width: {
      type: String,
      default: '100%', // 默认宽度为 100%
    },
    height: {
      type: String,
      default: '100%', // 默认高度为 100%
    },
    autoResize: {
      type: Boolean,
      default: true, // 默认启用自动调整大小
    },
    chartData: {
      type: Object,
      default: () => { } // 默认空对象,存储图表数据
    }
  },
  data() {
    return {
      chart: null, // 存储 echart 实例
      chartColor: {
        text: '#ffffff', // 文字颜色
        bg: '#02456b', // 背景色
        color: ['#06DEF3', '#1779CE', '#FAD961', '#F76B1C'], // 数据颜色
      },
      hoveredIndex: '', // 记录鼠标悬浮的索引
      option: null // 存储图表配置
    }
  },
  mounted() {
    // DOM 渲染后初始化图表
    this.$nextTick(() => {
      this.chart = echarts.init(this.$el); // 初始化 echart 实例
      this.initChart(); // 调用初始化方法
    });
  },
  watch: {
    chartData: {
      deep: true, // 深度监听 chartData
      handler(val) {
        this.initChart(); // 当 chartData 发生变化时,重新初始化图表
      },
    },
  },
  methods: {
    /**
     * 根据屏幕大小调整字体大小
     * @param {Number} res 原始字体大小
     * @return {Number} 调整后的字体大小
     */
    fontSize(res) {
      let clientWidth =
        window.innerWidth ||
        document.documentElement.clientWidth ||
        document.body.clientWidth;
      if (!clientWidth) return;
      let fontSize = clientWidth / 1920; // 按 1920 设计稿宽度计算比例
      return res * fontSize;
    },

    /**
     * 初始化图表,设置图表配置项
     */
    initChart() {
      let that = this;
      const series = this.getPie3D(this.chartData.data, 0.85); // 生成3D饼图的系列
      series.push({
        name: "pie2d", // 2D饼图,用于3D饼图视觉对齐
        type: "pie",
        labelLine: { length: 0, length2: 0 },
        startAngle: 2, // 起始角度
        clockwise: false, // 逆时针旋转
        radius: ["0%", "0%"], // 饼图半径
        center: ["0%", "0%"], // 饼图中心位置
        data: this.chartData.data,
        itemStyle: { opacity: 0 } // 设置透明度
      });

      let rich = { name: { fontSize: this.fontSize(12), color: "#fff" } };
      // 动态生成 rich 配置,用于自定义图例文本样式
      for (let i = 0; i < 7; i++) {
        rich[`name${i}`] = {
          fontSize: this.fontSize(i === 1 ? 16 : 20),
          align: 'left',
          padding: [0, 0, 0, this.fontSize(10)],
          fontWeight: i === 1 ? 900 : 600,
          color: i !== 0 ? this.chartData.color[i - 2] : 'rgba(130, 159, 179, 1)'
        };
      }

      // 动态为每个数据项添加样式
      this.chartData.data.map((item, index) => {
        let style = {
          fontSize: this.fontSize(16),
          padding: [0, 5, 0, 5],
          color: this.chartData.color[index],
        };
        this.$set(rich, `value${index}`, style);
      });

      // 定义图表配置项
      let option = {
        color: this.chartData.color,
        legend: {
          show: true,
          orient: 'vertical',
          right: '5%',
          top: 'center',
          itemWidth: this.fontSize(16),
          itemHeight: this.fontSize(4),
          textStyle: {
            fontWeight: 400,
            color: '#CEE8F8',
            fontSize: this.fontSize(14),
            lineHeight: this.fontSize(26),
            rich: rich,
          },
          formatter: function (name) {
            let res = that.chartData.data.find(v => v.name === name);
            return `{name1|${res.name}}{name${that.chartData.data.indexOf(res) + 2}|${res.value}}{name0|${res.unit}}`;
          },
        },
        tooltip: {
          formatter: function (optionsData) {
            let value = that.chartData.data.find(v => v.name === optionsData.seriesName)?.value || 0;
            return `${optionsData.seriesName}: ${value}`;
          },
          borderColor: this.chartColor.bg,
          backgroundColor: this.chartColor.bg,
          textStyle: {
            color: '#fff',
            fontSize: this.fontSize(12),
            rich: rich
          },
        },
        title: {
          text: that.chartData.name,
          textAlign: 'center',
          left: '30%',
          top: '43%',
          textStyle: { color: "#fff", fontSize: this.fontSize(14) },
        },
        series: series,
      };

      this.chart.setOption(option, true); // 设置图表配置项
      this.chart.resize(); // 图表自适应
      window.onresize = () => this.chart.resize(); // 监听窗口大小变化
    },

    /**
     * 生成扇形的参数方程
     * @param {Number} startRatio 扇形起始比例
     * @param {Number} endRatio 扇形结束比例
     * @param {Boolean} isSelected 是否选中
     * @param {Boolean} isHovered 是否悬浮
     * @param {Number} k 辅助参数
     * @param {Number} height 扇形高度
     * @param {Number} i 当前序号
     * @return {Object} 曲面参数方程
     */
    getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, height, i) {
      // 曲面参数方程的实现,计算每个扇形的坐标和大小
      // ...
    },

    /**
     * 生成模拟 3D 饼图的配置项
     * @param {Array} pieData 饼图数据
     * @param {Number} internalDiameterRatio 内环直径比
     * @return {Array} 图表 series 配置项
     */
    getPie3D(pieData, internalDiameterRatio) {
      let series = [];
      let sumValue = pieData.reduce((sum, data) => sum + data.value, 0); // 计算总值
      let startValue = 0;

      pieData.forEach((data, i) => {
        let endValue = startValue + data.value;
        let seriesItem = {
          name: data.name || `series${i}`,
          type: "surface",
          parametric: true,
          pieData: data,
          pieStatus: { selected: false, hovered: false, k: (1 - internalDiameterRatio) / (1 + internalDiameterRatio) }
        };
        seriesItem.parametricEquation = this.getParametricEquation(
          startValue / sumValue,
          endValue / sumValue,
          false,
          false,
          seriesItem.pieStatus.k,
          10,
          i
        );
        startValue = endValue;
        series.push(seriesItem);
      });

      return series;
    },
  },
}
</script>


http://www.kler.cn/a/349444.html

相关文章:

  • 【旋转数组】二分法专题
  • HDLBits中文版,标准参考答案 | 3.3 Building Larger Circuits | 构建更大的电路
  • 本地生活全域抽佣系统--本地生活服务商的便捷运营平台
  • 使用C++写一个自己定义的图像格式,写入磁盘
  • unity学习-灯光类型
  • 高可用之限流 08-leaky bucket漏桶算法
  • leetcode解题思路分析(一百六十一)1394 - 1400 题
  • ros service不走是为什么
  • STM32的独立看门狗定时器(IWDG)技术介绍
  • spring面试之2024
  • 【量化交易】聚宽安装
  • Linux虚拟化技术嬗变综述
  • MeterSphere接口自动化平台调试
  • 使用 Spring 框架构建 MVC 应用程序:初学者教程
  • 【三】【算法】P1007 独木桥,P1012 [NOIP1998 提高组] 拼数,P1019 [NOIP2000 提高组] 单词接龙
  • 元学习案例(学习如何学习)
  • vue3中如何给响应式对象
  • 微分几何-曲线论(向量函数)
  • 2024年【汽车驾驶员(技师)】考试题库及汽车驾驶员(技师)试题及解析
  • 集合框架05:List接口使用、List实现类、ArrayList使用