nuxt3使用echarts5渲染中国地图
2024-1-23
·
hexWers

nuxt是vue的全栈框架,需求是引入echart,并渲染中国地图

在nuxt3环境已经搭建的情况下,我使用了tailwindcss,配置过程省略

导入包

导入包echartsvue-echarts

npm install echarts vue-echarts

大部分情况只导入vue-echarts就可以了,如果有交互组件再导入echarts

修改nuxt配置文件

目的是将echarts代码转译成向后兼容的旧版本代码,确保代码可以在多种浏览器运行

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  ssr: false,
  devtools: { enabled: true },

  modules: ["@nuxtjs/tailwindcss", "nuxt-icons"],

  build: {
    transpile: [/echarts/],
  }
})

插件

插件的形式是为了方便全局引入echarts,当然,也可以不用插件导入import * as echarts from "echarts";,只是打包体积会异常的大罢了

import { use } from 'echarts/core';

// import ECharts modules manually to reduce bundle size
import { CanvasRenderer } from 'echarts/renderers';
import { BarChart } from 'echarts/charts';
import { GridComponent, TooltipComponent } from 'echarts/components';

export default defineNuxtPlugin(() => {
    use([CanvasRenderer, BarChart, GridComponent, TooltipComponent]);
});

或者可以全部引入

import * as echarts from 'echarts';

export default defineNuxtPlugin((nuxtApp) => {
    nuxtApp.vueApp.config.globalProperties.$echarts = echarts
});

nuxtApp.vueApp.config.globalProperties.$echarts = echarts意思是将 echarts 对象挂载到全局属性上,这样就可以在任何 Vue 组件中通过 this.$echarts 来访问 echarts 对象,而无需重复引入

通过这种方式,你可以在整个 Vue 应用中方便地使用 echarts 对象,而不必在每个组件中都导入和配置一次。

nuxtApp 是 Nuxt.js 应用的实例,nuxtApp.vueApp 是 Vue 应用的实例

config.globalProperties 是 Vue 3 中的属性,它允许我们定义在所有组件实例中可用的全局属性或方法。这样定义的属性或方法可以在任何组件中使用,而不需要单独导入或声明

China地图文件

在echarts4中内置,但是由于一些原因在echarts5中去除,所以需要下载

一般来说,直接用XXX.json就可以了,例如本文就只下载了china.json,按需下载即可

china.json放入assets文件夹中,通过import chinaJson from '@/assets/china.json'的方式引入

示例

<template>
    <div class="h-screen w-screen">
        <div class="h-full w-full" id="china-map"></div>
    </div>
</template>

<script>
import chinaJson from '@/assets/china.json'

export default {
    mounted() {
        this.initEcharts();
    },
    methods: {

        async initEcharts() {
            // 注册geojson
            this.$echarts.registerMap('china', chinaJson);

            const option = {
                title: {
                    text: 'aaa)',
                    subtext: 'ggg',
                    sublink: 'http://www.census.gov/popest/data/datasets.html',
                    left: 'right'
                },
                tooltip: {
                    trigger: 'item',
                    showDelay: 0,
                    transitionDuration: 0.2
                },
                visualMap: {
                    left: 'right',
                    min: 500000,
                    max: 38000000,
                    inRange: {
                        color: [
                            '#313695',
                            '#4575b4',
                            '#74add1',
                            '#abd9e9',
                            '#e0f3f8',
                            '#ffffbf',
                            '#fee090',
                            '#fdae61',
                            '#f46d43',
                            '#d73027',
                            '#a50026'
                        ]
                    },
                    text: ['High', 'Low'],
                    calculable: true
                },
                toolbox: {
                    show: true,
                    //orient: 'vertical',
                    left: 'left',
                    top: 'top',
                    feature: {
                        dataView: { readOnly: false },
                        restore: {},
                        saveAsImage: {}
                    }
                },
                series: [
                    {
                        name: '中国',
                        type: 'map',
                        roam: true,
                        map: 'china',
                        emphasis: {
                            label: {
                                show: true
                            }
                        },
                        data: [
                            { name: '山东', value: 4822023 },
                            { name: '山西', value: 731449 },
                            { name: '河南', value: 6553255 },
                            { name: '河北', value: 2949131 },
                            { name: '陕西', value: 38041430 },
                            { name: '广东', value: 5187582 },
                            { name: '福建', value: 3590347 },
                            { name: '浙江', value: 917092 },
                            { name: '甘肃', value: 632323 },
                            { name: '吉林', value: 19317568 },
                            { name: '新疆', value: 9919945 },
                            { name: '内蒙古', value: 1392313 },
                        ]
                    }
                ]
            };

            const myChart = this.$echarts.init(document.getElementById("china-map"));// 图标初始化
            myChart.setOption(option);
            window.addEventListener("resize", () => {
                myChart.resize();
            });
        },

    }
};
</script>

打包体积相差不大

实测用插件打包和直接import * as echarts from "echarts";打包都是3M多,差距不大,原因大致是现代的打包工具进行tree shaking(指在打包过程中通过静态代码分析的方式去除未被使用的代码)和代码分割,对于重复的模块尽可能只打包一次

GEOJSON画图原理

简单说就是一组json文件,里面可以指定很多的类型和坐标,和svg类似

例如:

{
    "type": "Point",
    "coordinates": [30, 10]
}

就是一个点,其他类型可能是多个点MultiPoint,多个线条MultiLineString,多个面MultiPolygon等等

地图主要是由MultiPolygon组成,一个一个省份或许就是一个面,多个面组成就是中国地图了


参考: