vue+echarts+datav大屏數(shù)據(jù)展示及實現(xiàn)中國地圖省市縣下鉆功能
隨著前端技術(shù)的飛速發(fā)展,大數(shù)據(jù)時代的來臨,我們在開發(fā)項目時越來越多的客戶會要求我們做一個數(shù)據(jù)展示的大屏,可以直觀的展示用戶想要的數(shù)據(jù),同時炫酷的界面也會深受客戶的喜歡。
大屏展示其實就是一堆的圖表能夠讓人一目了然地看到該系統(tǒng)下的一些基本數(shù)據(jù)信息的匯總,也會有一些實時數(shù)據(jù)刷新,信息預(yù)警之類的。筆者在之前也做過一些大屏類的數(shù)據(jù)展示,但是由于都是一些圖表類的,覺得沒什么可說的,加之數(shù)據(jù)也都牽扯到公司,所以沒有沉淀下來什么。
最近有朋友要做一個大屏,問了自己一個問題,自己也剛好做了一個簡單的大屏數(shù)據(jù)展示,趁此機會做一個小總結(jié)。
先看一下效果:

由于數(shù)據(jù)牽扯到公司內(nèi)部信息,所以將一些復(fù)雜的切換邏輯都去掉類,但保留了一些數(shù)據(jù)間但相互聯(lián)動。
項目采用的是Vue+Echanrts+datav寫的,結(jié)構(gòu)目錄如下:

由于只是一個單一頁面,數(shù)據(jù)處理也不是復(fù)雜,沒有涉及到router和vuex,從結(jié)構(gòu)目錄上看就是一個很典型的vue-cli項目,在之前我也講過關(guān)于vue-cli項目的一些操作和目錄結(jié)構(gòu)解釋,這里就不做多做說明了,在文章最后會提供該項目的源碼地址庫。
大屏主要的炫酷效果本人引用的是datav組件,地址:http://datav.jiaminghi.com/,這簡直就是數(shù)據(jù)可視化的一款神器,神奇之處我就不多說了,大家可以自己去它的網(wǎng)站上自行體會。它也提供了如何在vue 中使用該組件。
datav可以全局注入,也可以按需注入,本人省事就直接在main.js中進行了全局注入。

所有的頁面代碼都放在了views文件目錄下:

