一、项目背景
在数据可视化中,地图可视化是一种非常直观且富有表现力的方式。ECharts作为一款强大的可视化库,提供了丰富的地图功能。今天,我们将通过一个完整的示例,展示如何使用ECharts实现中国地图的点动画和线动画效果,让你的可视化项目更具吸引力!
二、技术栈
-
ECharts:用于地图绘制和动画效果实现。
-
Vue.js:作为前端框架,方便组件化开发和数据绑定。
三、地图基础配置
首先,我们需要一个基本的地图配置,展示中国地图的轮廓和一些基础样式。以下是代码示例:
<template>
<div ref="chartsRef" />
</template>
<script setup>
import * as echarts from 'echarts'
import { ref, onMounted } from 'vue'
const chartsRef = ref(null)
// 地图基础配置
const options = {
tooltip: {
trigger: 'item',
},
geo: {
show: true,
map: 'china', // 使用中国地图
roam: true, // 允许缩放和拖动
zoom: 1, // 初始缩放比例
center: [101.4038, 36.8207], // 地图中心点经纬度
emphasis: {
show: false,
areaColor: '#389BB7', // 高亮区域颜色
borderWidth: 0
},
itemStyle: {
borderColor: 'rgba(147, 235, 248, 1)', // 区域边框颜色
borderWidth: 1,
}
},
series: [
{
type: 'map',
map: 'china',
geoIndex: 0,
aspectScale: 0.75, // 长宽比
showLegendSymbol: false, // 存在legend时显示
label: {
normal: {
show: false
},
textStyle: {
color: '#fff'
}
},
itemStyle: {
areaColor: '#031525', // 默认区域颜色
borderColor: '#FFFFFF' // 区域边框颜色
},
emphasis: {
areaColor: '#2B91B7' // 高亮区域颜色
},
animation: false // 禁用地图的动画效果
}
]
}
let chart = null
const initChart = () => {
chart = echarts.init(chartsRef.value) // 初始化 ECharts 实例
chart.setOption(options) // 设置地图配置
}
onMounted(() => {
initChart() // 初始化地图
})
</script>
四、地图点动画效果
1. 数据准备
const geoCoordMap = {
江苏: [118.8062, 31.9208],
//...网上有相关数据,自行查找
湖北: [112.29, 30.98]
}
const mapData = []
for (const key in geoCoordMap) {
mapData.push({
year: '湖北',
name: key,
})
}
2. 动画效果配置
const convertData = (data) => {
const res = []
for (let i = 0; i < data.length; i++) {
const geoCoord = geoCoordMap[data[i].name]
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value) // 将经纬度和数据值合并
})
}
}
return res
}
const pointOptions = {
series: [
{
type: 'effectScatter', // 使用 effectScatter 类型实现动态点效果
coordinateSystem: 'geo', // 指定坐标系为地理坐标系
data: convertData(
mapData
.sort((a, b) => b.value - a.value) // 按数据值降序排序
),
showEffectOn: 'render', // 在渲染时显示动画效果
rippleEffect: {
brushType: 'stroke' // 波纹效果类型
},
label: {
formatter: '{b}', // 显示地区名称
position: 'right', // 标签位置
show: true
},
itemStyle: {
color: '#f00', // 动态点的颜色
},
emphasis: {
scale: true // 高亮时放大
},
zlevel: 1 // 设置层级
}
]
}
五、地图线动画效果
最后,我们为地图添加动态的线,用于表示地区之间的流动关系。以下是实现代码:
1. 数据准备
const geoGpsMap = [112.29, 30.98] // 湖北省的经纬度,作为起点
2. 动画效果配置
const convertToLineData = (data, gps) => {
const res = []
for (let i = 0; i < data.length; i++) {
const dataItem = data[i]
const toCoord = geoCoordMap[dataItem.name] // 目标地区的经纬度
const fromCoord = gps // 起点经纬度,例如:湖北
if (fromCoord && toCoord) {
res.push([
{
coord: fromCoord,
},
{
coord: toCoord
}
])
}
}
return res
}
const lineOptions = {
series: [
{
type: 'lines', // 使用 lines 类型实现动态线效果
zlevel: 2, // 设置层级
effect: {
show: true, // 显示动画效果
period: 4, // 箭头指向速度,值越小速度越快
trailLength: 0.02, // 特效尾迹长度
symbol: 'arrow', // 箭头图标
symbolSize: 3 // 图标大小
},
lineStyle: {
color: '#f00', // 线的颜色
width: 0.1, // 线的宽度
opacity: 0.5, // 线的透明度
curveness: 0.3 // 线的曲直度
},
data: convertToLineData(mapData, geoGpsMap) // 动态线的数据
}
]
}
六、完整代码
以下是完整的代码实现,包括地图基础配置、点动画和线动画:
<template>
<div ref="chartsRef" />
</template>
<script setup>
import * as echarts from 'echarts'
import { ref, onMounted } from 'vue'
const chartsRef = ref(null)
// 地图基础配置
const options = {
tooltip: {
trigger: 'item',
},
geo: {
show: true,
map: 'china',
roam: true,
zoom: 1,
center: [101.4038, 36.8207],
emphasis: {
show: false,
areaColor: '#389BB7',
borderWidth: 0
},
itemStyle: {
borderColor: 'rgba(147, 235, 248, 1)',
borderWidth: 1,
}
},
series: [
{
type: 'map',
map: 'china',
geoIndex: 0,
aspectScale: 0.75,
showLegendSymbol: false,
label: {
normal: {
show: false
},
textStyle: {
color: '#fff'
}
},
roam: true,
itemStyle: {
areaColor: '#031525',
borderColor: '#FFFFFF'
},
emphasis: {
areaColor: '#2B91B7'
},
animation: false
}
]
}
// 地图点动画数据
const geoCoordMap = {
江苏: [118.8062, 31.9208],
湖北: [112.29, 30.98]
}
const mapData = []
for (const key in geoCoordMap) {
mapData.push({
year: '湖北',
name: key,
})
}
const convertData = (data) => {
const res = []
for (let i = 0; i < data.length; i++) {
const geoCoord = geoCoordMap[data[i].name]
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value)
})
}
}
return res
}
const pointOptions = {
series: [
{
type: 'effectScatter',
coordinateSystem: 'geo',
data: convertData(
mapData
.sort((a, b) => b.value - a.value)
.slice(0, 20)
),
symbolSize: (val) => val[2] / 10,
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
},
label: {
formatter: '{b}',
position: 'right',
show: true
},
itemStyle: {
color: '#f00',
shadowBlur: 10,
shadowColor: '#f00'
},
emphasis: {
scale: true
},
zlevel: 1
}
]
}
// 地图线动画数据
const geoGpsMap = [112.29, 30.98]
const convertToLineData = (data, gps) => {
const res = []
for (let i = 0; i < data.length; i++) {
const dataItem = data[i]
const toCoord = geoCoordMap[dataItem.name]
const fromCoord = gps
if (fromCoord && toCoord) {
res.push([
{
coord: fromCoord,
value: dataItem.value
},
{
coord: toCoord
}
])
}
}
return res
}
const lineOptions = {
series: [
{
type: 'lines',
zlevel: 2,
effect: {
show: true,
period: 4,
trailLength: 0.02,
symbol: 'arrow',
symbolSize: 3
},
lineStyle: {
color: '#f00',
width: 0.1,
opacity: 0.5,
curveness: 0.3
},
data: convertToLineData(mapData, geoGpsMap)
}
]
}
// 初始化地图
let chart = null
const initChart = () => {
chart = echarts.init(chartsRef.value)
chart.setOption(options) // 设置地图基础配置
chart.setOption(pointOptions) // 设置点动画配置
chart.setOption(lineOptions) // 设置线动画配置
}
onMounted(() => {
initChart()
window.addEventListener('resize', () => {
chart && chart.resize()
})
})
</script>
<style>
.echarts {
width: 100%;
height: 600px;
}
</style>
1、完整效果