完美封装Echarts【分层结构】

前言:ECharts,一个使用JavaScript实现的开源可视化库。

一、什么是数据可视化?

什么是数据可视化呢?

1.为了清晰有效地传递信息,数据可视化使用统计图形、图表、信息图表和其他工具;
2. 可以使用点、线或条,对数字数据进行编码;
3.数据可视化让我们可以更加清晰的去认识、理解、表达数据;

Echarts
Echarts

前端可视化的工具

1.常见的框架: ECharts 、g2、d3、vis、hightChart等等;
2.g2框架封装:bizcharts(react) viser(vue);
3.地理可视化: g2、L7、高德的 Loca、 菜鸟的 鸟图;
4.3D可视化:three.js;

认识ECharts

什么是ECharts呢?官方的解释是:一个基于 JavaScript 的开源可视化图表库;

ECharts的历史:

  • ECharts由百度团队开源;
  • 2018年初,捐赠给Apache基金会,成为ASF(Apache Software Foundation,简称为ASF,Apache软件基金会)孵化级项目;
  • 2021年1月26日晚,Apache基金会官方宣布 ECharts项目正式毕业,成为Apache顶级项目;
  • 2021年1月28日,ECharts 5线上发布会举行;

ECharts的特点:

  • 丰富的图表类型:提供开箱即用的 20 多种图表和十几种组件,并且支持各种图表以及组件的任意组合;
  • 强劲的渲染引擎:Canvas、SVG 双引擎一键切换,增量渲染、流加载等技术实现千万级数据的流畅交互;
  • 专业的数据分析:通过数据集管理数据,支持数据过滤、聚类、回归,帮助实现同一份数据的多维度分析;
  • 优雅的可视化设计:默认设计遵从可视化原则,支持响应式设计,并且提供了灵活的配置项方便开发者定制;
  • 健康的开源社区:活跃的社区用户保证了项目的健康发展,也贡献了丰富的第三方插件满足不同场景的需求;
  • 友好的无障碍访问:智能生成的图表描述和贴花图案,帮助视力障碍人士了解图表内容,读懂图表背后的故事;

二、使用Echarts的步骤

第一步:我们可以通过以下方式获取ECharts:

  • 从 Apache ECharts 官网下载界面 获取官方源码包后构建;
  • 在 ECharts 的 GitHub 获取;
  • 通过 npm 获取 echarts,npm install echarts --save;
  • 通过 jsDelivr 等 CDN 引入;

第二步:引入Echarts

可以通过不同的方式引入

第三步:初始化Echarts对象,并且设置配置进行绘制

1.通过echarts.init(dom, theme, options)初始化;
2.通过setOption方法设置绘制的数据;

三、ECharts配置信息

option = {
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [820, 932, 901, 934, 1290, 1330, 1320],
      type: 'line',
      areaStyle: {}
    }
  ]
};

四、Echarts的渲染模式

1.通常在渲染图表是我们会选择 SVG或者canvas进行渲染:

  • 通常情况下,这两种渲染模式是比较相近的,并且是可以相互替换的;
  • 但是在一些场景中,它们的表现和能力有一定的差异;
  • 对于它们之间的取舍,一直是没有一个明确、标准的答案的,也是一个经常被拿到讨论的话题;

2.ECharts最初采用的是canvas绘制图表,从ECharts4.x开始,发布了SVG渲染器,提供了另外的一种选择。

3.那么它们之间到底如何选择呢?

  • 一般来说,Canvas 更适合绘制图形元素数量非常大(这一般是由数据量大导致)的图表(如热力图、地理坐标 系或平行坐标系上的大规模线图或散点图等),也利于实现某些视觉特效;
  • 但是,在不少场景中,SVG 具有重要的优势:它的内存占用更低(这对移动端尤其重要)、渲染性能略高、并
    且用户使用浏览器内置的缩放功能时不会模糊;

4.ECharts在不同的设备上,进行了性能的测试:

  • 从图片来看,在这些场景中,SVG 渲染器相比 Canvas 渲染器在移动端的总体表现更好;
  • 当然,这个实验并非是全面的评测,在另一些数据量较大或者有图表交互动画的场景中,目前的 SVG 渲染器的性能还比不过 Canvas 渲染器;
    Echarts
    5.那么到底选择哪一个渲染器呢?
  • 在软硬件环境较好,数据量不大的场景下(例如 PC 端做商务报表),两种渲染器都可以适用,并不需要太多纠结;
  • 在环境较差,出现性能问题需要优化的场景下,可以通过试验来确定使用哪种渲染器;
  • 比如在须要创建很多 ECharts 实例且浏览器易崩溃的情况下(可能是因为 Canvas 数量多导致内存占用超出手
    机承受能力),可以使用 SVG 渲染器来进行改善;
  • 大略的说,如果图表运行在低端安卓机,或者我们在使用一些特定图表如 水球图等,SVG 渲染器可能效果更好; p数据量很大、较多交互时,可以选用 Canvas 渲染器;

