Echarts- svg地图

2,437 阅读3分钟

参考链接

知识点:

this.nationChart.clear() 清空图表,重新配置图表(清空以前图表)

pointer-events: none; 阻止该元素响应事件。(避免提示框 遮盖图表高亮显示)

echarts custom keyframeAnimation 动画 需要5.3.3 版本以上

  1. 修改UI figma 导出的svg(path + image)

    把image 从 defs 中移到外面,成为第一个视图加载, 添加 x="" y="" width="" height="" 移动图片,达到 位置对齐,不会偏移

    path 形状 添加 fill="transparent", 达到 path背景透明,使用image

    path 添加 name 属性,具现化 可以在Echarts(什么都不配置 展示出来)

  2. axios加载svg 文件, svg 放在 public 文件夹下

function getOption(element, echartsInstance) {
	return new Promise((resolve) => {
		// /big_map.svg
		axios('/big_map.svg' , {
			method: 'GET',
			baseURL: '/'
		}).then(({
			data
		}) => {
			element.$echarts.registerMap('map', {
				svg: data
			});

			resolve(demo1(echartsInstance))
		})
	})
}
  1. 修改Echarts 配置文件

    svg 加载 series中map 或 geo。geo 可以方便加 点和其他series

    label: 地图 正常状态下文字(svg -> path -> name),rich可以设置图片

    regions 单独定制的区块设置(正常状态和高亮状态),regions 某个形状 单独效果 ,在svg 正常状态下是透明的, 选择状态设置特殊颜色,完成炫酷的效果

    根据 具体的name 触发选择状态

    myChart.dispatchAction({
          type: 'geoSelect',
          geoIndex: 0,
          name: name
     });
    
    regions: [{ // 单独定制的区块设置
    // name: '地图一',
    // itemStyle: {
    // 	areaColor: 'red',
    // 		},
    // 	},
    

    itemStyle: 地图 正常状态下 统一样式, path 的背景色areaColor,边界线颜色和宽度 borderColor borderWidth

    emphasis:地图 高亮状态下 样式

    添加 好看的点 series -> custom

    coordinateSystem: 'geo' 坐标系是 geo(svg 地图下坐标)

    coord: 添加点 的坐标

    circles:涟漪动画 custom 中的circle圆圈(动画使用查看配置文件)

    image: 涟漪动画上面的 图标(base64图片)

    text: image 上面的文字 fill + lineWidth + stroke 使文字更突出,有点艺术感

    text: 有高亮状态,可以和地图高亮联动。高亮时有没有图标 color 颜色控制

    散点图 背景可以是图片

    监听mouseover + mouseout 事件,完成监听用户触发高亮的 情况,返回 触发坐标,限制触发次数, 展示提示框

    getZr().on('click') 获取地图上面点的坐标, 地图上面点数据坐标就是通过监听click事件获取的

    style: {
    text: name_arr[params.dataIndex],
    textAlign: 'center',
    fill: 'white',
    lineWidth: 3,
    stroke: 'black'
    }
    
function demo1(echartsInstance) {
    // svg 地图展示的 名称
    const name_arr = mapData.map((item) => item.name)

    // geo 加载 svg 
    const option = {
	geo: {
            map: 'map', //这里写注册过的map 名字
            label: { // 文字标注 即svg -> path 加上具名元素 -> name属性值
		show: false, //显示
		color: 'rgba(255, 255, 255, 0.6)', //颜色
		fontSize: 10
            },
            itemStyle: {
		// 统一样式
		// areaColor: 'rgba(178, 236, 255, 0.5)',
		borderColor: 'rgba(178, 236, 255, 1)',
		borderWidth: 2
		// opacity: 1,
            },
            emphasis: { // 高亮状态
		// disabled: true,
		itemStyle: {
                    areaColor: 'rgba(55, 111, 208, 0.4)',
                    // opacity: 1,
                    // shadowColor: 'rgba(74, 188, 251, 0.4)',
                    // shadowBlur: 3,
                    // shadowOffsetX: 3,
                    // shadowOffsetY: 3,
		},
		label: {
                    show: false, //高亮时文字不要出现
		}
            }
	},
	series: [{
            type: 'custom',
            coordinateSystem: 'geo',
            geoIndex: 0,
            zlevel: 1,
            data: mapData.map((item) => item.value),
            renderItem(params, api) {
		const coord = api.coord([
                    api.value(0, params.dataIndex),
                    api.value(1, params.dataIndex)
		]);
		const circles = [];
		for (let i = 0; i < 5; i++) {
                    circles.push({
			type: 'circle',
			shape: {
                            cx: 0,
                            cy: 0,
                            r: 30
			},
			style: {
                            stroke: 'rgba(178, 236, 255, 1)',
                            fill: 'none',
                            lineWidth: 2
			},
			// Ripple animation
			keyframeAnimation: {
                            duration: 4000,
                            loop: true,
                            delay: (-i / 4) * 4000,
                            keyframes: [{
				percent: 0,
				scaleX: 0,
				scaleY: 0,
				style: {
                                    opacity: 1
				}
                            },
                            {
				percent: 1,
				scaleX: 1,
				scaleY: 0.4,
				style: {
                                    opacity: 0
				}
                            }]
			}
                    });
		}
				
	return {
            type: 'group',
            x: coord[0],
            y: coord[1],
            children: [
		...circles,
		{
                    type: 'image',
			style: {
                            image: image,
                            x: -10,
                            y: -25,
                            width: 20,
                            height: 29
			},
			// Jump animation.
			// keyframeAnimation: {
                            // 	duration: 1000,
                            // 	loop: true,
                            // 	delay: Math.random() * 1000,
                            // 	keyframes: [{
				// y: -10,
                                // percent: 0.5,
				// easing: 'cubicOut'
				// },
				// {
				// y: 0,
				// percent: 1,
                                // easing: 'bounceOut'
				// }
				// ]
                            // }
			},
			{
                            type: 'text',
                            y: -40,
                            style: {
				text: name_arr[params.dataIndex],
				textAlign: 'center',
				fill: 'white',
				lineWidth: 3,
				stroke: 'black'
                            }
			}
                       ]
                    };
                   }
		}]
	}

	echartsInstance.getZr().on('mouseover', {
            geoIndex: 0
	}, function(params) {
            if (!isHigh) {
		isHigh = true
		if (params.target) {
                    let show_flag = false
                    for (let key in params.target) {
			if (key.includes('__ec_inner_')) {
                            const tar = params.target[key]
                            if (tar && tar.componentHighDownName && !show_flag) {
				show_flag = true
				clearTimeout(timer)
				mitt.emit('showTooltop1', {
                                    name: tar.componentHighDownName,
                                    offsetX: params.offsetX,
                                    offsetY: params.offsetY - 20
				})
                            }
			}
                    }
                    }

		}
	});
	echartsInstance.getZr().on('mouseout', {
		geoIndex: 0
	}, function(params) {
		isHigh = false
		clearTimeout(timer)
		timer = setTimeout(() => {
			mitt.emit('showTooltop1')
		}, 500)
	});
	//获取 svg 底图的坐标
	// echartsInstance.getZr().on('click', function(params) {
	// 	var pixelPoint = [params.offsetX, params.offsetY];
	// 	var dataPoint = echartsInstance.convertFromPixel({
	// 		geoIndex: 0
	// 	}, pixelPoint);
	// 	// 在 SVG 上点击时,坐标会被打印。
	// 	// 这些坐标可以在 `series.data` 里使用。
	// 	let name = ''
	// 	if (params.target) {
	// 						  let show_flag = false
	// 						  for (let key in params.target) {
	// 						  	if (key.includes('__ec_inner_')) {
	// 								const tar = params.target[key]
	// 								if (tar && tar.componentHighDownName && !show_flag) {
	// 									show_flag = true
	// 									name = tar.componentHighDownName

	// 								}
	// 							}
	// 						  }
	// 	}
	// 	console.log(name, dataPoint);
	// });

	// '地图一' 是一个 SVG 元素的名字。 地图一 区域点击
	echartsInstance.on('click', {
		geoIndex: 0
	}, function(params) {
		mitt.emit('jump')
	});

	// 古水水电站1 古水水电站8 古水水电站9 点击 散点图绑定点击事件
	// echartsInstance.on('click', 'series.scatter', function(params) {
	// 	console.log(params);
	// });
	return option
}