背景
设计稿里面需要对地图进行贴背景图处理(显示山川等纹理),公司目前主要使用图表展示技术是Echarts,而Echarts本身的纹理贴图十分难用,因此需要根据Echarts特性做一些改造。
过程
分析
该图里面较难的其实主要是实现背景图
研发
- 该项目需要用到一份Svg【地图数据】
从该网站分别下载svg数据。
- 处理svg数据(重点)
2.1. 找ui或者打开在线ps,修改path的名称并导出成svg。
2.2. 打开svg, 将path的id改为name
2.3. 实现贴图(重点)
让ui提供地图的背景图,并通过引入的方式,加到svg里面
此时,打开svg,就可以看到对应的效果
- echarts注册对应的数据
- 实现
import { china } from '@tsintergy/geo-json';
import * as echarts from 'echarts';
import type { FC } from 'react';
import React, { useCallback, useEffect, useMemo } from 'react';
/** @ts-expect-error */
import chinaSvg from './assets/china.svg';
/** @ts-expect-error */
import stationImg from './assets/energyStorageStationIcon.png';
import { convertData, data } from './data';
import './index.less';
type Props = Record<string, unknown>;
const Map2: FC<Props> = () => {
const getColor = useCallback(
(value: number, visualMapSelect: boolean[] = [true, true, true, true]) => {
if (value >= 0 && value < 25 && visualMapSelect[3]) {
return '#12EEA388';
}
if (value >= 25 && value < 50 && visualMapSelect[2]) {
return '#F49B1688';
}
if (value >= 50 && value < 75 && visualMapSelect[1]) {
return '#EE5C7F88';
}
if (value >= 75 && value <= 100 && visualMapSelect[0]) {
return '#8F7DFF88';
}
return '#eee';
},
[],
);
const option = useMemo(() => {
return {
tooltip: {
trigger: 'item',
backgroundColor: 'rgba(1,14,13,0.77)',
borderColor: '#41FFFF',
borderWidth: 2,
padding: 8,
textStyle: {
color: '#fff',
},
},
visualMap: {
show: true,
left: 20,
bottom: 20,
type: 'piecewise',
pieces: [
{ gte: 75, label: '≥75%' },
{ gte: 50, lt: 75, label: '50%-75%' },
{ gte: 25, lt: 50, label: '25%-50%' },
{ gte: 0, lt: 25, label: '0%-25%' },
],
inRange: {
color: ['#12EEA3', '#F49B16', '#EE5C7F', '#8F7DFF'],
},
seriesIndex: [0, 1],
textStyle: {
color: '#fff',
},
},
geo: {
map: 'chinaSvg',
show: true,
aspectScale: 0.85,
zoom: 2,
roam: true,
// center: [650, 400],
label: {
normal: {
show: false,
},
emphasis: {
show: false,
},
},
itemStyle: {
normal: {
areaColor: '#00000020',
borderColor: '#97F6FFcc', // 线
borderWidth: 2,
},
emphasis: {
areaColor: '#97F6FF80', // 悬浮区背景
},
},
regions: data?.map((item) => {
return {
name: item.name,
itemStyle: {
areaColor: getColor(item.response),
},
};
}),
},
series: [
{
symbolSize: 25,
geoIndex: 0,
label: {
formatter: '{b}',
position: 'right',
show: true,
},
itemStyle: {
normal: {
color: '#fff',
},
},
name: '虚拟电厂',
type: 'scatter',
coordinateSystem: 'geo',
data: convertData(
data?.map((item) => {
return { name: item.name, value: item.response };
}) || [],
),
// eslint-disable-next-line global-require
symbol: `image://${stationImg}`,
},
],
};
}, [getColor]);
useEffect(() => {
window
.fetch(chinaSvg)
.then((res) => {
return res.text();
})
.then((e) => {
const _chinaSvg = e.replace(
'/assets/ui-example/Map/Map2/1.png',
// eslint-disable-next-line no-undef
`${projectName}/assets/ui-example/Map/Map2/1.png`,
);
echarts.registerMap('chinaSvg', { svg: _chinaSvg });
echarts.registerMap('china', china as any);
const echartDom = document.getElementById('echarts')!;
const echartsInstance = echarts.init(echartDom);
echartsInstance.setOption(option as any);
echartsInstance.on('datarangeselected', function (obj: { selected: any }) {
const currentOption: any = echartsInstance.getOption();
currentOption.geo[0].regions = data.map((item) => {
return {
name: item.name,
itemStyle: {
areaColor: getColor(item.response, obj.selected),
},
};
});
echartsInstance.setOption(currentOption);
});
});
}, [getColor, option]);
return (
<div className={`Map2`} style={{ width: '100%' }}>
<div id="echarts" style={{ width: '100%', height: '500px' }} />
</div>
);
};
export default Map2;
- 修改数据,使背景跟地图贴合,及删除多余数据
结果
本示例完美实现贴图,及放大缩小平移,如果觉得有用的话,请点赞收藏。