Vue3 + Echarts 5 繪製帶有立體感流線中國地圖,建議收藏
阿新 • • 發佈:2022-04-06
本文繪製的地圖效果圖如下:
一、Echarts 使用五部曲
1、下載並引入 echarts
Echarts 已更新到了 5.0 版本,安裝完記得檢查下自己的版本是否是 5.0 。
npm install echarts --save
下載地圖的 json 資料
可以下載中國以及各個省份地圖資料。免費的檔案下載地址:
http://datav.aliyun.com/portal/school/atlas/area_selector#&lat=30.332329214580188&lng=106.72278672066881&zoom=3.5
記得收藏哦!免得浪費加班時間。
引入:
import * as echarts from "echarts" import chinaJSON from'../../assets/json/china.json'
2、準備容器
給元素定義寬高確定的容器用來裝地圖。
<template> <div id="chinaMap"></div> </template>
3、例項化 echarts 物件
import * as echarts from 'echarts' import chinaJson from '../../assets/json/china.json' var myChart = echarts.init(document.getElementById('chinaMap'))// 建立了一個 myChart 物件
4、指定配置項和資料
var option = { // 存放需要繪製圖片型別,以及樣式設定 }
5、給 echarts 物件設定配置項
myChart.setOption(option)
就這麼簡單幾步還用你告訴我嗎?不瞞你說,官網也有這東東。雖然這些你都知道,但是並不影響你還是不知道流線圖是怎麼繪製出來的。下面我們看看是如何繪製的。
二、開始繪製流線中國地圖
第一步:先繪製一箇中國地圖
import * as echarts from 'echarts' import chinaJson from '../../assets/json/china.json' import { onMounted, ref } from'vue' const chinaMap = ref() onMounted(() => { drawChina() }) function drawChina() { var myChart = echarts.init(chinaMap.value) echarts.registerMap('china', chinaJson) //註冊可用的地圖 var option = { geo: { show: true, //設定中心點 center: [105.194115019531, 35.582111640625], map: 'china', roam: true, //是否允許縮放,拖拽 zoom: 1, //初始化大小 //縮放大小限制 scaleLimit: { min: 0.1, //最小 max: 12, //最大 }, //各個省份模組樣式設定 itemStyle: { normal: { areaColor: '#3352c7',//背景色 color: 'red',//字型顏色 borderColor: '#5e84fd', borderWidth: 2, }, }, //高亮狀態 emphasis: { itemStyle: { areaColor: '#ffc601', }, label: { show: true, color: '#fff', }, }, // 顯示層級 z: 10, }, } myChart.setOption(option) }
一個簡單的地圖就繪製好了,繼續研究如何新增流線。
第二步:新增流線
通過 series 屬性來設定髮色點的樣式,接受點的樣式,以及線條和線條上的動畫。
設定 series 的值:
// 中國地理座標圖 var chinaGeoCoordMap: Object = { 西安: [108.906866, 34.162109], 拉薩: [91.140856, 29.645554], } //發射點 var chinaDatas = [ [ { name: '拉薩', value: 2, }, ], ] //投射點 const scatterPos = [108.906866, 34.162109] // 資料轉換 var convertData = function (data: any) { var res = [] for (var i = 0; i < data.length; i++) { var dataItem = data[i] var fromCoord = chinaGeoCoordMap[dataItem[0].name] var toCoord = scatterPos if (fromCoord && toCoord) { res.push([ { coord: fromCoord, value: dataItem[0].value, }, { coord: toCoord, }, ]) } } return res } var series: Array<any> = [] ;[['西安', chinaDatas]].forEach(function (item, i) { series.push( //設定指向箭頭資訊 { type: 'lines', zlevel: 2, effect: { show: true, period: 4, //箭頭指向速度,值越小速度越快 trailLength: 0.02, //特效尾跡長度[0,1]值越大,尾跡越長重 symbol: 'arrow', //箭頭圖示 symbolSize: 8, //圖示大小 }, lineStyle: { normal: { color: '#adffd0', width: 1, //尾跡線條寬度 opacity: 1, //尾跡線條透明度 curveness: 0.3, //尾跡線條曲直度 }, }, data: convertData(item[1]), }, // 發射點位置漣漪等效果 { type: 'effectScatter', coordinateSystem: 'geo', zlevel: 2, rippleEffect: { //漣漪特效 period: 4, //動畫時間,值越小速度越快 brushType: 'stroke', //波紋繪製方式 stroke, fill scale: 4, //波紋圓環最大限制,值越大波紋越大 }, label: { normal: { show: true, position: 'right', //顯示位置 offset: [5, 0], //偏移設定 formatter: function (params) { //圓環顯示文字 return params.data.name }, fontSize: 13, }, emphasis: { show: true, }, }, symbol: 'circle', symbolSize: function (val: Array<any>) { return 5 + val[2] * 5 //圓環大小 }, itemStyle: { normal: { show: false, color: '#f8f9f5', }, }, data: item[1].map(function (dataItem: any) { return { name: dataItem[0].name, value: chinaGeoCoordMap[dataItem[0].name].concat([dataItem[0].value]), } }), }, //被攻擊點 { type: 'effectScatter', coordinateSystem: 'geo', zlevel: 2, rippleEffect: { //漣漪相關 period: 2, brushType: 'stroke', scale: 5, }, label: { normal: { show: true, position: 'right', color: '#0f0', formatter: '{b}', textStyle: { color: '#fff', fontSize: 12, }, }, emphasis: { show: true, color: '#f60', }, }, itemStyle: { normal: { color: '#f00', }, }, symbol: 'circle', symbolSize: 10, //圓圈大小 data: [ { name: item[0], value: chinaGeoCoordMap[item[0]].concat([10]), }, ], }, ) })
給上邊的 option 新增 series 屬性。
第三步:新增立體投影
新增立體投影的時候,由於並沒有這樣的屬性,所以需要通過設定邊框投影,再加一個偏移。
實現原理:繪製兩個地圖,設定中心點是一樣的,然後一個設定邊框投影+偏移,它的層級設定小一點,上邊再繪製一個地圖不設定投影,這樣就能夠實現上述效果。
// series 新增一個物件,繪製新地圖 { //繪製一個新地圖 type: 'map', map: 'china', zoom: 1, center: [105.194115019531, 35.582111640625], z: -1, aspectScale: 0.75, // itemStyle: { normal: { areaColor: '#f00', borderColor: '#090438', borderWidth: '2', shadowColor: '#090438', shadowOffsetX: 0, shadowOffsetY: 15, }, }, }
上述效果的完整原始碼:
<template> <div> 首頁 <div ref="chinaMap" class="chinaMap" style=" height: 800px; border: solid 1px red; width: 100%; background: #0b0873; " > 地圖1 </div> </div> </template> <style scoped> .chinaMap { transform: rotate3d(1, 0, 0, 35deg); } </style> <script lang="ts" setup> import * as echarts from 'echarts' import chinaJson from '../../assets/json/china.json' import { onMounted, ref } from 'vue' const chinaMap = ref() onMounted(() => { drawChina() }) /**************************** series start ************************************/ //中國地理座標圖 var chinaGeoCoordMap: Object = { 西安: [108.906866, 34.162109], 柯橋區: [120.476075, 30.078038], 拉薩: [91.140856, 29.645554], 瀋陽: [123.431474, 41.805698], 新疆: [87.627704, 43.793026], 臺灣: [121.508903, 25.044319], } var chinaDatas = [ [ { name: '柯橋區', value: 0, }, ], [ { name: '拉薩', value: 2, }, ], [ { name: '瀋陽', value: 1, }, ], [ { name: '新疆', value: 1, }, ], [ { name: '臺灣', value: 1, }, ], ] //設定投射點 const scatterPos = [108.906866, 34.162109] var convertData = function (data: any) { var res = [] for (var i = 0; i < data.length; i++) { var dataItem = data[i] var fromCoord = chinaGeoCoordMap[dataItem[0].name] var toCoord = scatterPos if (fromCoord && toCoord) { res.push([ { coord: fromCoord, value: dataItem[0].value, }, { coord: toCoord, }, ]) } } console.log('res', res) return res } var series: Array<any> = [] ;[['西安', chinaDatas]].forEach(function (item, i) { console.log(item, item[0]) series.push( { //繪製一個新地圖 type: 'map', map: 'china', zoom: 1, center: [105.194115019531, 35.582111640625], z: -1, aspectScale: 0.75, // itemStyle: { normal: { areaColor: '#f00', borderColor: '#090438', borderWidth: '2', shadowColor: '#090438', shadowOffsetX: 0, shadowOffsetY: 15, }, }, }, //設定指向箭頭資訊 { type: 'lines', zlevel: 2, effect: { show: true, period: 4, //箭頭指向速度,值越小速度越快 trailLength: 0.02, //特效尾跡長度[0,1]值越大,尾跡越長重 symbol: 'arrow', //箭頭圖示 symbolSize: 8, //圖示大小 }, lineStyle: { normal: { color: '#adffd0', width: 1, //尾跡線條寬度 opacity: 1, //尾跡線條透明度 curveness: 0.3, //尾跡線條曲直度 }, }, data: convertData(item[1]), }, // 發射點位置漣漪等效果 { type: 'effectScatter', coordinateSystem: 'geo', zlevel: 2, rippleEffect: { //漣漪特效 period: 4, //動畫時間,值越小速度越快 brushType: 'stroke', //波紋繪製方式 stroke, fill scale: 4, //波紋圓環最大限制,值越大波紋越大 }, label: { normal: { show: true, position: 'right', //顯示位置 offset: [5, 0], //偏移設定 formatter: function (params) { //圓環顯示文字 return params.data.name }, fontSize: 13, }, emphasis: { show: true, }, }, symbol: 'circle', symbolSize: function (val: Array<any>) { return 5 + val[2] * 5 //圓環大小 }, itemStyle: { normal: { show: false, color: '#f8f9f5', }, }, data: item[1].map(function (dataItem: any) { return { name: dataItem[0].name, value: chinaGeoCoordMap[dataItem[0].name].concat([dataItem[0].value]), } }), }, //被攻擊點 { type: 'effectScatter', coordinateSystem: 'geo', zlevel: 2, rippleEffect: { //漣漪相關 period: 2, brushType: 'stroke', scale: 5, }, label: { normal: { show: true, position: 'right', // offset:[5, 0], color: '#0f0', formatter: '{b}', textStyle: { color: '#fff', fontSize: 12, }, }, emphasis: { show: true, color: '#f60', }, }, itemStyle: { normal: { color: '#f00', }, }, symbol: 'circle', symbolSize: 10, //圓圈大小 data: [ { name: item[0], value: chinaGeoCoordMap[item[0]].concat([10]), }, ], }, ) }) /****************************************************************/ function drawChina() { var myChart = echarts.init(chinaMap.value) echarts.registerMap('china', chinaJson) //註冊可用的地圖 var option = { tooltip: { trigger: 'item', backgroundColor: 'rgba(166, 200, 76, 0.82)', borderColor: '#FFFFCC', showDelay: 0, hideDelay: 0, enterable: true, transitionDuration: 0, extraCssText: 'z-index:100', formatter: function (params, ticket, callback) { //根據業務自己拓展要顯示的內容 var res = '' var name = params.name var value = params.value[params.seriesIndex + 1] res = "<span style='color:#fff;'>" + name + '</span><br/>資料:' + value return res }, }, geo: { show: true, center: [105.194115019531, 35.582111640625], map: 'china', roam: true, //是否允許縮放,拖拽 zoom: 1, //初始化大小 //縮放大小限制 scaleLimit: { min: 0.1, //最小 max: 12, //最大 }, //設定中心點 //center: [95.97, 29.71], //省份地圖新增背景 //regions: regions, itemStyle: { normal: { areaColor: '#3352c7', color: 'red', borderColor: '#5e84fd', borderWidth: 2, }, }, label: { color: 'rgba(255,255,255,0.5)', show: false, }, //高亮狀態 emphasis: { itemStyle: { areaColor: '#ffc601', }, label: { show: true, color: '#fff', }, }, z: 10, }, //配置屬性 series: series, } myChart.setOption(option) } </script>