Vue3实战笔记(43)—Vue3组合式API下封装可复用ECharts图表组件

news2024/11/16 12:00:16

文章目录

  • 前言
  • 一、封装echart图标钩子
  • 二、使用步骤
  • 总结


前言

接上文,已经安装好了ECharts,开始封装组件方便使用。


一、封装echart图标钩子

首先应用我们之前学习的钩子方式,在hooks目录下创建一个名为 useECharts.js 的文件,用于封装 ECharts 的逻辑:


import { ref, onMounted, onUnmounted } from 'vue';
import * as echarts from 'echarts';

export default function useECharts(chartContainer, options) {
  const chartInstance = ref(null);

  onMounted(() => {
    // 初始化 ECharts 实例
    chartInstance.value = echarts.init(chartContainer.value);
    // 设置 ECharts 配置项
    chartInstance.value.setOption(options.value);

    // 监听窗口大小变化,自动调整图表大小
    window.addEventListener('resize', () => chartInstance.value.resize());
  });

  onUnmounted(() => {
    // 销毁 ECharts 实例
    chartInstance.value.dispose();
    // 移除窗口大小变化监听器
    window.removeEventListener('resize', () => chartInstance.value.resize());
  });

  // 返回 ECharts 实例,以便在外部进行操作
  return chartInstance;
}

二、使用步骤

其实这样就做到了简单的封装,可以直接使用了:

  <div ref="chartContainer" style="width: 100%; height: 400px"></div>
</template><script>
import useECharts from './useECharts';

export default {
  setup() {
    const chartContainer = ref(null);
    const options = ref({
      // ECharts 配置项
      title: {
        text: 'ECharts 示例',
      },
      tooltip: {},
      xAxis: {
        data: ['类目1', '类目2', '类目3', '类目4', '类目5', '类目6'],
      },
      yAxis: {},
      series: [
        {
          name: '数值',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20],
        },
      ],
    });

    const chartInstance = useECharts(chartContainer, options);

    // 你可以在这里根据需要操作 ECharts 实例,例如更新数据
    // chartInstance.value.setOption({...})

    return {
      chartContainer,
    };
  },
};
</script>

为了更方便使用,我们可以进一步封装一些常用的组件,例如:
在components中创建组件EChartsGaugeClock.vue

代码如下(示例):


<template>
    <div ref="chartContainer" style="width: 100%; height: 100%"></div>
</template>

<script setup lang="ts" name="">
import { ref } from 'vue';
import useECharts from '@/hooks/useECharts';


const chartContainer = ref(null);


const options = ref({
  series: [
    {
      name: 'hour',
      type: 'gauge',
      startAngle: 90,
      endAngle: -270,
      min: 0,
      max: 12,
      splitNumber: 12,
      clockwise: true,
      axisLine: {
        lineStyle: {
          width: 15,
          color: [[1, 'rgba(0,0,0,0.7)']],
          shadowColor: 'rgba(0, 0, 0, 0.5)',
          shadowBlur: 15
        }
      },
      splitLine: {
        lineStyle: {
          shadowColor: 'rgba(0, 0, 0, 0.3)',
          shadowBlur: 3,
          shadowOffsetX: 1,
          shadowOffsetY: 2
        }
      },
      axisLabel: {
        fontSize: 50,
        distance: 25,
        formatter: function (value) {
          if (value === 0) {
            return '';
          }
          return value + '';
        }
      },
      anchor: {
        show: true,
        icon: 'path://M532.8,70.8C532.8,70.8,532.8,70.8,532.8,70.8L532.8,70.8C532.7,70.8,532.8,70.8,532.8,70.8z M456.1,49.6c-2.2-6.2-8.1-10.6-15-10.6h-37.5v10.6h37.5l0,0c2.9,0,5.3,2.4,5.3,5.3c0,2.9-2.4,5.3-5.3,5.3v0h-22.5c-1.5,0.1-3,0.4-4.3,0.9c-4.5,1.6-8.1,5.2-9.7,9.8c-0.6,1.7-0.9,3.4-0.9,5.3v16h10.6v-16l0,0l0,0c0-2.7,2.1-5,4.7-5.3h10.3l10.4,21.2h11.8l-10.4-21.2h0c6.9,0,12.8-4.4,15-10.6c0.6-1.7,0.9-3.5,0.9-5.3C457,53,456.7,51.2,456.1,49.6z M388.9,92.1h11.3L381,39h-3.6h-11.3L346.8,92v0h11.3l3.9-10.7h7.3h7.7l3.9-10.6h-7.7h-7.3l7.7-21.2v0L388.9,92.1z M301,38.9h-10.6v53.1H301V70.8h28.4l3.7-10.6H301V38.9zM333.2,38.9v10.6v10.7v31.9h10.6V38.9H333.2z M249.5,81.4L249.5,81.4L249.5,81.4c-2.9,0-5.3-2.4-5.3-5.3h0V54.9h0l0,0c0-2.9,2.4-5.3,5.3-5.3l0,0l0,0h33.6l3.9-10.6h-37.5c-1.9,0-3.6,0.3-5.3,0.9c-4.5,1.6-8.1,5.2-9.7,9.7c-0.6,1.7-0.9,3.5-0.9,5.3l0,0v21.3c0,1.9,0.3,3.6,0.9,5.3c1.6,4.5,5.2,8.1,9.7,9.7c1.7,0.6,3.5,0.9,5.3,0.9h33.6l3.9-10.6H249.5z M176.8,38.9v10.6h49.6l3.9-10.6H176.8z M192.7,81.4L192.7,81.4L192.7,81.4c-2.9,0-5.3-2.4-5.3-5.3l0,0v-5.3h38.9l3.9-10.6h-53.4v10.6v5.3l0,0c0,1.9,0.3,3.6,0.9,5.3c1.6,4.5,5.2,8.1,9.7,9.7c1.7,0.6,3.4,0.9,5.3,0.9h23.4h10.2l3.9-10.6l0,0H192.7z M460.1,38.9v10.6h21.4v42.5h10.6V49.6h17.5l3.8-10.6H460.1z M541.6,68.2c-0.2,0.1-0.4,0.3-0.7,0.4C541.1,68.4,541.4,68.3,541.6,68.2L541.6,68.2z M554.3,60.2h-21.6v0l0,0c-2.9,0-5.3-2.4-5.3-5.3c0-2.9,2.4-5.3,5.3-5.3l0,0l0,0h33.6l3.8-10.6h-37.5l0,0c-6.9,0-12.8,4.4-15,10.6c-0.6,1.7-0.9,3.5-0.9,5.3c0,1.9,0.3,3.7,0.9,5.3c2.2,6.2,8.1,10.6,15,10.6h21.6l0,0c2.9,0,5.3,2.4,5.3,5.3c0,2.9-2.4,5.3-5.3,5.3l0,0h-37.5v10.6h37.5c6.9,0,12.8-4.4,15-10.6c0.6-1.7,0.9-3.5,0.9-5.3c0-1.9-0.3-3.7-0.9-5.3C567.2,64.6,561.3,60.2,554.3,60.2z',
        showAbove: false,
        offsetCenter: [0, '-35%'],
        size: 120,
        keepAspect: true,
        itemStyle: {
          color: '#707177'
        }
      },
      pointer: {
        icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z',
        width: 12,
        length: '55%',
        offsetCenter: [0, '8%'],
        itemStyle: {
          color: '#C0911F',
          shadowColor: 'rgba(0, 0, 0, 0.3)',
          shadowBlur: 8,
          shadowOffsetX: 2,
          shadowOffsetY: 4
        }
      },
      detail: {
        show: false
      },
      title: {
        offsetCenter: [0, '30%']
      },
      data: [
        {
          value: 0
        }
      ]
    },
    {
      name: 'minute',
      type: 'gauge',
      startAngle: 90,
      endAngle: -270,
      min: 0,
      max: 60,
      clockwise: true,
      axisLine: {
        show: false
      },
      splitLine: {
        show: false
      },
      axisTick: {
        show: false
      },
      axisLabel: {
        show: false
      },
      pointer: {
        icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z',
        width: 8,
        length: '70%',
        offsetCenter: [0, '8%'],
        itemStyle: {
          color: '#C0911F',
          shadowColor: 'rgba(0, 0, 0, 0.3)',
          shadowBlur: 8,
          shadowOffsetX: 2,
          shadowOffsetY: 4
        }
      },
      anchor: {
        show: true,
        size: 20,
        showAbove: false,
        itemStyle: {
          borderWidth: 15,
          borderColor: '#C0911F',
          shadowColor: 'rgba(0, 0, 0, 0.3)',
          shadowBlur: 8,
          shadowOffsetX: 2,
          shadowOffsetY: 4
        }
      },
      detail: {
        show: false
      },
      title: {
        offsetCenter: ['0%', '-40%']
      },
      data: [
        {
          value: 0
        }
      ]
    },
    {
      name: 'second',
      type: 'gauge',
      startAngle: 90,
      endAngle: -270,
      min: 0,
      max: 60,
      animationEasingUpdate: 'bounceOut',
      clockwise: true,
      axisLine: {
        show: false
      },
      splitLine: {
        show: false
      },
      axisTick: {
        show: false
      },
      axisLabel: {
        show: false
      },
      pointer: {
        icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z',
        width: 4,
        length: '85%',
        offsetCenter: [0, '8%'],
        itemStyle: {
          color: '#C0911F',
          shadowColor: 'rgba(0, 0, 0, 0.3)',
          shadowBlur: 8,
          shadowOffsetX: 2,
          shadowOffsetY: 4
        }
      },
      anchor: {
        show: true,
        size: 15,
        showAbove: true,
        itemStyle: {
          color: '#C0911F',
          shadowColor: 'rgba(0, 0, 0, 0.3)',
          shadowBlur: 8,
          shadowOffsetX: 2,
          shadowOffsetY: 4
        }
      },
      detail: {
        show: false
      },
      title: {
        offsetCenter: ['0%', '-40%']
      },
      data: [
        {
          value: 0
        }
      ]
    }
  ]
});

