代码直接复制然后导入echarts包即可运行,模拟数据在data里面,代码中有注释。
一、需求及思路
1.1 实现地图下钻
获取全国及省份文件路径
provinces:key = 当前省会名json怎么读称(注意全国的话要额外标注)
provinces:value = 对应省会路径
provinces: {
'全国': require("echarts/map/json/china.json"),
'上海': require("echarts/map/json/province/shanghai.json"),
'河北': require("echarts/map/json/province/hebei.json")
...}
点击省的时候调用registerMap
=>myEchart.registerMap('全国', provinceappointments['全国'])
再重新给地图设置op缓存tion即可实现地图下钻
=>this.myChart.setOption(options, true)
注意: 重新设置option需要在里面进行配置,registerMap函数的第一个参数要对缓存视频变成本地视频应在option里面的地图series的map上,详细代码参考下方,这里只描述具体思路。
1测试仪.2 追踪点击轨迹(实现点击返回)
右上角轨迹轴,点击轨迹轴可以返回到对应的地图上
这里优化在下面的代码中去掉了原因是可以因
各自项目
而异 思路是可以做一个缓存,可以把每个省份上的撒点数据存到一个对象中,每次点击这个省的时候先查找这个对缓存象中是否有数据,有的appointment话直接取出,没有的话发请求然后存到对象中,下RTC次点击缓存文件这个省就可以节约请求资源直接appreciate拿数据了(这个对象不会存在本地,刷新页面就会清空)
// {
// name: "全国",
// scatterData: [], // 撒点数据
// mapData: [], // 面板数据
// index: 0, // 0:全国,1:省,2:市场
// }
guideAxle: []
注意如果点的是当前测试你的自卑程度显示的省区域不用发请求也无需做任json解析失败何操作
1.3缓存视频变成本地视频 放人头攒动大地图后点击旁白区域重置地测试你适合学心理学吗图大小置中显示
监听空白区域点击事件(echarts提供),然后调用 this.myChart.setOption(options, true)
即可实现重置置中rtc是什么意思
this.myChart.getZr().on('click', params => {
if (!params.target) {
// 鼠标点击地图外 还原地图大小
}
})
1.4 把数据的指定维度映射到对应json格式怎么打开的视觉元素上,优化取整
方便阅读,阅读性较强
如 最大值191231 分成 5 段json解析失败 191231/5=38246.2;取运算结果的第一个值
3
手动+1;然后拼接一共多少位40000
;然后乘以之前的5
;返回200000
;
// val 最大值
// splitNumber 分成几段
handlerVisualMapMax(val, splitNumber = 5) {
val = val / splitNumber + "";
let newVal = +val[0] + 1 + "";
while (newVal.length < val.length) {
newVal += "0"
}
return newVal * splitNumber;
},
1.5 金额格式测试抑郁症的20道题化组件 >appreciate; 如:1200000元
=>1‘200万元
100000000元
=> 1亿元
// num 金额
// toFixed 保留几位小数
// returnResult 返回的格式 对象or金额or单位
numFormatUnit(num, toFixed = 2, returnResult = "obj") {
let m = {
num: 0,
unit: ""
}
if (!num) {
m.num = num;
return returnResult === 'obj' ? m : m[returnResult];
};
const moneyUnits = ["元", "万元", "亿元", "万亿"]
const dividend = 10000;
let curentNum = Number(num);
const strNumSize = (tempNum) => {
const stringNum = tempNum.toString()
const index = stringNum.indexOf(".")
let newNum = stringNum;
if (index != -1) {
newNum = stringNum.substring(0, index)
}
return newNum.length
}
//转换数字
let curentUnit = moneyUnits[0];
//转换单位
let i = 0;
for (; i < 4; i++) {
curentUnit = moneyUnits[i]
if (strNumSize(curentNum) < 5) {
break;
}
curentNum = curentNum / dividend
}
toFixed = i > 1 ? toFixed : 0;
m.num = curentNum.toFixed(toFixed).toString()
.replace(/(^|\s)\d+/g, (m) => m.replace(/(?=(?!\b)(\d{3})+$)/g, "'"));
m.unit = curentUnit;
return returnResult === 'obj' ? m : m[returnResult];
}
由于这个项目是基于旧项目扩展上海团队的看板 所以echarts的版本会比较低
一、完整代码
<template>
<div class="sh-map" id="sh-map">
<div
id="china_map"
:style="{ width: '100%', height: 'calc(100% - 0px)' }"
></div>
<div class="sh-national-exchange">
<h1>全国交易市场</h1>
<h2><span>5</span>个</h2>
</div>
<ul class="sh__guide__axle">
<li
v-for="(item, index) in guideAxle"
:key="index"
@click="switchGuide(item, index)"
>
<span>{{ item.name }}</span>
</li>
</ul>
</div>
</template>
<script>
import * as myEchart from 'echarts';
export default {
name: "ShMap",
components: {},
data() {
return {
provinces: {
全国: require("echarts/map/json/china.json"),
上海: require("echarts/map/json/province/shanghai.json"),
河北: require("echarts/map/json/province/hebei.json"),
山西: require("echarts/map/json/province/shanxi.json"),
内蒙古: require("echarts/map/json/province/neimenggu.json"),
辽宁: require("echarts/map/json/province/liaoning.json"),
吉林: require("echarts/map/json/province/jilin.json"),
黑龙江: require("echarts/map/json/province/heilongjiang.json"),
江苏: require("echarts/map/json/province/jiangsu.json"),
浙江: require("echarts/map/json/province/zhejiang.json"),
安徽: require("echarts/map/json/province/anhui.json"),
福建: require("echarts/map/json/province/fujian.json"),
江西: require("echarts/map/json/province/jiangxi.json"),
山东: require("echarts/map/json/province/shandong.json"),
河南: require("echarts/map/json/province/henan.json"),
湖北: require("echarts/map/json/province/hubei.json"),
湖南: require("echarts/map/json/province/hunan.json"),
广东: require("echarts/map/json/province/guangdong.json"),
广西: require("echarts/map/json/province/guangxi.json"),
海南: require("echarts/map/json/province/hainan.json"),
四川: require("echarts/map/json/province/sichuan.json"),
贵州: require("echarts/map/json/province/guizhou.json"),
云南: require("echarts/map/json/province/yunnan.json"),
西藏: require("echarts/map/json/province/xizang.json"),
陕西: require("echarts/map/json/province/shanxi1.json"),
甘肃: require("echarts/map/json/province/gansu.json"),
青海: require("echarts/map/json/province/qinghai.json"),
宁夏: require("echarts/map/json/province/ningxia.json"),
新疆: require("echarts/map/json/province/xinjiang.json"),
北京: require("echarts/map/json/province/beijing.json"),
天津: require("echarts/map/json/province/tianjin.json"),
重庆: require("echarts/map/json/province/chongqing.json"),
香港: require("echarts/map/json/province/xianggang.json"),
澳门: require("echarts/map/json/province/aomen.json"),
台湾: require("echarts/map/json/province/taiwan.json"),
},
myChart: null,
// {
// name: "全国",
// scatterData: [], // 撒点数据
// mapData: [], // 面板数据
// index: 0, // 0:全国,1:省,2:市场
// }
guideAxle: [],
}
},
mounted() {
this.$nextTick(() => {
this.initEchartMap();
})
},
methods: {
// 右上角切换
switchGuide(item, index) {
const guideAxleLast = this.guideAxle.length - 1;
// 点击当前块不做任何操作
if (index === guideAxleLast) return;
this.guideAxle.splice(index + 1);
if (item.index == 0 || (item.index == 1)) {
const { name } = item;
myEchart.registerMap(name, this.provinces[name]);
this.renderMap(item);
}
},
// 渲染地图
renderMap(obj) {
const keyName = obj.name;
let options = {
backgroundColor: "#00000000",
tooltip: {
show: true,
triggerOn: "none",
backgroundColor: '#00000000',
padding: 0,
enterable: true,
transitionDuration: 1,
axisPointer: {
type: 'line',
axis: 'auto',
snap: true,
},
textStyle: {
color: "#000",
decoration: "none"
}
},
geo: {
show: true,
map: keyName,
label: {
normal: {
color: "#fff",
fontSize: 12,
show: true
},
emphasis: {
color: "#fff",
fontSize: 14,
show: true
}
},
regions: [
{
name: "南海诸岛",
itemStyle: {
// 隐藏地图
normal: {
opacity: 0, // 为 0 时不绘制该图形
}
},
label: {
show: false // 隐藏文字
}
}
],
scaleLimit: {
min: 1.25,
max: 25
},
roam: true,
zoom: 1.25,
itemStyle: {
normal: {
borderWidth: 1, // 区域边框宽度
borderColor: "#A66300", // 区域边框颜色
areaColor: "#070707", // 区域颜色
},
emphasis: {
borderWidth: 1.5, // 区域边框宽度
borderColor: "#ffffff", // 区域边框颜色
areaColor: '#FF9800', // 区域颜色
}
}
},
visualMap: {
show: true,
splitNumber: 5,
itemWidth: 20,
itemHeight: 10,
textGap: 15,
max: 0,
padding: 0,
textStyle: {
color: "rgba(255,255,255,0.5)"
},
inRange: {
color: ['#4D3602', '#FEE1AA']
},
formatter: (valMin, valMax) => {
const formatValMin = this.numFormatUnit(valMin, 4);
const formatValMax = this.numFormatUnit(valMax, 4);
return `${formatValMin.num}-${formatValMax.num}${formatValMax.unit ? formatValMax.unit : "元"}`;
}
},
series: [
{
name: "点1",
type: "scatter",
coordinateSystem: "geo",
data: JSON.parse('[{"name":"0012交易市场","value":["121.489912","31.244415"],"id":"TM-1c8839b004464dfb84f936aeee6d0cc5","marketName":"0012","province":"上海市","marketLocation":["31.244415","121.489912"],"accuracyCreditAmount":"0.00","accuracyLoanAmount":"0","repaymentLoanAmount":0,"creditOrgCount":0,"loanOrgCount":0,"pledgorVehicleCount":0,"applyCreditOrgCount":0,"creditTotalCount":0,"balanceTotalAmount":"0.00","actualBalanceAmount":"0.00","visualMap":false},{"name":"m8722交易市场","value":["121.3839","31.175947"],"id":"TM-2562d19b17e9478fba7b848154947265","marketName":"m8722","province":"上海市","marketLocation":["31.175947","121.3839"],"accuracyCreditAmount":"2000000.00","accuracyLoanAmount":"16257.00","repaymentLoanAmount":16257,"creditOrgCount":3,"loanOrgCount":3,"pledgorVehicleCount":8,"applyCreditOrgCount":1,"creditTotalCount":5,"balanceTotalAmount":"0.00","actualBalanceAmount":"0.00","visualMap":false},{"name":"一二交易市场","value":["121.455708","31.249574"],"id":"TM-0a88833966b04039b95d0f6692329785","marketName":"一二","province":"上海市","marketLocation":["31.249574","121.455708"],"accuracyCreditAmount":"0.00","accuracyLoanAmount":"0","repaymentLoanAmount":0,"creditOrgCount":0,"loanOrgCount":0,"pledgorVehicleCount":0,"applyCreditOrgCount":1,"creditTotalCount":1,"balanceTotalAmount":"0.00","actualBalanceAmount":"0.00","visualMap":false},{"name":"成都锦和市场测试671","value":["104.017594","30.578247"],"id":"671","marketName":"成都锦和市场测试671","province":"四川省","marketLocation":["30.578247","104.017594"],"accuracyCreditAmount":"0.00","accuracyLoanAmount":"0","repaymentLoanAmount":0,"creditOrgCount":0,"loanOrgCount":0,"pledgorVehicleCount":1,"applyCreditOrgCount":0,"creditTotalCount":1,"balanceTotalAmount":"0.00","actualBalanceAmount":"0.00","visualMap":false},{"name":"武汉市民之家交易市场","value":["114.295164","30.659795"],"id":"TM-00889f1ee2974d188e4e793d8a03762a","marketName":"武汉市民之家","province":"湖北省","marketLocation":["30.659795","114.295164"],"accuracyCreditAmount":"0.00","accuracyLoanAmount":"0","repaymentLoanAmount":0,"creditOrgCount":0,"loanOrgCount":0,"pledgorVehicleCount":0,"applyCreditOrgCount":0,"creditTotalCount":1,"balanceTotalAmount":"0.00","actualBalanceAmount":"0.00","visualMap":false}]'),
symbol: 'image://' + require('@/assets/sh/homePage/撒点_授用信.png'),
symbolSize: 30,
color: { opacity: 1 },
label: {
normal: {
show: false
},
emphasis: {
show: true,
fontSize: 14,
formatter(params) {
return params.data.name
}
}
},
itemStyle: {
normal: {
color: "#0066FF",
},
emphasis: {
color: "#14FF00"
}
},
zlevel: 2,
},
{
type: 'map',
map: keyName,
geoIndex: 0,
aspectScale: 0.75, //长宽比
showLegendSymbol: true, // 存在legend时显示
label: {
normal: {
show: false
},
emphasis: {
show: false,
textStyle: {
color: '#fff'
}
}
},
roam: true,
itemStyle: {
normal: {
areaColor: '#FFF0D1',
},
emphasis: {
areaColor: '#FFBA2E'
}
},
animation: true,
data: JSON.parse('[{ "province": "北京市", "creditAmount": 140.15, "loanAmount": 17, "repaymentLoanAmount": 150000, "accuracyCreditAmount": 1401500, "accuracyLoanAmount": 170000, "creditOrgCount": 4, "loanOrgCount": 2, "pledgorVehicleCount": 33, "applyCreditOrgCount": 10, "creditTotalCount": 16, "name": "北京", "value": 170000 }, { "province": "陕西省", "creditAmount": 500, "loanAmount": 0.11, "repaymentLoanAmount": 1100, "accuracyCreditAmount": 5000000, "accuracyLoanAmount": 1100, "creditOrgCount": 1, "loanOrgCount": 1, "pledgorVehicleCount": 3, "applyCreditOrgCount": 0, "creditTotalCount": 1, "name": "陕西", "value": 1100 }, { "province": "上海市", "creditAmount": 610, "loanAmount": 0.01, "repaymentLoanAmount": 117, "accuracyCreditAmount": 6100000, "accuracyLoanAmount": 117, "creditOrgCount": 4, "loanOrgCount": 2, "pledgorVehicleCount": 11, "applyCreditOrgCount": 2, "creditTotalCount": 8, "name": "上海", "value": 117 }]'),
},
]
}
options.visualMap.max = this.handlerVisualMapMax(191231);
this.myChart.setOption(options, true)
},
//初始化中国地图
initEchartMap() {
let mapDiv = document.getElementById('china_map');
let shMap = document.getElementById('sh-map');
let obj = {
name: "全国",
scatterData: [], // 撒点数据
mapData: [], // 面板数据
index: 0, // 0:全国,1:省,2:市场
}
myEchart.registerMap(obj.name, this.provinces[obj.name])
this.resizeMyChartContainer(mapDiv, shMap);
this.myChart = myEchart.init(mapDiv);
this.guideAxle.push(obj);
this.renderMap(obj);
window.onresize = () => {
this.resizeMyChartContainer(mapDiv, shMap);
this.myChart.resize();
}
// 注册点击事件
this.myChartGetZrClick();
this.myChartClick();
},
// 地图容器宽度
resizeMyChartContainer(mapDiv, shMap) {
mapDiv.style.width = shMap.offsetWidth + 'px'
},
// map getZr click
myChartGetZrClick() {
this.myChart.getZr().on('click', params => {
// 鼠标点击地图外 还原地图大小
if (!params.target) {
const currentIndex = this.guideAxle.length - 1;
const currentGuide = this.guideAxle[currentIndex];
this.renderMap(currentGuide.index === 2 ? this.guideAxle[currentIndex - 1] : currentGuide)
}
})
},
// map click
myChartClick() {
this.myChart.on("click", params => {
const { name } = params;
const guideAxleLast = this.guideAxle.length - 1;
let currentIndex = this.guideAxle[guideAxleLast].index;
// 是否替换, // 是否处理添加
let isReplace, ishandlerAdd = false;
let obj = {
name,
scatterData: [],
mapData: [],
index: 0,
}
if (params.seriesType === "map" && params.data) {
ishandlerAdd = true;
obj.index = 1;
myEchart.registerMap(name, this.provinces[name]);
this.renderMap(obj);
if (currentIndex !== 0) isReplace = true;
}
if (params.seriesType === "scatter") {
ishandlerAdd = true;
obj.index = 2;
if (currentIndex === 2) isReplace = true;
}
if (!ishandlerAdd) return;
if (isReplace) {
this.guideAxle.splice(guideAxleLast, 1, obj)
} else {
this.guideAxle.push(obj)
}
});
},
// 格式化金额
numFormatUnit(num, toFixed = 2, returnResult = "obj") {
let m = {
num: 0,
unit: ""
}
if (!num) {
m.num = num;
return returnResult === 'obj' ? m : m[returnResult];
};
const moneyUnits = ["元", "万元", "亿元", "万亿"]
const dividend = 10000;
let curentNum = Number(num);
const strNumSize = (tempNum) => {
const stringNum = tempNum.toString()
const index = stringNum.indexOf(".")
let newNum = stringNum;
if (index != -1) {
newNum = stringNum.substring(0, index)
}
return newNum.length
}
//转换数字
let curentUnit = moneyUnits[0];
//转换单位
let i = 0;
for (; i < 4; i++) {
curentUnit = moneyUnits[i]
if (strNumSize(curentNum) < 5) {
break;
}
curentNum = curentNum / dividend
}
toFixed = i > 1 ? toFixed : 0;
m.num = curentNum.toFixed(toFixed).toString()
.replace(/(^|\s)\d+/g, (m) => m.replace(/(?=(?!\b)(\d{3})+$)/g, "'"));
m.unit = curentUnit;
return returnResult === 'obj' ? m : m[returnResult];
},
// 地图左下角整数格式化单位
handlerVisualMapMax(val, splitNumber = 5) {
val = val / splitNumber + "";
let newVal = +val[0] + 1 + "";
while (newVal.length < val.length) {
newVal += "0"
}
return newVal * splitNumber;
},
}
}
</script>
<style lang="scss">
@mixin flex($justifyContent: flex-start, $alignItems: flex-start) {
display: flex;
align-items: $alignItems;
justify-content: $justifyContent;
}
.sh-map {
flex: 1;
width: 100%;
height: 100%;
position: relative;
#china_map {
position: relative;
z-index: 2;
}
.sh-national-exchange {
position: absolute;
z-index: 1000;
left: 0;
top: 0;
color: #ffffff;
h1 {
font-size: 16px;
font-weight: 400;
margin-bottom: 0;
}
h2 {
font-size: 14px;
font-weight: 400;
}
span {
font-size: 52px;
color: #ffd522;
font-family: "DIN Alternate Bold";
margin-right: 8px;
font-weight: 400;
vertical-align: sub;
}
}
.sh__guide__axle {
position: absolute;
z-index: 99;
top: 0;
right: 20px;
padding: 0;
margin: 0;
li {
cursor: pointer;
list-style: none;
margin-bottom: 24px;
font-size: 14px;
color: #ffffff;
text-align: right;
span {
font-weight: 400;
display: inline-block;
padding: 9px 16px;
background: rgba(255, 255, 255, 0.06);
border-radius: 2px;
border: 1px solid rgba(255, 255, 255, 0.3);
position: relative;
&::before,
&::after {
content: "";
display: inline-block;
position: absolute;
right: -20px;
top: 16px;
}
&::before {
width: 1px;
height: 65px;
background: rgba(255, 255, 255, 0.3);
}
&::after {
width: 5px;
right: -22.5px;
height: 5px;
background: #ffd522;
border-radius: 50%;
}
}
&:last-child {
span {
color: #ffd522;
font-weight: 600;
box-shadow: 0px 0px 4px 1px #f7c76596;
border: 1px solid #f7c765;
&::before {
width: 100%;
height: 1px;
left: 0;
top: 99%;
background: linear-gradient(
266deg,
#fffcf6 0%,
#fff1d3 4%,
#f7c765 28%
);
}
}
}
}
}
}
</style>