您好,登錄后才能下訂單哦!
這篇文章給大家介紹在vue中使用echarts和datav實(shí)現(xiàn)一個(gè)地圖功能,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
隨著前端技術(shù)的飛速發(fā)展,大數(shù)據(jù)時(shí)代的來(lái)臨,我們?cè)陂_(kāi)發(fā)項(xiàng)目時(shí)越來(lái)越多的客戶會(huì)要求我們做一個(gè)數(shù)據(jù)展示的大屏,可以直觀的展示用戶想要的數(shù)據(jù),同時(shí)炫酷的界面也會(huì)深受客戶的喜歡。
大屏展示其實(shí)就是一堆的圖表能夠讓人一目了然地看到該系統(tǒng)下的一些基本數(shù)據(jù)信息的匯總,也會(huì)有一些實(shí)時(shí)數(shù)據(jù)刷新,信息預(yù)警之類的。筆者在之前也做過(guò)一些大屏類的數(shù)據(jù)展示,但是由于都是一些圖表類的,覺(jué)得沒(méi)什么可說(shuō)的,加之?dāng)?shù)據(jù)也都牽扯到公司,所以沒(méi)有沉淀下來(lái)什么。
最近有朋友要做一個(gè)大屏,問(wèn)了自己一個(gè)問(wèn)題,自己也剛好做了一個(gè)簡(jiǎn)單的大屏數(shù)據(jù)展示,趁此機(jī)會(huì)做一個(gè)小總結(jié)。
先看一下效果:
由于數(shù)據(jù)牽扯到公司內(nèi)部信息,所以將一些復(fù)雜的切換邏輯都去掉類,但保留了一些數(shù)據(jù)間但相互聯(lián)動(dòng)。
項(xiàng)目采用的是Vue+Echanrts+datav寫的,結(jié)構(gòu)目錄如下:
由于只是一個(gè)單一頁(yè)面,數(shù)據(jù)處理也不是復(fù)雜,沒(méi)有涉及到router和vuex,從結(jié)構(gòu)目錄上看就是一個(gè)很典型的vue-cli項(xiàng)目,在之前我也講過(guò)關(guān)于vue-cli項(xiàng)目的一些操作和目錄結(jié)構(gòu)解釋,這里就不做多做說(shuō)明了,在文章最后會(huì)提供該項(xiàng)目的源碼地址庫(kù)。
大屏主要的炫酷效果本人引用的是datav組件,地址:http://datav.jiaminghi.com/,這簡(jiǎn)直就是數(shù)據(jù)可視化的一款神器,神奇之處我就不多說(shuō)了,大家可以自己去它的網(wǎng)站上自行體會(huì)。它也提供了如何在vue 中使用該組件。
datav可以全局注入,也可以按需注入,本人省事就直接在main.js中進(jìn)行了全局注入。
所有的頁(yè)面代碼都放在了views文件目錄下:
其中index.vue文件為主文件入口,其他都是其子組件,組件名稱以方位的形式命名,如centerForm.vue就是中間的表單控件。
本項(xiàng)目引入了中國(guó)地圖并實(shí)現(xiàn)省市縣下鉆,最初采用的是阿里旗下的高德地圖,后來(lái)因?yàn)榉N種原因改為了百度提供的Echarts來(lái)實(shí)現(xiàn),但兩種使用方法都保留了下來(lái),大家可以根據(jù)自己的需求進(jìn)行選擇。
其中Echarts中國(guó)地圖的代碼如下:
<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, // 實(shí)例化echarts provincesMap: cityProvincesMap.provincesMap, // 省拼音,用于查找對(duì)應(yīng)json provincesCode: cityProvincesMap.provincesCode, // 市行政區(qū)劃,用于查找對(duì)應(yīng)json areaMap: cityProvincesMap.areaMap, // 省行政區(qū)劃,用于數(shù)據(jù)的查找,按行政區(qū)劃查數(shù)據(jù) special: ["北京市", "天津市", "上海市", "重慶市", "香港", "澳門"],//直轄市和特別行政區(qū)-只有二級(jí)地圖,沒(méi)有三級(jí)地圖 mapData: [], // 當(dāng)前地圖上的地區(qū) option: {...mapOption.basicOption}, // map的相關(guān)配置 deepTree: [],// 點(diǎn)擊地圖時(shí)push,點(diǎn)返回時(shí)pop areaName: '中國(guó)', // 當(dāng)前地名 areaCode: '000000', // 當(dāng)前行政區(qū)劃 areaLevel: 'country', // 當(dāng)前級(jí)別 } }, 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}) } }, // 地圖點(diǎn)擊 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; //如果點(diǎn)擊的是34個(gè)省、市、自治區(qū),繪制選中地區(qū)的二級(jí)地圖 this.requestGetProvinceJSON(params.data); } else if (params.seriesName in this.provincesMap) { //如果是【直轄市/特別行政區(qū)】只有二級(jí)下鉆 if (this.special.indexOf(params.seriesName) >= 0) { return; } else { this.areaCode = this.areaMap[params.name]; this.areaLevel = params.data.areaLevel; //顯示縣級(jí)地圖 this.requestGetCityJSON(params.data) } } else { return; } this.$emit('map-change', params.data); }, //繪制全國(guó)地圖 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'} }); //注冊(cè)地圖 this.$echarts.registerMap('china', res); //繪制地圖 this.renderMap('china', arr); }); }, // 加載省級(jí)地圖 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); }); }, // 加載市級(jí)地圖 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)用省市地圖時(shí)本人采用的是將地圖信息的json存放在了本地,這是由于本人的項(xiàng)目中很多地市的行政區(qū)劃很多需要變動(dòng),這也是放棄高德地圖的原因之一。json文件放在了public文件目錄下,如下圖:
里面有一些自己沒(méi)用到的json數(shù)據(jù)本人進(jìn)行了刪除,關(guān)于中國(guó)詳細(xì)的json數(shù)據(jù)大家可以去https://datav.aliyun.com/tools/atlas/下載,內(nèi)容由高德開(kāi)放平臺(tá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: '中國(guó)', 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, //返回下一級(jí)行政區(qū) showbiz: false //最后一級(jí)返回街道信息 }; this.district = new AMap.DistrictSearch(this.opts);//注意:需要使用插件同步下發(fā)功能才能這樣直接使用 this.district.search('中國(guó)', (status, result) => { if (status == 'complete') { this.getData(result.districtList[0], '', 100000); } }); }, methods: { //地圖點(diǎn)擊事件 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ū)級(jí)別 this.district.setExtensions('all'); //行政區(qū)查詢 //按照adcode進(jìn)行查詢可以保證數(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)建一個(gè)實(shí)例 var districtExplorer = window.districtExplorer = new DistrictExplorer({ eventSupport: true, //打開(kāi)事件支持 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: '危險(xiǎn)', 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) } //清空下一級(jí)別的下拉列表 if (level === 'province') { this.citySelect.innerHTML = ''; this.districtSelect.innerHTML = ''; } else if (level === 'city') { this.districtSelect.innerHTML = ''; } var subList = data.districtList; if (subList) { let optionName = '--請(qǐng)選擇--'; 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ū)級(jí)別 this.district.setExtensions('all'); //行政區(qū)查詢 //按照adcode進(jìn)行查詢可以保證數(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>
關(guān)于在vue中使用echarts和datav實(shí)現(xiàn)一個(gè)地圖功能就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。