1. 本文在基础上进行改进,后端使用若依后端
IofTV-Screen: 🔥一个基于 vue、datav、Echart 框架的物联网可视化(大屏展示)模板,提供数据动态刷新渲染、屏幕适应、数据滚动配置,内部图表自由替换、Mixins注入等功能,持续更新.... - Gitee.com
2.效果:将系统大屏显示地图
3. 使用开源项目IofTV-Screen中的Echart组件
<template>
<div class="centermap">
<div class="maptitle">
<div class="zuo"></div>
<span class="titletext">{{ maptitle }}</span>
<div class="you"></div>
</div>
<div class="mapwrap">
<dv-border-box-13>
<div class="quanguo" @click="getData('china')" v-if="code !== 'china'">
中国
</div>
<Echart id="CenterMap" :options="options" ref="CenterMap"/>
</dv-border-box-13>
</div>
</div>
</template>
4. 安装并导入编码转文本组件
(1)安装
npm install element-china-area-data -S
(2)导入编码转文本组件,实现“610000” 转换为“陕西省”
import { CodeToText } from 'element-china-area-data'
5. 获取数据修改如下,前端代码其他代码不做变动
地图所需数据格式为
[{"name":"内蒙古自治区","value":25},
{"name":"河北省","value":6},
{"name":"陕西省","value":2}]
本文从后台获取的数据为{"msg":"操作成功","code":200,"list":[{"name":"内蒙古自治区","value":25},{"name":"河北省","value":6},{"name":"陕西省","value":2}]}
数据是数组对象,其中name为省市名称,value是数值
methods: {
getData(code) {
let codeText=code
if(code!='china')
codeText = CodeToText[code];
getProblemsByProvinceCity(codeText).then(res => {
if (res.code == 200) {
this.getGeojson(code, res.list);
this.mapclick();
} else {
this.$Message.warning(res.msg)
}
}
)
},
6. 使用定时器轮询刷新
//轮询
switper() {
if (this.timer) {
return
}
let looper = (a) => {
this.getData()
};
this.timer = setInterval(looper, this.$store.state.settings.echartsAutoTime);
}
其中this.$store.state.settings.echartsAutoTime可替换成3000
7. provincecity.js增加api
// 查询用户数 export function getProvinceCityCount(code) { return request({ url: '/system/provinceCity/getProvinceCityCount/' + code, method: 'get' }) }
8. 增加controller后端方法
/** * 统计省市问题数量 */ @GetMapping("/getProvinceCityCount/{code}") public AjaxResult getProblemsByProvinceCity(@PathVariable("code") String code) { AjaxResult ajax = AjaxResult.success(); List<FProvinceCityCount> list=fProblemsService.countProblemsByProvinceCity(code); ajax.put("list", list); return ajax; }
9. center-map前端最终代码
<template>
<div class="centermap">
<div class="maptitle">
<div class="zuo"></div>
<span class="titletext">{{ maptitle }}</span>
<div class="you"></div>
</div>
<div class="mapwrap">
<dv-border-box-13>
<div class="quanguo" @click="getData('china')" v-if="code !== 'china'">
中国
</div>
<Echart id="CenterMap" :options="options" ref="CenterMap"/>
</dv-border-box-13>
</div>
</div>
</template>
<script>
import xzqCode from "../../../utils/bigScreen/map/xzqCode";
import {currentGET} from '@/api/bigScreen/modules'
import * as echarts from "echarts";
import { CodeToText } from 'element-china-area-data'
import {GETNOBASE} from '@/api/bigScreen/api'
import {getProblemsByProvinceCity} from "@/api/feedback/problems";
export default {
data() {
return {
maptitle: "现场分布图",
options: {},
timer: null,
code: "china", //china 代表中国 其他地市是行政编码
echartBindClick: false,
isSouthChinaSea: false, //是否要展示南海群岛 修改此值请刷新页面
};
},
created() {
},
mounted() {
// console.log(xzqCode);
this.getData("china")
},
methods: {
getData(code) {
let codeText=code
if(code!='china')
codeText = CodeToText[code];
console.log(code, codeText);
getProblemsByProvinceCity(codeText).then(res => {
if (res.code == 200) {
console.log('设备分布2', res);
this.getGeojson(code, res.list);
this.mapclick();
} else {
this.$Message.warning(res.msg)
}
}
)
},
//轮询
switper() {
if (this.timer) {
return
}
let looper = (a) => {
this.getData()
};
this.timer = setInterval(looper, this.$store.state.settings.echartsAutoTime);
},
async getGeojson(name, mydata) {
this.code = name;
//如果要展示南海群岛并且展示的是中国的话
let geoname = name
if (this.isSouthChinaSea && name == "china") {
geoname = "chinaNanhai";
}
//如果有注册地图的话就不用再注册 了
let mapjson = echarts.getMap(name);
if (mapjson) {
mapjson = mapjson.geoJSON;
} else {
mapjson = await GETNOBASE(`./map-geojson/${geoname}.json`).then((res) => {
return res;
});
echarts.registerMap(name, mapjson);
}
let cityCenter = {};
let arr = mapjson.features;
//根据geojson获取省份中心点
arr.map((item) => {
cityCenter[item.properties.name] =
item.properties.centroid || item.properties.center;
});
let newData = [];
mydata.map((item) => {
if (cityCenter[item.name]) {
newData.push({
name: item.name,
value: cityCenter[item.name].concat(item.value),
});
}
});
this.init(name, mydata, newData);
},
init(name, data, data2) {
let top = 45;
let zoom = 1.05;
if (name == "china") {
top = 40;
zoom = 1.05;
}
let option = {
backgroundColor: "rgba(0,0,0,0)",
tooltip: {
show: false,
},
legend: {
show: false,
},
visualMap: {
left: 20,
bottom: 20,
pieces: [
{gte: 1000, label: "1000个以上"}, // 不指定 max,表示 max 为无限大(Infinity)。
{gte: 600, lte: 999, label: "600-999个"},
{gte: 200, lte: 599, label: "200-599个"},
{gte: 50, lte: 199, label: "49-199个"},
{gte: 10, lte: 49, label: "10-49个"},
{lte: 9, label: "1-9个"}, // 不指定 min,表示 min 为无限大(-Infinity)。
],
inRange: {
// 渐变颜色,从小到大
color: [
"#c3d7df",
"#5cb3cc",
"#8abcd1",
"#66a9c9",
"#2f90b9",
"#1781b5",
],
},
textStyle: {
color: "#fff",
},
},
geo: {
map: name,
roam: false,
selectedMode: false, //是否允许选中多个区域
zoom: zoom,
top: top,
aspectScale: 0.78,
tooltip: {
show: false,
},
label: {
show: false,
}, //地图中文字内容及样式控制
itemStyle: {
areaColor: "rgba(0,0,0,0)",
borderColor: "rgba(0,0,0,0)",
},
emphasis: {
disabled: true,
},
},
series: [
{
name: "MAP",
type: "map",
mapType: name,
aspectScale: 0.78,
data: data,
// data: [1,100],
selectedMode: false, //是否允许选中多个区域
zoom: zoom,
geoIndex: 1,
top: top,
tooltip: {
show: true,
formatter: function (params) {
if (params.data) {
return params.name + ":" + params.data["value"];
} else {
return params.name;
}
},
backgroundColor: "rgba(0,0,0,.6)",
borderColor: "rgba(147, 235, 248, .8)",
textStyle: {
color: "#FFF",
},
},
label: {
show: false,
color: "#000",
// position: [-10, 0],
formatter: function (val) {
// console.log(val)
if (val.data !== undefined) {
return val.name.slice(0, 2);
} else {
return "";
}
},
rich: {},
emphasis: {show: false},
},
itemStyle: {
borderColor: "rgba(147, 235, 248, .8)",
borderWidth: 1,
areaColor: {
type: "radial",
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [
{
offset: 0,
color: "rgba(147, 235, 248, 0)", // 0% 处的颜色
},
{
offset: 1,
color: "rgba(147, 235, 248, .2)", // 100% 处的颜色
},
],
globalCoord: false, // 缺为 false
},
shadowColor: "rgba(128, 217, 248, .3)",
shadowOffsetX: -2,
shadowOffsetY: 2,
shadowBlur: 10,
emphasis: {
areaColor: "#389BB7",
borderWidth: 1,
},
},
},
{
data: data2,
type: "effectScatter",
coordinateSystem: "geo",
symbolSize: function (val) {
return 4;
// return val[2] / 50;
},
legendHoverLink: true,
showEffectOn: "render",
rippleEffect: {
// period: 4,
scale: 6,
color: "rgba(255,255,255, 1)",
brushType: "fill",
},
tooltip: {
show: true,
formatter: function (params) {
if (params.data) {
return params.name + ":" + params.data["value"][2];
} else {
return params.name;
}
},
backgroundColor: "rgba(0,0,0,.6)",
borderColor: "rgba(147, 235, 248, .8)",
textStyle: {
color: "#FFF",
},
},
label: {
formatter: (param) => {
return param.name.slice(0, 2);
},
fontSize: 11,
offset: [0, 2],
position: "bottom",
textBorderColor: "#fff",
textShadowColor: "#000",
textShadowBlur: 10,
textBorderWidth: 0,
color: "#FFF",
show: true,
},
// colorBy: "data",
itemStyle: {
color: "rgba(255,255,255,1)",
borderColor: "rgba(2255,255,255,2)",
borderWidth: 4,
shadowColor: "#000",
shadowBlur: 10,
},
},
],
};
this.options = option;
},
message(text) {
this.$Message({
text: text,
type: 'warning'
})
},
mapclick() {
if (this.echartBindClick) return;
//单击切换到级地图,当mapCode有值,说明可以切换到下级地图
this.$refs.CenterMap.chart.on("click", (params) => {
console.log("mapclick");
console.log(params);
let xzqData = xzqCode[params.name];
console.log(xzqData);
if (xzqData) {
this.getData(xzqData.adcode);
} else {
this.message("暂无下级地市!");
}
});
this.echartBindClick = true
},
},
};
</script>
<style lang='scss' scoped>
.centermap {
margin-bottom: 30px;
.maptitle {
height: 60px;
display: flex;
justify-content: center;
padding-top: 10px;
box-sizing: border-box;
.titletext {
font-size: 28px;
font-weight: 900;
letter-spacing: 6px;
background: linear-gradient(92deg,
#0072ff 0%,
#00eaff 48.8525390625%,
#01aaff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0 10px;
}
.zuo,
.you {
background-size: 100% 100%;
width: 29px;
height: 20px;
margin-top: 8px;
}
.zuo {
background: url("../../../assets/bigScreen/img/xiezuo.png") no-repeat;
}
.you {
background: url("../../../assets/bigScreen/img/xieyou.png") no-repeat;
}
}
.mapwrap {
height: 548px;
width: 100%;
// padding: 0 0 10px 0;
box-sizing: border-box;
position: relative;
.quanguo {
position: absolute;
right: 20px;
top: -46px;
width: 80px;
height: 28px;
border: 1px solid #00eded;
border-radius: 10px;
color: #00f7f6;
text-align: center;
line-height: 26px;
letter-spacing: 6px;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 237, 237, 0.5),
0 0 6px rgba(0, 237, 237, 0.4);
}
}
}
</style>