建议:因为Echarts里面的配置太多了,建议使用的时候先去查看案例,然后删删改改,回头查看配置文档。

五、Vue使用Echarts

实现组件化,工程化项目 => 使用分层结构,我辈义不容辞。
在这里插入图片描述
这里代码展示从顶层封装 => 页面展示

1.useEchart.ts

import * as Echarts from 'echarts'
// 获取中国地图数据
import chinaMapData from '../data/china.json'
Echarts.registerMap('china', chinaMapData)

// 封装Echarts的顶级hooks,新添加相关的逻辑很方便
export default function (el: HTMLElement) {
    // 1.创建Echarts实例
    const echartInstance = Echarts.init(el)

    // 2.把option创建好
    const setOption = (option: Echarts.EChartsOption) => {
        echartInstance.setOption(option)
    }

    // 3.调用Echarts实例来适配echarts大小
    window.addEventListener('resize', () => {
        echartInstance.resize()
    })

    // 4.把函数放出去,比如折叠菜单时,调用,echarts就会适配
    const updataSize = () => {
        echartInstance.resize()
    }

    return { setOption, updataSize }
}

2.base-echart.vue

<template>
    <div class="base-echart">
        <div ref="echartDivRef" :style="{ width: width, height: height }"></div>
    </div>
</template>

<script lang="ts" setup>
// 使用setup最新版
import { ref, onMounted, withDefaults, defineProps, watchEffect } from 'vue'
import { EChartsOption } from 'echarts'
import useEchart from '../hooks/useEchart'

// 定义prpos
const props = withDefaults(
    defineProps<{
        option: EChartsOption
        width?: string
        height?: string
    }>(),
    {
        width: '100%',
        height: '360px'
    }
)

const echartDivRef = ref<HTMLElement>()

onMounted(() => {
    const { setOption } = useEchart(echartDivRef.value!)
    watchEffect(() => {
        setOption(props.option)
    })
    // const echartInstance = echarts.init(echartDivRef.value!)
    // echartInstance.setOption(props.option)
})
</script>

<style lang="less" scoped></style>

3.bar-echart.vue(这里就写一个柱状图封装哈)

<template>
    <div class="bar-echart">
        <base-echart :option="option"></base-echart>
    </div>
</template>

<script setup lang="ts">
import { computed, defineProps, withDefaults } from 'vue'
import * as echarts from 'echarts'
import baseEchart from '@/base-ui/echart/index'

const props = withDefaults(
    defineProps<{
        title?: string
        xLabels: string[]
        values: any[]
    }>(),
    {
        title: '这是一个柱状图'
    }
)

const option = computed(() => {
    return {
        title: {
            text: '特性示例:渐变色 阴影 点击缩放',
            subtext: 'Feature Sample: Gradient Color, Shadow, Click Zoom'
        },
        xAxis: {
            data: props.xLabels,
            axisLabel: {
                inside: true,
                color: '#fff'
            },
            axisTick: {
                show: false
            },
            axisLine: {
                show: false
            },
            z: 10
        },
        yAxis: {
            axisLine: {
                show: false
            },
            axisTick: {
                show: false
            },
            axisLabel: {
                color: '#999'
            }
        },
        dataZoom: [
            {
                type: 'inside'
            }
        ],
        series: [
            {
                type: 'bar',
                showBackground: true,
                itemStyle: {
                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                        { offset: 0, color: '#83bff6' },
                        { offset: 0.5, color: '#188df0' },
                        { offset: 1, color: '#188df0' }
                    ])
                },
                emphasis: {
                    itemStyle: {
                        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                            { offset: 0, color: '#2378f7' },
                            { offset: 0.7, color: '#2378f7' },
                            { offset: 1, color: '#83bff6' }
                        ])
                    }
                },
                data: props.values
            }
        ]
    }
})
</script>

<style lang="less" scoped></style>

4.dashboard.vue(页面使用)