其中index.vue文件為主文件入口,其他都是其子組件,組件名稱以方位的形式命名,如centerForm.vue就是中間的表單控件。
本項目引入了中國地圖并實現(xiàn)省市縣下鉆,最初采用的是阿里旗下的高德地圖,后來因為種種原因改為了百度提供的Echarts來實現(xiàn),但兩種使用方法都保留了下來,大家可以根據(jù)自己的需求進行選擇。
其中Echarts中國地圖的代碼如下:
<template>
<div id="china_map_box">
<el-button type="primary" size="mini" class="back" @click="back" v-if="deepTree.length > 1">返回</el-button>
<div class="echarts">
<div id="map"></div>
</div>
</div>
</template>
<script>
import {getChinaJson, getProvinceJSON, getCityJSON} from "../api/get-json";
import {cityProvincesMap} from '../config/cityProvincesMap'
import {mapOption} from '../config/mapOption'
export default {
name: "china",
components: {},
data() {
return {
chart: null, // 實例化echarts
provincesMap: cityProvincesMap.provincesMap, // 省拼音,用于查找對應(yīng)json
provincesCode: cityProvincesMap.provincesCode, // 市行政區(qū)劃,用于查找對應(yīng)json
areaMap: cityProvincesMap.areaMap, // 省行政區(qū)劃,用于數(shù)據(jù)的查找,按行政區(qū)劃查數(shù)據(jù)
special: ["北京市", "天津市", "上海市", "重慶市", "香港", "澳門"],//直轄市和特別行政區(qū)-只有二級地圖,沒有三級地圖
mapData: [], // 當前地圖上的地區(qū)
option: {...mapOption.basicOption}, // map的相關(guān)配置
deepTree: [],// 點擊地圖時push,點返回時pop
areaName: '中國', // 當前地名
areaCode: '000000', // 當前行政區(qū)劃
areaLevel: 'country', // 當前級別
}
},
mounted() {
this.$nextTick(() => {
this.initEcharts();
this.chart.on('click', this.echartsMapClick);
});
},
methods: {
// 初次加載繪制地圖
initEcharts() {
//地圖容器
this.chart = this.$echarts.init(document.getElementById('map'));
if (this.areaCode === '000000') {
this.requestGetChinaJson();
} else {
this.requestGetProvinceJSON({areaName: this.areaName, areaCode: this.areaCode})
}
},
// 地圖點擊
echartsMapClick(params) {
// console.log(params);
this.areaName = params.areaName;
if (params.name in this.provincesMap) {
this.areaCode = params.data.areaCode;
this.areaLevel = params.data.areaLevel;
//如果點擊的是34個省、市、自治區(qū),繪制選中地區(qū)的二級地圖
this.requestGetProvinceJSON(params.data);
} else if (params.seriesName in this.provincesMap) {
//如果是【直轄市/特別行政區(qū)】只有二級下鉆
if (this.special.indexOf(params.seriesName) >= 0) {
return;
} else {
this.areaCode = this.areaMap[params.name];
this.areaLevel = params.data.areaLevel;
//顯示縣級地圖
this.requestGetCityJSON(params.data)
}
} else {
return;
}
this.$emit('map-change', params.data);
},
//繪制全國地圖
requestGetChinaJson() {
getChinaJson().then(res => {
let arr = [];
for (let i = 0; i < res.features.length; i++) {
let obj = {
name: res.features[i].properties.name,
areaName: res.features[i].properties.name,
areaCode: res.features[i].id,
areaLevel: 'province',
value: Math.round(Math.random()),
};
arr.push(obj)
}
this.mapData = arr;
this.deepTree.push({
mapData: arr,
params: {name: 'china', areaName: 'china', areaLevel: 'country', areaCode: '000000'}
});
//注冊地圖
this.$echarts.registerMap('china', res);
//繪制地圖
this.renderMap('china', arr);
});
},
// 加載省級地圖
requestGetProvinceJSON(params) {
getProvinceJSON(params.areaCode).then(res => {
this.$echarts.registerMap(params.areaName, res);
let arr = [];
for (let i = 0; i < res.features.length; i++) {
let obj = {
name: res.features[i].properties.name,
areaName: res.features[i].properties.name,
areaCode: res.features[i].id,
areaLevel: 'city',
value: Math.round(Math.random()),
};
arr.push(obj)
}
this.mapData = arr;
this.deepTree.push({
mapData: arr,
params: params,
});
this.renderMap(params.areaName, arr);
});
},
// 加載市級地圖
requestGetCityJSON(params) {
this.areaLevel = params.areaLevel;
getCityJSON(params.areaCode).then(res => {
this.$echarts.registerMap(params.areaName, res);
let arr = [];
for (let i = 0; i < res.features.length; i++) {
let obj = {
name: res.features[i].properties.name,
areaName: res.features[i].properties.areaName,
areaCode: res.features[i].id,
areaLevel: 'districts',
value: Math.round(Math.random()),
};
arr.push(obj)
}
this.mapData = arr;
this.deepTree.push({mapData: arr, params: params});
this.renderMap(params.areaName, arr);
})
},
renderMap(map, data) {
this.option.series = [
{
name: map,
mapType: map,
...mapOption.seriesOption,
data: data
}
];
//渲染地圖
this.chart.setOption(this.option);
},
// 返回
back() {
// console.log(this.deepTree);
if (this.deepTree.length > 1) {
this.deepTree.pop();
let areaName = this.deepTree[this.deepTree.length - 1].params.areaName;
let mapData = this.deepTree[this.deepTree.length - 1].mapData;
this.$emit('back-change', this.deepTree[this.deepTree.length - 1].params);
this.renderMap(areaName, mapData);
}
}
}
}
</script>
<style lang="scss" scoped>
#china_map_box {
display: flex;
width: 100%;
height: 100%;
position: relative;
.echarts {
width: 0;
flex: 1;
background-size: 100% 100%;
#map {
height: 100%;
}
}
.back {
position: absolute;
top: .8rem;
right: .5rem;
z-index: 999;
padding-left: .12rem;
padding-right: .12rem;
}
}
</style>
在調(diào)用省市地圖時本人采用的是將地圖信息的json存放在了本地,這是由于本人的項目中很多地市的行政區(qū)劃很多需要變動,這也是放棄高德地圖的原因之一。json文件放在了public文件目錄下,如下圖:

