百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Vue3中我是这样玩Echart的

bigegpt 2024-08-10 12:17 14 浏览

Echart的基本操作

vue3中,通过npm install echarts可获取到对应的echart资源,在项目文件中建立对应的utils作为引用echart资源的工具库。

@/utils/utils

import * as echarts from "echarts/core"

import { BarChart, LineChart, PieChart, MapChart, PictorialBarChart, RadarChart } from "echarts/charts"

import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  PolarComponent,
  AriaComponent,
  ParallelComponent,
  LegendComponent,
  RadarComponent,
  ToolboxComponent,
  DataZoomComponent,
  VisualMapComponent,
  TimelineComponent,
  CalendarComponent,
  GraphicComponent
} from "echarts/components"

import { CanvasRenderer } from "echarts/renderers"

echarts.use([
  LegendComponent,
  TitleComponent,
  TooltipComponent,
  GridComponent,
  PolarComponent,
  AriaComponent,
  ParallelComponent,
  BarChart,
  LineChart,
  PieChart,
  MapChart,
  RadarChart,
  CanvasRenderer,
  PictorialBarChart,
  RadarComponent,
  ToolboxComponent,
  DataZoomComponent,
  VisualMapComponent,
  TimelineComponent,
  CalendarComponent,
  GraphicComponent
])

export default echarts

然后再建立个Echart.vue文件

<template>
  <div ref="echartsRef" style="height: 400px; width: 500px">gamePlay</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue"
import echarts from "@/utils/echarts"
const echartsRef = ref()
onMounted(() => {
  const myChart = echarts.init(echartsRef.value)
  // 指定图表的配置项和数据
  const option = {
    title: {
      text: "ECharts 入门示例"
    },
    tooltip: {},
    legend: {
      data: ["销量"]
    },
    xAxis: {
      data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
    },
    yAxis: {},
    series: [
      {
        name: "销量",
        type: "bar",
        data: [5, 20, 36, 10, 10, 20]
      }
    ]
  }

  // 使用刚指定的配置项和数据显示图表。
  myChart.setOption(option)
})
</script>


渲染出一个echart图表了。

封装useEchartHook渲染图表

虽然我们已经能渲染出图表了,但是这个操作并不是最优解,因为我们的实际业务中是存在很多不同类型的图表,不可能每个都实例化Echart然后再手动调用setOptions方法,这显的很蠢。那么这个时候就需要引入useHookEchart的做法了。

import { Ref, shallowRef, onMounted, onDeactivated, onBeforeUnmount } from "vue"
import echarts from "@/utils/echarts"
export type EChartsCoreOption = echarts.EChartsCoreOption
const useEcharts = (elRef: Ref<HTMLDivElement>, options: EChartsCoreOption) => {
  const charts = shallowRef<echarts.ECharts>()

  const initCharts = () => {
    charts.value = echarts.init(elRef.value)
    setOptions(options)
  }
  const setOptions = (options: EChartsCoreOption) => {
    charts.value && charts.value.setOption(options)
  }
  const echartsResize = () => {
    charts.value && charts.value.resize()
  }
  onMounted(() => {
    window.addEventListener("resize", echartsResize)
  })
  // 防止 echarts 页面 keepAlive 时,还在继续监听页面
  onDeactivated(() => {
    window.removeEventListener("resize", echartsResize)
  })

  onBeforeUnmount(() => {
    window.removeEventListener("resize", echartsResize)
  })
  return {
    initCharts,
    setOptions,
    echartsResize
  }
}
export { useEcharts }

然后再echart.vue中引入

<template>
  <div style="width: 100%; height: 100%" ref="elEcharts" />
</template>
<script setup lang="ts">
import { shallowRef, onMounted, watch } from "vue"
import { useEcharts, type EChartsCoreOption } from "@/hooks/useEcharts"

interface Props {
  options: EChartsCoreOption
}
const props = defineProps<Props>()
const themeStore = useThemeStore()
const elEcharts = shallowRef()
const currentOptions = shallowRef(props.options)
const { setOptions, initCharts } = useEcharts(elEcharts, currentOptions.value)

watch(
  () => props.options,
  (nVal) => {
    let targetOptions: EChartsCoreOption = {}
    if (themeStore.currentColorArray && themeStore.currentColorArray.length > 0) {
      targetOptions = { ...nVal }
      targetOptions.color = themeStore.currentColorArray
    } else {
      targetOptions = { ...nVal }
    }
    setOptions(targetOptions)
  }
)

onMounted(() => {
  initCharts()
})
</script>

业务中使用

<template>
    <BaseEcharts :options="options2" />
