前言
在现代数据可视化领域,3D 地图飞线效果是一种非常吸引人的展示方式,特别适合展示地理空间关系和数据流动。本文将详细解析如何使用 ECharts GL 在 Vue 项目中实现一个 3D 中国地图飞线效果。
技术栈
Vue.js 2.x/3.x
ECharts 5.x
ECharts GL 2.x
核心实现步骤
1. 准备工作
首先需要安装必要的依赖:
npm install echarts echarts-gl --save
2. 基础地图配置
import * as echarts from 'echarts'
import "echarts-gl";
import chinaJson from '@/utils/chinaOutline.json'export default {mounted() {this.initChart()},methods: {initChart() {const dom = this.$refs.chartRef;this.myChart = echarts.init(dom);echarts.registerMap('china', chinaJson);// ...其他配置}}
}
3. 数据处理
我们需要准备两类数据:
城市点位数据 - 用于在地图上显示城市位置
飞线数据 - 用于显示从起点到各城市的连线
const FROMCITY = [113.28064, 23.125177] // 起点坐标(深圳)
const FROMCITYCOORD = [113.28064, 23.125177]// 处理飞线数据
const linesData = this.cityList.map(city => ({fromName: FROMCITY,toName: city.city,coords: [[FROMCITYCOORD[0], FROMCITYCOORD[1], 1], [city.provinceCapitalX, city.provinceCapitalY, 1]],
}));// 处理散点数据
const scatterData = this.cityList.map(city => ({name: city.city.replace('市', ''),value: [city.provinceCapitalX, city.provinceCapitalY, 1],
}));
4. 3D 地图核心配置
geo3D: {map: 'china',regionHeight: 8, // 区域高度itemStyle: {color: 'RGBA(153, 249, 235, 1)', // 地图基础颜色borderWidth: 1.5},viewControl: {distance: 110, // 观察距离alpha: 60, // 上下旋转角度beta: 0 // 左右旋转角度},// ...其他配置
}
5. 飞线系列配置
{type: 'lines3D',effect: {show: true,period: 4, // 动画周期trailWidth: 4, // 尾迹宽度symbol: 'arrow', // 箭头符号color: 'rgba(255,255,255, 1)'},lineStyle: {width: 1.5,color: '#1AD9FF', // 飞线颜色opacity: 0.8},data: linesData // 飞线数据
}
6. 城市点位配置
{type: 'scatter3D',symbol: 'circle',symbolSize: 14,label: {show: true,formatter: '{b}', // 显示城市名称color: '#FFF'},itemStyle: {color: '#FFA601' // 点颜色},data: scatterData // 散点数据
}
完整代码解析
setChartInit() {const dom = this.$refs.chartRef;this.myChart = this.myChart || echarts.init(dom);// 注册地图echarts.registerMap('china', chinaJson);// 准备数据const linesData = this.cityList.map(city => ({fromName: FROMCITY,toName: city.city,coords: [[FROMCITYCOORD[0], FROMCITYCOORD[1], 1], [city.provinceCapitalX, city.provinceCapitalY, 1]],}));const scatterData = this.cityList.map(city => ({name: city.city.replace('市', ''),value: [city.provinceCapitalX, city.provinceCapitalY, 1],}));// 配置项const option = {// 3D地图配置geo3D: {map: 'china',regionHeight: 8,// ...其他geo3D配置},series: [// 飞线系列{type: 'lines3D',// ...飞线配置data: linesData},// 点位系列{type: 'scatter3D',// ...点位配置data: scatterData}]};this.myChart.setOption(option);
}
完整代码
<template><div class="chartRef" ref="chartRef" style="height: 100%;width: 100%" />
</template>
<script>import * as echarts from 'echarts'
import '@/utils/chinaMap'
import "echarts-gl";
import chinaJson from '@/utils/chinaOutline.json'const FROMCITY = [113.28064, 23.125177]
const FROMCITYCOORD = [113.28064, 23.125177]export default {name: 'Demo',data() {return {cityList:[{"id": 0,"city": "绍兴市","provinceCapitalX": "120.15358","provinceCapitalY": "30.287458","num": 200},{"id": 1,"city": "北京市","provinceCapitalX": "116.405289","provinceCapitalY": "39.904987","num": 200},{"id": 2,"city": "嘉兴市","provinceCapitalX": "120.15358","provinceCapitalY": "30.287458","num": 200},{"id": 3,"city": "锦州市","provinceCapitalX": "118.76741","provinceCapitalY": "41.796768","num": 200},{"id": 4,"city": "临沂市","provinceCapitalX": "120.15358","provinceCapitalY": "30.287458","num": 200},{"id": 5,"city": "深圳市","provinceCapitalX": "113.28064","provinceCapitalY": "23.125177","num": 200}
],}},mounted() {this.getData()},watch: {},methods: {// 地图组件初始加载setChartInit() {const dom = this.$refs.chartRef;this.myChart = this.myChart || echarts.init(dom);echarts.registerMap('china', chinaJson);const linesData = this.cityList.map(city => ({fromName: FROMCITY,toName: city.city,coords: [[FROMCITYCOORD[0], FROMCITYCOORD[1], 1], [city.provinceCapitalX, city.provinceCapitalY, 1]],}));const scatterData = this.cityList.map(city => ({name: city.city.replace('市', ''),value: [city.provinceCapitalX, city.provinceCapitalY, 1],}));const option = {tooltip: {trigger: 'axis',axisPointer: {type: 'shadow'}},backgroundColor: 'transparent',geo3D: {zlevel: 1,type: 'geo3D',coordinateSystem: 'geo3D',map: 'china',regionHeight: 8,roam: false,silent: false, select: {disabled: false},itemStyle: {borderColor: 'RGBA(37, 182, 144, 0)',color: 'RGBA(153, 249, 235, 1)',borderWidth: 1.5},shading: "realistic",realisticMaterial: {detailTexture: "./bg.png",textureTiling: 1,blendMode: 'Additive', // 可选值:Additive / Subtractive / Multiply 等},light: {main: {intensity: 1.2,shadow: true,shadowQuality: 'high'},ambient: {intensity: 0.3}},viewControl: {distance: 110,alpha: 60,beta: 0,autoRotate: false,rotateSensitivity: 1,zoomSensitivity: 1,panSensitivity: 1},emphasis: {label: {show: true,color: 'RGBA(255, 255, 255, 1)',fontSize: 14,},itemStyle: {color: 'RGBA(255, 255, 255, 1)',borderWidth: 4,borderColor: "RGBA(255,255,255, 1)",regionHeight: 25,opacity: 1,shadowColor: 'RGBA(153, 249, 235, 1)'}},},series: [// 飞线系列{type: 'lines3D',coordinateSystem: 'geo3D',zlevel: 2,silent: true,effect: {show: true,period: 4,trailWidth: 4,trailLength: 0.4,symbol: 'arrow',symbolSize: 16,color: 'rgba(255,255,255, 1)'},lineStyle: {width: 1.5,color: '#1AD9FF',opacity: 0.8},data: linesData},// 点位系列{type: 'scatter3D',coordinateSystem: 'geo3D',zlevel: 3,symbol: 'circle',symbolSize: 14,silent: false,label: {show: true,position: 'right',formatter: '{b}',textStyle: {color: '#FFF',fontSize: 14}},itemStyle: {color: '#FFA601'},emphasis: {label: {show: false},itemStyle: {color: '#1AD9FF'}},data: scatterData}]}this.myChart.setOption(option);}}
}
</script><style scoped lang="scss"></style>
效果优化技巧
动画效果:通过调整
effect.period
可以改变飞线动画速度视觉层次:使用
zlevel
控制不同图层的叠加顺序光照效果:调整
light
配置可以改变地图的明暗效果交互体验:配置
viewControl
可以控制地图的旋转、缩放等交互行为
常见问题解决
地图不显示:
确保正确注册了地图 JSON 数据
检查容器是否有固定宽高
飞线不显示:
检查坐标数据格式是否正确
确保 lines3D 系列被正确添加到 series 中
性能问题:
数据量过大时考虑简化或聚合数据
使用
silent: true
减少不必要的交互检测
总结
通过 ECharts GL 实现 3D 地图飞线效果,可以为地理空间数据提供更加直观的展示方式。本文详细介绍了从数据准备到最终实现的完整流程,以及各种配置项的用途和优化技巧。这种可视化方式特别适合展示城市间的关联关系、物流路线、人口迁移等场景。
希望这篇技术解析能帮助你在项目中实现类似的效果。如果有任何问题,欢迎在评论区讨论。