const chartInstance = useECharts(chartContainer, options);

setInterval(function () {
  var date = new Date();
  var second = date.getSeconds();
  var minute = date.getMinutes() + second / 60;
  var hour = (date.getHours() % 12) + minute / 60;
  // options.animationDurationUpdate = 300;
  chartInstance.value.setOption({
    series: [
      {
        name: 'hour',
        animation: hour !== 0,
        data: [{ value: hour }]
      },
      {
        name: 'minute',
        animation: minute !== 0,
        data: [{ value: minute }]
      },
      {
        animation: second !== 0,
        name: 'second',
        data: [{ value: second }]
      }
    ]
  });
}, 1000);




// 你可以在这里根据需要操作 ECharts 实例,例如更新数据
// chartInstance.value.setOption({...})

</script>

<style lang='scss' scoped>
* {
  margin: 0;
  padding: 0;
}
#chartContainer {
  position: relative;
  height: 300px;
  overflow: hidden;
}

</style>

在components中创建组件EChartsGaugeSimple.vue,
代码如下(示例):


<template>
    <div ref="chartContainer" style="width: 100%; height: 100%"></div>
</template>

<script setup lang="ts" name="">
import { ref } from 'vue';
import useECharts from '@/hooks/useECharts';


const chartContainer = ref(null);
const options = ref({
  tooltip: {
    formatter: '{a} <br/>{b} : {c}%'
  },
  series: [
    {
      name: 'Pressure',
      type: 'gauge',
      progress: {
        show: true
      },
      detail: {
        valueAnimation: true,
        formatter: '{value}'
      },
      data: [
        {
          value: 50,
          name: 'SCORE'
        }
      ]
    }
  ]
});

const chartInstance = useECharts(chartContainer, options);

// 你可以在这里根据需要操作 ECharts 实例,例如更新数据
// chartInstance.value.setOption({...})
</script>

