1.通过阿里云数据可视化平台设置行政区范围,下载geoJson数据文件,在代码中引入该地图数据文件。
阿里云数据可视化平台:点击跳转
2.使用ECharts渲染地图,添加图片作为地图纹理。
地图背景图:
效果图:
注意问题:
如果在渲染地图时,发现背景渲染比较模糊:
-
检查ECharts 版本,ECharts 4.x 对纹理渲染存在缺陷,导致背景模糊。可以考虑升级到更高版本。目前已知4.2.1是有问题的,我本地升级到5.4.3后正常,且在4.2.1版本下通过以下方法,也无法解决图片模糊的问题。
-
容器尺寸与图片分辨率需要匹配,可以调整layoutSize和容器的尺寸,使得图片不需要被过度缩放;
-
检查图片分辨率,确保使用更高分辨率的图片,以便在放大的情况下也能清晰显示。
-
平铺模式(repeat)不匹配, repeat支持设置'no-repeat','repeat','repeat-x', 'repeat-y',可以根据实际效果进行调整;
如果在渲染地图时,发现背景图纹理不显示:
检查图片是否未预加载完成,确保在图片加载完成后,再执行图表的初始化。
如果在渲染地图时,发现地图拖拽会分层:
检查series的geoIndex属性,通过指定geoIndex,使map 和 series共享一个geo;
代码(以下代码不包含弹窗效果):
<template>
<div id="myChart" />
</template>
<script>
import * as echarts from 'echarts'
import chinaJson from './china.json'
export default {
name: 'LabMap',
data() {
return {}
},
mounted() {
this.initChart()
},
methods: {
initChart() {
const domImg = document.createElement('img')
domImg.src = require('./mapBg.png')
const myChart = echarts.init(document.getElementById('myChart'))
myChart.showLoading()
echarts.registerMap('china', chinaJson) // 注册中国地图
myChart.hideLoading()
const option = {
backgroundColor: '#040b1c',
geo: {
show: true, // 是否显示地理坐标系组件
map: 'china', // 使用 registerMap 注册的地图名称
roam: true, // 是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move'。设置成 true 为都开启
zoom: 0.9, // 固定缩放
layoutCenter: ['50%', '50%'], // 地图中心在屏幕中的位置
layoutSize: '100%', // 地图的大小,支持相对于屏幕宽高的百分比或者绝对的像素大小
aspectScale: 0.75, // 这个参数用于 scale 地图的长宽比,如果设置了projection则无效
label: {
show: false, // 是否显示标签
emphasis: {
// 高亮状态下的多边形和标签样式
show: false
}
},
itemStyle: {
areaColor: { // 地图区域的颜色(支持纯色,渐变色或者纹理填充,image为纹理填充)
image: domImg, // 支持为 HTMLImageElement, HTMLCanvasElement,不支持路径字符串
repeat: 'repeat' // 是否平铺,可以是 'repeat-x', 'repeat-y', 'no-repeat'
},
borderColor: '#5CDDF7', // 图形的描边颜色
borderWidth: 2, // 描边线宽。为 0 时无描边。
shadowBlur: 10, // 图形阴影的模糊大小。该属性配合 shadowColor,shadowOffsetX, shadowOffsetY 一起设置图形的阴影效果。
shadowColor: '#5CDDF7', // 阴影颜色
shadowOffsetX: -5, // 阴影水平方向上的偏移距离
shadowOffsetY: 5, // 阴影垂直方向上的偏移距离
emphasis: { // 高亮状态下的多边形和标签样式
areaColor: '#18FEFE',
borderColor: 'yellow'
}
}
},
series: [
{
name: '数据',
type: 'map',
map: 'china', // 使用注册的地图名称
geoIndex: 0, // 0不会分层
label: {
show: false // 显示省份名称
},
// 确保纹理层级正确:将纹理仅应用于 geo 组件,避免与 series 冲突:
itemStyle: {
areaColor: 'transparent' // 系列设置为透明,透出geo的纹理
},
data: [
{ name: '北京', value: 100 },
{ name: '上海', value: 200 }
]
}
]
}
myChart.clear()
myChart.setOption(option)
window.addEventListener(
'resize',
() => {
myChart.resize()
},
false
)
}
}
}
</script>
<style scoped>
#myChart {
width: 80%;
height: 800px;
margin: auto;
}
</style>
3.添加弹窗,优化展示效果
- 高亮选中区域,优化鼠标悬浮效果;
- 增加坐标弹窗,自定义展示效果;
- 增加坐标点图标,图标跳动显示;
完整代码
<template>
<div id="myChart" />
</template>
<script>
import * as echarts from 'echarts'
import chinaJson from './china.json'
export default {
name: 'LabMap',
data() {
return {}
},
mounted() {
this.initChart()
},
methods: {
initChart() {
const data = [
{
deviceCount: 138,
longitude: '110.3467',
latitude: '41.4899',
region: '内蒙古',
remark: '测试数据测试数据测试数据测试数据测试数据'
},
{
deviceCount: 235,
longitude: '91.11',
latitude: '29.97',
region: '西藏',
remark: '测试数据测试数据测试数据测试数据测试数据'
},
{
deviceCount: 400,
longitude: '113.0823',
latitude: '28.2568',
region: '湖南',
remark: '测试数据测试数据测试数据测试数据测试数据'
}
]
const regionData = []
const ponitData = []
data.forEach((item) => {
regionData.push({
name: item.region,
value: [Number(item.longitude), Number(item.latitude)]
})
ponitData.push({
name: item.region,
deviceCount: item.deviceCount,
value: [Number(item.longitude), Number(item.latitude)],
remark: item.remark
})
})
const domImg = document.createElement('img')
domImg.src = require('./mapBg.png')
const myChart = echarts.init(document.getElementById('myChart'))
myChart.showLoading()
echarts.registerMap('china', chinaJson) // 注册中国地图
myChart.hideLoading()
const option = {
backgroundColor: '#040b1c',
tooltip: {
trigger: 'item',
backgroundColor: '#002260',
borderColor: '#0984F3',
color: '#fff',
borderWidth: 1,
padding: [5, 15],
textStyle: {
color: '#fff'
},
formatter: '{b}'
},
geo: {
show: true, // 是否显示地理坐标系组件
map: 'china', // 使用 registerMap 注册的地图名称
roam: true, // 是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move'。设置成 true 为都开启
zoom: 0.9, // 固定缩放
layoutCenter: ['50%', '50%'], // 地图中心在屏幕中的位置
layoutSize: '100%', // 地图的大小,支持相对于屏幕宽高的百分比或者绝对的像素大小
aspectScale: 0.75, // 这个参数用于 scale 地图的长宽比,如果设置了projection则无效
label: {
show: false, // 是否显示标签
emphasis: {
// 高亮状态下的多边形和标签样式
show: false
}
},
itemStyle: {
areaColor: {
// 地图区域的颜色(支持纯色,渐变色或者纹理填充,image为纹理填充)
image: domImg, // 支持为 HTMLImageElement, HTMLCanvasElement,不支持路径字符串
repeat: 'repeat' // 是否平铺,可以是 'repeat-x', 'repeat-y', 'no-repeat'
},
borderColor: '#5CDDF7', // 图形的描边颜色
borderWidth: 2, // 描边线宽。为 0 时无描边。
shadowBlur: 10, // 图形阴影的模糊大小。该属性配合 shadowColor,shadowOffsetX, shadowOffsetY 一起设置图形的阴影效果。
shadowColor: '#5CDDF7', // 阴影颜色
shadowOffsetX: -5, // 阴影水平方向上的偏移距离
shadowOffsetY: 5, // 阴影垂直方向上的偏移距离
emphasis: {
// 高亮状态下的多边形和标签样式
areaColor: '#0B2986',
borderColor: '#0984F3'
}
}
},
series: [
{
symbolSize: 1,
label: {
normal: {
formatter: '{b}',
position: 'bottom',
color: '#fff',
fontSize: 16,
fontWeight: 'bold',
show: true
},
emphasis: {
show: true
}
},
name: '区域',
type: 'scatter',
coordinateSystem: 'geo',
data: regionData
},
{
name: '数据',
type: 'map',
map: 'china', // 使用注册的地图名称
geoIndex: 0, // 0不会分层
label: {
show: false // 显示省份名称
},
// 确保纹理层级正确:将纹理仅应用于 geo 组件,避免与 series 冲突:
itemStyle: {
areaColor: 'transparent' // 系列设置为透明,透出geo的纹理
},
data: data
},
{
name: '弹窗',
type: 'effectScatter',
coordinateSystem: 'geo',
legendHoverLink: true,
symbol: 'image://' + require('./坐标.png'),
symbolSize: [15, 18],
symbolOffset: ['-50%', '-70%'],
data: ponitData,
showEffectOn: 'render',
rippleEffect: {
period: 3, // 秒数
scale: 3, // 缩放比例
brushType: 'stroke'
},
hoverAnimation: true,
zlevel: 1,
label: {
show: true,
offset: [-95, 0], // 偏移设置
lineHeight: 23,
backgroundColor: '#002260',
borderColor: '#5CDDF7',
borderWidth: 1,
padding: [4, 14],
formatter: (value) => {
let remark = value.data.remark
remark =
remark.length > 6 ? remark.substr(0, 6) + '...' : remark
return (
`{name|${value.data.name}}\n{pt|` +
'销售数量' +
`:}${value.data.deviceCount}` +
'台' +
`\n{pt|` +
'备注' +
`:}${remark}`
)
},
rich: {
name: {
color: '#fff'
},
pt: {
color: '#00CAFF'
}
},
color: '#fff'
}
}
]
}
myChart.clear()
myChart.setOption(option)
window.addEventListener(
'resize',
() => {
myChart.resize()
},
false
)
}
}
}
</script>
<style scoped>
#myChart {
width: 80%;
height: 800px;
margin: auto;
}
</style>