里面有一些自己沒用到的json數(shù)據(jù)本人進行了刪除,關(guān)于中國詳細的json數(shù)據(jù)大家可以去https://datav.aliyun.com/tools/atlas/下載,內(nèi)容由高德開放平臺提供。
高德地圖chinaGaode.vue代碼如下:
<template>
<div id="china_map_box">
<el-button type="primary" size="mini" class="back" @click="back">返回</el-button>
<div class="map" >
<map-range @change="search"></map-range>
</div>
<div class="echarts">
<div id="map"></div>
</div>
</div>
</template>
<script>
import mapRange from "./mapRange";
export default {
name: "chinaGaode",
components: {
mapRange
},
data() {
return {
provinceSelect: null,
citySelect: null,
districtSelect: null,
areaName: '中國',
geoJsonData: '',
echartsMap: null,
map: null,
district: null,
polygons: [],
areaCode: 100000,
opts: {},
areaData: {},
mapData: [],
deepTree:[],
}
},
mounted() {
this.provinceSelect = document.getElementById('province');
this.citySelect = document.getElementById('city');
this.districtSelect = document.getElementById('district');
this.deepTree = [{mapData: this.mapData,code: 100000}];
this.echartsMap = this.$echarts.init(document.getElementById('map'));
this.echartsMap.on('click', this.echartsMapClick);
this.map = new AMap.Map('container', {
resizeEnable: true,
center: [116.30946, 39.937629],
zoom: 3
});
this.opts = {
subdistrict: 1, //返回下一級行政區(qū)
showbiz: false //最后一級返回街道信息
};
this.district = new AMap.DistrictSearch(this.opts);//注意:需要使用插件同步下發(fā)功能才能這樣直接使用
this.district.search('中國', (status, result) => {
if (status == 'complete') {
this.getData(result.districtList[0], '', 100000);
}
});
},
methods: {
//地圖點擊事件
echartsMapClick(params) {
if (params.data.level == 'street') return;
//清除地圖上所有覆蓋物
for (var i = 0, l = this.polygons.length; i < l; i++) {
this.polygons[i].setMap(null);
}
this.areaName = params.data.name;
this.areaCode = params.data.areaCode;
this.district.setLevel(params.data.level); //行政區(qū)級別
this.district.setExtensions('all');
//行政區(qū)查詢
//按照adcode進行查詢可以保證數(shù)據(jù)返回的唯一性
this.district.search(this.areaCode, (status, result) => {
if (status === 'complete') {
this.deepTree.push({mapData: this.mapData,code: params.data.areaCode});
this.getData(result.districtList[0], params.data.level, this.areaCode);
}
});
this.$emit('map-change', params.data);
},
loadMapData(areaCode) {
AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => {
//創(chuàng)建一個實例
var districtExplorer = window.districtExplorer = new DistrictExplorer({
eventSupport: true, //打開事件支持
map: this.map
});
districtExplorer.loadAreaNode(areaCode, (error, areaNode) => {
if (error) {
console.error(error);
return;
}
let mapJson = {};
mapJson.type = "FeatureCollection";
mapJson.features = areaNode.getSubFeatures();
this.loadMap(this.areaName, mapJson);
this.geoJsonData = mapJson;
});
});
},
loadMap(mapName, data) {
if (data) {
this.$echarts.registerMap(mapName, data);
var option = {
visualMap: {
type: 'piecewise',
pieces: [
{max: 1, label: '審核完成', color: '#2c9a42'},
{min: -1, max: 1, label: '未完成', color: '#d08a00'},
// {min: 60, label: '危險', color: '#c23c33'},
],
color: '#fff',
textStyle: {
color: '#fff',
},
visibility: 'off',
top:50,
left:30,
},
series: [{
name: '數(shù)據(jù)名稱',
type: 'map',
roam: false,
mapType: mapName,
selectedMode: 'single',
showLegendSymbol: false,
visibility: 'off',
itemStyle: {
normal: {
color: '#ccc',
areaColor: '#fff',
borderColor: '#fff',
borderWidth: 0.5,
label: {
show: true,
textStyle: {
color: "rgb(249, 249, 249)",
fontSize: '1rem'
}
}
},
emphasis: {
areaColor: false,
borderColor: '#fff',
areaStyle: {
color: '#fff'
},
label: {
show: true,
textStyle: {
color: "rgb(249, 249, 249)"
}
}
}
},
data: this.mapData,
}]
};
this.echartsMap.setOption(option);
}
},
getData(data, level, adcode) {
var bounds = data.boundaries;
if (bounds) {
for (var i = 0, l = bounds.length; i < l; i++) {
var polygon = new AMap.Polygon({
map: this.map,
strokeWeight: 1,
strokeColor: '#0091ea',
fillColor: '#80d8ff',
fillOpacity: 0.2,
path: bounds[i]
});
this.polygons.push(polygon);
}
this.map.setFitView();//地圖自適應(yīng)
}
//清空下一級別的下拉列表
if (level === 'province') {
this.citySelect.innerHTML = '';
this.districtSelect.innerHTML = '';
} else if (level === 'city') {
this.districtSelect.innerHTML = '';
}
var subList = data.districtList;
if (subList) {
let optionName = '--請選擇--';
var contentSub = new Option(optionName);
var curlevel = subList[0].level;
if (curlevel === 'street') {
let mapJsonList = this.geoJsonData.features;
let mapJson = {};
for (let i in mapJsonList) {
if (mapJsonList[i].properties.name == this.areaName) {
mapJson.type = "FeatureCollection";
mapJson.features = [].concat(mapJsonList[i]);
}
}
this.mapData = [];
this.mapData.push({name: this.areaName, value: 0, level: curlevel});
this.loadMap(this.areaName, mapJson);
return;
}
var curList = document.querySelector('#' + curlevel);
curList.add(contentSub);
this.mapData = [];
for (var i = 0, l = subList.length; i < l; i++) {
var name = subList[i].name;
var areaCode = subList[i].adcode;
this.mapData.push({
name: name,
value: Math.round(Math.random()),
areaCode: areaCode,
level: curlevel
});
var levelSub = subList[i].level;
contentSub = new Option(name);
contentSub.setAttribute("value", levelSub);
contentSub.center = subList[i].center;
contentSub.adcode = subList[i].adcode;
curList.add(contentSub);
}
this.loadMapData(adcode);
this.areaData[curlevel] = curList;
}
},
search(area) {
let obj = this.areaData[area];
//清除地圖上所有覆蓋物
for (var i = 0, l = this.polygons.length; i < l; i++) {
this.polygons[i].setMap(null);
}
var option = obj[obj.options.selectedIndex];
var keyword = option.text; //關(guān)鍵字
var adcode = option.adcode;
this.areaName = keyword;
this.areaCode = adcode;
this.district.setLevel(option.value); //行政區(qū)級別
this.district.setExtensions('all');
//行政區(qū)查詢
//按照adcode進行查詢可以保證數(shù)據(jù)返回的唯一性
this.district.search(adcode, (status, result) => {
if (status === 'complete') {
this.deepTree.push({mapData: this.mapData,code:adcode});
this.getData(result.districtList[0], obj.id, adcode);
}
});
var params = {
areaCode: adcode,
level: area,
name: keyword,
value: '',
};
this.$emit('map-change', params);
},
back() {
// console.log(this.deepTree)
if (this.deepTree.length > 1) {
this.mapData = this.deepTree[this.deepTree.length - 1].mapData;
this.deepTree.pop();
// console.log(this.deepTree[this.deepTree.length - 1], 'back');
this.loadMapData(this.deepTree[this.deepTree.length - 1].code)
}
}
}
}
</script>
<style lang="scss" scoped>
#china_map_box {
display: flex;
width: 100%;
height: 100%;
position: relative;
.echarts {
width: 0;
flex: 1;
background-size: 100% 100%;
#map {
height: 100%;
}
}
.back {
position: absolute;
top: .8rem;
right: .5rem;
z-index: 999;
}
}
</style>
在網(wǎng)上有很多下伙伴都在查找如何使用中國地圖并實現(xiàn)下鉆,在實際使用地圖時其實并不難,以上是本人提供的一些解決方案和代碼提供。
由于代碼是從本人的一個項目中剝離而來,代碼的質(zhì)量可能欠佳,有些邏輯處理和傅子組件間的數(shù)據(jù)聯(lián)動也都有所減少,但并不影響該項目demo的使用,如果有需要大家可以去以下地址下載源碼學(xué)習(xí),也歡迎star。
gitee源碼地址:https://gitee.com/vijtor/vue-map-datav
到此這篇關(guān)于vue+echarts+datav大屏數(shù)據(jù)展示及實現(xiàn)中國地圖省市縣下鉆的文章就介紹到這了,更多相關(guān)vue+echarts大屏數(shù)據(jù)展示內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue+echarts實現(xiàn)可拖動節(jié)點的折線圖(支持拖動方向和上下限的設(shè)置)
制作一個折線圖用于顯示當前24小時的數(shù)據(jù),并且可以通過拖動折現(xiàn)圖設(shè)置數(shù)據(jù),接下來通過本文給大家分享vue+echarts實現(xiàn)可拖動節(jié)點的折線圖(支持拖動方向和上下限的設(shè)置),感興趣的朋友跟隨一起學(xué)習(xí)吧2019-04-04
Django+Vue實現(xiàn)WebSocket連接的示例代碼
這篇文章主要介紹了Django+Vue實現(xiàn)WebSocket連接的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05