<style lang='scss' scoped>
</style>

两个组件封装好了直接在主页使用:


  <div style="height:600px;">
      <EChartsGaugeSimple></EChartsGaugeSimple>
  </div>
  
  <div style="height:600px;">
      <EChartsGaugeClock></EChartsGaugeClock>
  </div>

在这里插入图片描述


总结

把常用的都封装好,这样使用起来方便多了。

千行代码,一 bug 倾城。

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

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

相关文章

边框渐变样式

实现样式&#xff1a; 对应代码&#xff1a; div {min-height: 40vh;border: 10px solid transparent;background-image: linear-gradient(#222, #222), var(--gradient);background-origin: border-box;background-clip: padding-box, border-box;border-radius: 10px;positi…

【深度学习】yolov8 seg实例分割训练,交通灯

文章目录 一、类别定义二、标注后再清洗数据三、训练yolov8 seg四、部署五、代码资料 一、类别定义 类别0&#xff1a; 类别1&#xff1a; 类别2&#xff1a; 类别3&#xff1a; 类别4&#xff1a; 类别5&#xff1a; 类别6&#xff1a; 类别7&#xff1a; 二、标注后再清洗…

kubernetes之prometheus kube-controller-manager。 scheduler报错问题

项目场景&#xff1a; prometheus scheduler及kube-controller-manager监控报错 问题描述 kubeadm搭建完kube-prometheus 会有这个报错 原因分析&#xff1a; rootmaster2:~# kubectl describe servicemonitor -n kube-system kube-controller-manager通过以上图片我们发现 k…

数据结构_链式二叉树(Chained binary tree)基础

✨✨所属专栏&#xff1a;数据结构✨✨ ✨✨作者主页&#xff1a;嶔某✨✨ 二叉树的遍历 前序、中序以及后序遍历 学习二叉树结构&#xff0c;最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则&#xff0c;依次对二叉树中的结点进行相应的操作&#xff…

自己手写一个栈【C风格】

#include <iostream> //栈 #define MAX_SIZE 20 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0typedef int Status;//状态类型 typedef int ElemType;//元素类型typedef struct SqStack {ElemType data[MAX_SIZE];int top; };//初始化&#xff0c;方法1 …

安装 Ubuntu桌面版,详细步骤(附引导 U盘制作工具)

下载镜像 安装Ubuntu首先要下载镜像包&#xff0c;访问下面网址下载镜像包 https://releases.ubuntu.com/ 选择你要安装的Ubuntu版本 将 .iso 文件保存到所需位置&#xff0c;下面会使用此文件创建可引导 U盘。 制作 Ubuntu 引导 U 盘 首先要找到一个大于4G的U盘&#xff…

用Python Pygame做的一些好玩的小游戏

有些游戏的代码比较长就不公布了 1.简简单单 1.疯狂的鸡哥 你要准备的图片&#xff1a; 命名为&#xff1a;ji.png 代码&#xff1a; import pygame import random as r pygame.init() pygame.display.set_caption(aaa) pm pygame.display.set_mode((800,600))class Ls(py…

三前奏:获取/ 读取/ 评估数据【数据分析】

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 前面的博客 数据分析—技术栈和开发环境搭建 …

Excel提取某一列的唯一值

点击【筛选】&#xff08;【高级筛选】&#xff09;&#xff0c;参数里&#xff1a; 列表区域&#xff1a;为需要选择唯一值的那一列复制到&#xff1a;生成唯一值的目标区域 据说新版本的excel有了unique()函数&#xff0c;可以很快捷的选择某一列的唯一值&#xff0c;但是博…

深度学习500问——Chapter09:图像分割(3)

文章目录 9.8 PSPNet 9.9 DeepLab系列 9.9.1 DeepLabv1 9.9.2 DeepLabv2 9.9.3 DeeoLabv3 9.9.4 DeepLabv3 9.8 PSPNet 场景解析对于无限制的开放词汇和不同场景来说是具有挑战性的。本文使用文中的 pyramid pooling module 实现基于不同区域的上下文集成&#xff0c;提出了PS…