</template>
import BaseEcharts from "@/components/baseEcharts/index.vue"
const options2: EChartsCoreOption = {
  tooltip: {
    trigger: "axis"
  },

  grid: {
    left: "3%",
    right: "4%",
    bottom: "0%",
    top: "5%",
    containLabel: true
  },
  xAxis: {
    type: "category",
    boundaryGap: false,
    data: ["3-1", "3-2", "3-3", "3-4", "3-5", "3-6", "3-7"]
  },
  yAxis: {
    axisLabel: {
      formatter: function (val: number) {
        return val
      }
    }
  },
  series: [
    {
      name: "QQ",
      type: "line",
      stack: "Total",
      data: [200,201,202,203,204,205,206]
    },
    {
      name: "微信",
      type: "line",
      stack: "Total",
      data: [200,201,202,203,204,205,206]
    }
  ]
}


关于Echart主题换肤

由于产品希望图表的主题是可以自由变换的,也就是图表换肤。那好说,因为在echart中可以通过options上的color字段进行自由换主题。这个时候需要改造useEcharts中的initCharts方法

...
 const initCharts = (themeColor?: Array<string>) => {
    charts.value = echarts.init(elRef.value)
    if (themeColor) {
      options.color = themeColor
    }

    setOptions(options)
  }
...

然后再建立themeStore(由于是全局操作,这里使用的pinia) @/store/themeStore中建立updateCurrentColorByArray方法

import { defineStore } from "pinia"
import { ref } from "vue"
export const useThemeStore = defineStore("themeStore", () => {
 const currentColorArray = ref<string[]>()
  // 根据颜色组更新当前颜色组
  const updateCurrentColorByArray = (color: string[]) => {
    currentColorArray.value = color
  }



  return {
    updateCurrentColorByArray,
    currentColorArray
  }
})

在echartsTheme.ts中预设以下几种主题

export const echartsThemeData = [
  {
    name: "vintage",
    background: "#fef8ef",
    theme: [
      "#d87c7c",
      "#919e8b",
      "#d7ab82",
      "#6e7074",
      "#61a0a8",
      "#efa18d",
      "#787464",
      "#cc7e63",
      "#724e58",
      "#4b565b"
    ]
  },
  {
    name: "dark",
    background: "#333",
    theme: [
      "#dd6b66",
      "#759aa0",
      "#e69d87",
      "#8dc1a9",
      "#ea7e53",
      "#eedd78",
      "#73a373",
      "#73b9bc",
      "#7289ab",
      "#91ca8c",
      "#f49f42"
    ]
  },
  {
    name: "westeros",
    background: "transparent",
    theme: ["#516b91", "#59c4e6", "#edafda", "#93b7e3", "#a5e7f0", "#cbb0e3"]
  },
  {
    name: "essos",
    background: "rgba(242,234,191,0.15)",
    theme: ["#893448", "#d95850", "#eb8146", "#ffb248", "#f2d643", "#ebdba4"]
  },
  {
    name: "wonderland",
    background: "transparent",
    theme: ["#4ea397", "#22c3aa", "#7bd9a5", "#d0648a", "#f58db2", "#f2b3c9"]
  },
  {
    name: "walden",
    background: "rgba(252,252,252,0)",
    theme: ["#3fb1e3", "#6be6c1", "#626c91", "#a0a7e6", "#c4ebad", "#96dee8"]
  },
  {
    name: "chalk",
    background: "#293441",
    theme: ["#fc97af", "#87f7cf", "#f7f494", "#72ccff", "#f7c5a0", "#d4a4eb", "#d2f5a6", "#76f2f2"]
  },
  {
    name: "infographic",
    background: "transparent",
    theme: [
      "#C1232B",
      "#27727B",
      "#FCCE10",
      "#E87C25",
      "#B5C334",
      "#FE8463",
      "#9BCA63",
      "#FAD860",
      "#F3A43B",
      "#60C0DD",
      "#D7504B",
      "#C6E579",
      "#F4E001",
      "#F0805A",
      "#26C0C0"
    ]
  },
  {
    name: "macarons",
    background: "transparent",
    theme: [
      "#2ec7c9",
      "#b6a2de",
      "#5ab1ef",
      "#ffb980",
      "#d87a80",
      "#8d98b3",
      "#e5cf0d",
      "#97b552",
      "#95706d",
      "#dc69aa",
      "#07a2a4",
      "#9a7fd1",
      "#588dd5",
      "#f5994e",
      "#c05050",
      "#59678c",
      "#c9ab00",
      "#7eb00a",
      "#6f5553",
      "#c14089"
    ]
  },
  {
    name: "roma",
    background: "transparent",
    theme: [
      "#E01F54",
      "#001852",
      "#f5e8c8",
      "#b8d2c7",
      "#c6b38e",
      "#a4d8c2",
      "#f3d999",
      "#d3758f",
      "#dcc392",
      "#2e4783",
      "#82b6e9",
      "#ff6347",
      "#a092f1",
      "#0a915d",
      "#eaf889",
      "#6699FF",
      "#ff6666",
      "#3cb371",
      "#d5b158",
      "#38b6b6"
    ]
  },
  {
    name: "shine",
    background: "transparent",
    theme: ["#c12e34", "#e6b600", "#0098d9", "#2b821d", "#005eaa", "#339ca8", "#cda819", "#32a487"]
  },
  {
    name: "purple-passion",
    background: "rgba(91,92,110,1)",
    theme: ["#8a7ca8", "#e098c7", "#8fd3e8", "#71669e", "#cc70af", "#7cb4cc"]
  }
]