<template>
    <div class="dashboard">
        <el-row :gutter="10">
            <el-col :span="7">
                <hy-card title="分类商品数量(饼图)">
                    <pie-echart :pieData="categoryGoodsCount"></pie-echart>
                </hy-card>
            </el-col>
            <el-col :span="10">
                <hy-card title="不同城市商品销量">
                    <map-echart :mapData="addressGoodsSale"></map-echart>
                </hy-card>
            </el-col>
            <el-col :span="7">
                <hy-card title="分类商品数量(玫瑰图)">
                    <rose-echart :roseData="categoryGoodsCount"></rose-echart>
                </hy-card>
            </el-col>
        </el-row>

        <el-row :gutter="10" class="content-row">
            <el-col :span="12">
                <hy-card title="分类商品的销量">
                    <line-echart v-bind="categoryGoodsSale"></line-echart>
                </hy-card>
            </el-col>
            <el-col :span="12">
                <hy-card title="分类商品的收藏">
                    <bar-echart v-bind="categoryGoodsFavor"></bar-echart>
                </hy-card>
            </el-col>
        </el-row>
    </div>
</template>

<script lang="ts">
import { defineComponent, ref, onMounted, computed } from 'vue'
import { useStore } from '@/store'
import {
    PieEchart,
    roseEchart,
    lineEchart,
    barEchart,
    mapEchart
} from '@/components/page-echarts'

import HyCard from '@/base-ui/card/index'

export default defineComponent({
    name: 'dashboard',
    components: {
        HyCard,
        PieEchart,
        roseEchart,
        lineEchart,
        barEchart,
        mapEchart
    },
    setup() {
        const store = useStore()

        // 请求数据
        store.dispatch('dashboard/getDashboardDataAction')

        // 获取数据
        // 饼图
        const categoryGoodsCount = computed(() => {
            return store.state.dashboard.categoryGoodsCount.map((item: any) => {
                return { name: item.name, value: item.goodsCount }
            })
        })
        // 折线图
        const categoryGoodsSale = computed(() => {
            const xLabels: string[] = []
            const values: any[] = []
            const categoryGoodsSale = store.state.dashboard.categoryGoodsSale
            for (const item of categoryGoodsSale) {
                xLabels.push(item.name)
                values.push(item.goodsCount)
            }
            return { xLabels, values }
        })
        // 柱形图数据
        const categoryGoodsFavor = computed(() => {
            const xLabels: string[] = []
            const values: any[] = []
            const categoryGoodsFavor = store.state.dashboard.categoryGoodsFavor
            for (const item of categoryGoodsFavor) {
                xLabels.push(item.name)
                values.push(item.goodsFavor)
            }
            return { xLabels, values }
        })
        return { categoryGoodsCount, categoryGoodsSale, categoryGoodsFavor }
    }
})
</script>

<style scoped>
.content-row {
    margin-top: 20px;
}
</style>

六、效果图

在这里插入图片描述

水平有限,还不能写到尽善尽美,希望大家多多交流,跟春野一同进步!!!

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 封装 Echarts 的方法: 1. 安装 Echarts 使用 npm 安装 Echarts: ``` npm install echarts --save ``` 2. 创建 Vue 组件 创建一个 Vue 组件,例如 `Echarts.vue`。 3. 引入 Echarts 在 `Echarts.vue` 中引入 Echarts: ``` import echarts from 'echarts' ``` 4. 初始化 Echarts 在 `mounted` 钩子函数中初始化 Echarts: ``` mounted() { this.initChart() }, methods: { initChart() { const container = this.$refs.container this.chart = echarts.init(container) } } ``` 5. 配置 Echarts 在 `initChart` 方法中配置 Echarts: ``` initChart() { const container = this.$refs.container this.chart = echarts.init(container) const option = { // 配置项 } this.chart.setOption(option) } ``` 6. 监听组件大小变化 为了保证 Echarts 图表在组件大小变化时能够自适应,需要监听组件大小变化,并重新渲染 Echarts 图表。 ``` mounted() { this.initChart() window.addEventListener('resize', this.resizeHandler) }, beforeDestroy() { window.removeEventListener('resize', this.resizeHandler) }, methods: { resizeHandler() { this.chart.resize() } } ``` 7. 封装成可复用的组件 将以上步骤封装成一个可复用的 Vue 组件,供其他组件使用。例如: ``` <template> <div ref="container" style="width: 100%; height: 300px;"></div> </template> <script> import echarts from 'echarts' export default { name: 'Echarts', props: { option: { type: Object, required: true } }, mounted() { this.initChart() window.addEventListener('resize', this.resizeHandler) }, beforeDestroy() { window.removeEventListener('resize', this.resizeHandler) }, methods: { initChart() { const container = this.$refs.container this.chart = echarts.init(container) this.chart.setOption(this.option) }, resizeHandler() { this.chart.resize() } } } </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值