Java进阶学习笔记14——模板方法设计模式

面试和看源码。 谈到设计模式&#xff1a; 1、解决了什么问题&#xff1f; 2、怎么写&#xff1f; 模板方法设计模式解决了什么问题&#xff1f; 解决方法中存在重复代码的问题。 写法&#xff1a; 1&#xff09;定义一个抽象类&#xff1a; 2&#xff09;在里面定义两个方…

阅读笔记——《ProFuzzBench: A Benchmark for Stateful Protocol Fuzzing》

【参考文献】Natella R, Pham V T. Profuzzbench: A benchmark for stateful protocol fuzzing[C]//Proceedings of the 30th ACM SIGSOFT international symposium on software testing and analysis. 2021: 662-665.【注】本文仅为作者个人学习笔记&#xff0c;如有冒犯&…

Java反射角度简单理解spring IOC容器

概述 Java反射&#xff08;Reflection&#xff09;是Java编程语言的一个特性&#xff0c;它允许在运行时对类、接口、字段和方法进行动态查询和操作。反射提供了一种在运行时查看和修改程序行为的能力&#xff0c;这通常用于实现一些高级功能&#xff0c;如框架(Spring)、ORM&…

【正点原子Linux连载】 第四十七章 音频驱动实验摘自【正点原子】ATK-DLRK3568嵌入式Linux驱动开发指南

1&#xff09;实验平台&#xff1a;正点原子ATK-DLRK3568开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id731866264428 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第四十…

EEGLAB的相关使用

目录 概念 1.安装EEGLAB 2.文件实例演示 导入数据集处理 &#xff08;1&#xff09;导入数据集 &#xff08;2&#xff09;画图 &#xff08;3&#xff09; 修改并存储数据集 &#xff08;4&#xff09; 保存数据集 &#xff08;5&#xff09; 删除数据集 &#xff0…

零基础HTML教程(33)--HTML5表单新功能

文章目录 1. 背景2. HTML5新增表单元素2.1 number (数字输入框)2.2 email (邮箱输入框)2.3 url (链接输入框)2.4 tel (电话输入框)2.5 range (范围选择框)2.6 color (颜色选择框)2.7 datetime (日期时间选择框)2.8 search (搜索框) 3. placeholder &#xff08;占位属性&#x…

php TP8 阿里云短信服务SDKV 2.0

安装&#xff1a;composer require alibabacloud/dysmsapi-20170525 2.0.24 官方文档&#xff1a;短信服务_SDK中心-阿里云OpenAPI开发者门户 (aliyun.com) 特别注意&#xff1a;传入参数获得值形式 正确&#xff1a; $PhoneNumbers $postData[PhoneNumbers];$signName $po…

Vue集成Iframe

一、应用场景&#xff0c;为什么要集成Iframe&#xff1f; 1、庞大项目拆分后&#xff0c;便于管理和部署&#xff0c;用集成Iframe的方法合并 2、避免功能重复开发&#xff0c;共用模块可单独开发为一个项目&#xff0c;既可独立部署&#xff0c;也可集成到中台系统 二、集成…

【feature selection】特征选择学习笔记

文章目录 1. 什么是特征选择2. 特征选择与特征提取的区别3. 特征选择的方法3.1 Filtering过滤法3.2 Wrapper包装法3.3 Embedding嵌入法 4. 特征选择示例4.1 方差选择法示例4.2 递归特征消除法示例 1. 什么是特征选择 特征选择是特征工程的内容, 其目标是寻找最优特征子集。剔除…

暴雨“彩虹”行业大模型加速器平台全新发布

近日&#xff0c;在第七届数字中国建设峰会期间&#xff0c;暴雨信息全新发布“彩虹”行业大模型加速器平台&#xff0c;聚焦于为客户降本增效减负&#xff0c;将海量通用数据与行业特有数据融合&#xff0c;专注于流程工艺的智能化改进&#xff0c;因地制宜深挖业务需求&#…