在setting.vue中引入themeStore和echartTheme.ts

<template>
  <div class="echarts-theme">
    <baseTitle title="主题方案" toolContent="用于设置所有图表的主题" />
    <el-row :gutter="20">
      <el-col :span="12" v-for="item in echartsThemeData" :key="item.name">
        <div class="echarts-theme-item-group" @click="handleClick(item.theme)">
          <div
            class="echarts-theme-item-color"
            :style="{ backgroundColor: sItem }"
            v-for="sItem in item.theme"
            :key="sItem"
          />
        </div>
      </el-col>
    </el-row>
  </div>
</template>
<script setup lang="ts">
import baseTitle from "./baseTitle.vue"
import { echartsThemeData } from "@/config/echartTheme"
import { useThemeStore } from "@/store/modules/themeStore"
const themeStore = useThemeStore()
const handleClick = (theme: Array<string>) => {
  themeStore.updateCurrentColorByArray(theme)
}
</script>
<style lang="scss" scoped>
.echarts-theme-item-group {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  width: auto;
  height: 32px;
  padding: 5px;
  margin-bottom: 8px;
  overflow: hidden;
  cursor: pointer;
  border: 1px solid #eee;
  border-radius: 4px;
}

.echarts-theme-item-color {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin-right: 2px;
  margin-bottom: 10px;
  margin-left: 2px;
  border-radius: 3px;
}
</style>

在echarts.vue中监听currentColorArray变化,重新去设置图表主题即可

...
   watch(
      () => themeStore.currentColorArray,
      (nVal) => {
        currentOptions.value.color = nVal
        setOptions(currentOptions.value)
      }
    )
...

自定义颜色跟新图表主题

当我准备提交代码,关机下班的时候。产品突然说,用户再增加个根据颜色来生成图表的主题,而不是预设的主题。这个时候,我心里真的有1W只草泥马在奔腾。你一个图表目的不就是为了看数据展示吗?搞这么多花里胡哨的干嘛捏?

吐槽归吐槽,班还是要上的,先做个基础布局吧。


tvision-color

根据某个色阶来生成主题,我们可以通过 tvision-color进行操作。 在utils/color.ts

export const getColorArray = (hex: string) => {
  const { colors: newPalette, primary: brandColorIndex } = Color.getColorGradations({
    colors: [hex],
    step: 10,
    remainInput: false // 是否保留输入 不保留会矫正不合适的主题色
  })[0]
  return {
    newPalette,
    brandColorIndex
  }
}

getColorArray方法会返回根据这个色阶返回一系列的相关颜色的数据,其中brandColorIndex为这个色阶的主色。 在themeStore中添加

...
 // 根据颜色更新当前颜色组
  const updateCurrentColorArray = (color: string) => {
    const { newPalette, brandColorIndex } = getColorArray(color)
    const firstColor = newPalette[0]
    const primaryColor = newPalette[brandColorIndex]
    newPalette[0] = primaryColor
    newPalette[brandColorIndex] = firstColor
    currentColorArray.value = newPalette
  }
  return {
    updateCurrentColorArray,
    updateCurrentColorByArray,
  }
  ...

在业务中customColor.vue中调用

<template>
  <div class="customColor">
    <baseTitle title="主题色" />
    <div class="customColor-list">
      <div
        class="customColor-item"
        v-for="item in colorList"
        :key="item"
        :style="{ backgroundColor: item }"
        @click="handleClick(item)"
      >
        <el-icon v-if="currentValue === item"><Check /></el-icon>
      </div>
      <el-color-picker v-model="color1" @change="customColor" />
    </div>
  </div>
</template>
<script setup lang="ts">
import baseTitle from "./baseTitle.vue"
import { ref } from "vue"
const colorList = ref(["#409EFF", "#007BA7", "#212121", "#11A983", "#13C2C2", "#6959CD", "#FF6B6B", "#87CEEB"])
const emits = defineEmits(["change"])
const currentValue = ref()
const color1 = ref()
const handleClick = (item: string) => {
  currentValue.value = item
  emits("change", item)
}
const customColor = (item: string | null) => {
  if (item) {
    handleClick(item)
  }
}
</script>
<style scoped lang="scss">
@import "@/assets/mixins/box-center";

.customColor-list {
  @include box-center(space-between);

  .customColor-item {
    width: 30px;
    height: 30px;
    font-size: 18px;
    color: #fff;
    cursor: pointer;
    border-radius: 50%;
    @include box-center;
  }
}
</style>



总结

在这过程中,我们使用了Vue3和TS中使用Echart实现一键换肤和根据颜色生成图表主题的功能。通过封装useEchartHook来渲染图表,并使用tvision-color库根据色阶生成颜色组来更新主题。最终实现了用户可以根据自定义颜色来展示图表数据的需求。

相关推荐

5分钟搭建公网https网页文件服务器,免费权威TLS证书

请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习前言本文主要讲解如何快速搭建一个https网页文件服务器,并免费申请权威机构颁发的tls证...

nginx负载均衡配置(nginx负载均衡配置两个程序副本)

Nginx是什么没有听过Nginx?那么一定听过它的“同行”Apache吧!Nginx同Apache一样都是一种WEB服务器。基于REST架构风格,以统一资源描述符(UniformResources...

19《Nginx 入门教程》Nginx综合实践

今天我们将基于Nginx完成两个比较有用的场景,但是用到的Nginx的配置非常简单。内部Yum源搭建内部Pip源搭建1.实验环境ceph1centos7.6内网ip:172.16....

Nginx性能调优与优化指南(nginx优化配置大全)

Nginx性能调优需要结合服务器硬件资源、业务场景和负载特征进行针对性优化。以下是一些关键优化方向和具体配置示例:一、Nginx配置优化1.进程与连接数优化nginxworker_process...

C++后端开发必须彻底搞懂Nginx,从原理到实战(高级篇)

本文为Nginx实操高级篇。通过配置Nginx配置文件,实现正向代理、反向代理、负载均衡、Nginx缓存、动静分离和高可用Nginx6种功能,并对Nginx的原理作进一步的解析。当需...

【Nginx】史上最全的Nginx配置详解

Nginx服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里,http块又包括http全局块和server块。Nginx是非常重要的负载均衡中间件,被广泛应用于大型...

【Nginx】Nginx 4种常见配置实例(nginx基本配置与参数说明)

本文主要介绍nginx4种常见的配置实例。Nginx实现反向代理;Nginx实现负载均衡;Nginx实现动静分离;Nginx实现高可用集群;Nginx4种常见配置实例如下:一、Nginx反向代理配...

使用nginx+allure管理自动化测试报告

allure在自动化测试中经常用来生成漂亮的报告,但是网上及官网上给出的例子都仅仅是针对单个测试用例文件的形式介绍的,实际使用中,自动化测试往往需要包含不止一个产品或项目,本文介绍如何使用nginx+...

nginx配置文件详解(nginx配置文件详解高清版)

Nginx是一个强大的免费开源的HTTP服务器和反向代理服务器。在Web开发项目中,nginx常用作为静态文件服务器处理静态文件,并负责将动态请求转发至应用服务器(如Django,Flask,et...

SpringCloud Eureka-服务注册与发现

1.Eureka介绍1.1学习Eureka前的说明目前主流的服务注册&发现的组件是Nacos,但是Eureka作为老牌经典的服务注册&发现技术还是有必要学习一下,原因:(1)一些早期的分布式微服...

微服务 Spring Cloud 实战 Eureka+Gateway+Feign+Hystrix

前言我所在项目组刚接到一个微服务改造需求,技术选型为SpringCloud,具体需求是把部分项目使用SpringCloud技术进行重构。本篇文章中介绍了Eureka、Gateway、Fe...

深度剖析 Spring Cloud Eureka 底层实现原理

你作为一名互联网大厂后端技术开发人员,在构建分布式系统时,是不是常常为服务的注册与发现而头疼?你是否好奇,像SpringCloudEureka这样被广泛使用的组件,它的底层实现原理到底是怎样的...

热爱生活,喜欢折腾。(很热爱生活)

原文是stackoverflow的一则高票回答,原文链接可能之前也有人翻译过,但是刚好自己也有疑惑,所以搬运一下,个人水平有限所以可能翻译存在误差,欢迎指正(如侵删)。尽管classmethod和st...

GDB调试的高级技巧(详细描述gdb调试程序的全过程)

GDB是我们平时调试c/c++程序的利器,查起复杂的bug问题,比打印大法要好得多,但是也不得不说,gdb在默认情况下用起来并不是很好用,最近学习到几个高级点的技巧,分享下:一美化打印先上个例子...

Arduino 实例(二十三)Arduino 给Python 编译器发送信息

1首先Python需要安装Pyserial库,在命令提示符中输入pipintallpyserial若是遇到提示‘pip‘不是内部或外部命令,也不是可运行的程序或批处理文件,则需要设置环境变...