之前研究過研究過百度地圖配合echarts實作熱力地圖和大量标注點加載,有興趣可檢視部落格https://www.cnblogs.com/class1/p/13691867.html。結果效果不是太理想,進而轉戰高德地圖。
最終效果圖先展示一波。
圖上效果圖的實作主要有五點:
一,高德地圖的引入。
引入地圖,和百度地圖一樣,還是要申請自己使用的key值,網上講解很多,這裡不再細述。有了key值以後,在全局的入口html檔案中引入高德地圖,我使用的是antd pro架構,入口檔案是document.ejs。如果不想申請key值,直接複制粘貼下面的就可以行。
然後直接在項目裡建立頁面檔案,寫你的地圖就完了,非常友善。這裡我建立的地圖檔案命名為guidemap.js.
二,熱力地圖的實作。
關鍵部分代碼:
// 建立地圖,gaoDe為地圖容器标簽的id名const map = new AMap.Map('gaoDe', { resizeEnable: true, // 允許縮放地圖 center: [108.5, 34.3], // 地圖中心點經緯度 zoom: 4 // 地圖的等級,範圍是3~18級 }); let heatmap; map.plugin(["AMap.Heatmap"], function () { // 初始化heatmap對象 heatmap = new AMap.Heatmap(map, { radius: 25, // 給定半徑 opacity: [0, 0.8], gradient:{ // 熱力值的顔色設定,範圍是0-1,可以分段設定顔色 0.5: 'blue', 0.65: 'rgb(117,211,248)', 0.7: 'rgb(0, 255, 0)', 0.9: '#ffea00', 1.0: 'red' } }); heatmap.setDataSet({ data: gaoData, // heatmapData 熱力地圖的資料,這裡的資料格式 [ {"lng": 116.191031,"lat": 39.988585,"count": 10},{...}] max: 10 // 熱力最大範圍值 }) });
效果圖如下:
三,控件的添加。
關鍵部分代碼:
const scale = new AMap.Scale({ visible: true, offset: new AMap.Pixel(70,20), // 控件的偏移位置 }); map.addControl(scale); // 添加比例尺控件 map.addControl(new AMap.ToolBar()); // 添加縮放控件
因為是熱力圖,一般圖上會有個熱力标尺,但是高德地圖沒有,可以将高德地圖引入echarts圖表中,通過配置項加熱力标尺(visualMap屬性)。但是考慮到高德地圖的功能比較完備,為了一個屬性引入echarts,太大費周章。今天我決定手寫個熱力标尺:
10
這個是在react項目裡寫的html,css樣式這麼寫沒問題的。
看下添加的控件效果:這個手寫的熱力标尺毫無違和感是不是。
四,海量點标記的添加。
// 海量點标記 const mass = new AMap.MassMarks(massData, { opacity: 0.8, zIndex: 111, cursor: 'pointer', style: { url: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png', // 點标注用的圖檔,可自定義 anchor: new AMap.Pixel(6, 6), // 位置偏移 size: new AMap.Size(15, 15) // 标注的大小 } }); mass.setMap(map);
此時就是頁面标注點和熱力圖結合了,但是标注點還沒有添加資訊窗,點選是沒有效果的。如果标注點不是太多,也可以不用海量點,直接建立mark,每一個依次添加就行
const allLength=gaoData.length; // 擷取标注點的個數 for(let i = 0; i < allLength; i += 1){ // 把每個點都添加在地圖上 const marker = new AMap.Marker({ position: [gaoData[i].lng, gaoData[i].lat], map:map }); }
五,點标記的資訊窗的添加。
點标記應該和上面的四合起來用的。如果是海量點,加資訊窗如下:
const mass = new AMap.MassMarks(massData, { opacity: 0.8, zIndex: 111, cursor: 'pointer', style: { url: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png', anchor: new AMap.Pixel(6, 6), size: new AMap.Size(15, 15) } }); // 這部分是label标簽,使用label就是這樣寫的,使用這部分就要注釋掉下面資訊窗的代碼 // var marker = new AMap.Marker({content: ' ', map: map}); // mass.on('mouseover', function (e) { // marker.setPosition(e.data.lnglat); // marker.setLabel({content: e.data.lnglat}) // }); const infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -10)}); mass.on('click', function (e) { infoWindow.setContent(`
标題:熱點詳細資訊
地理位置:${e.data.lnglat.lng}, ${e.data.lnglat.lat}
最近三個月熱力值:${e.data.val}
`); infoWindow.open(map, e.data.lnglat); }); mass.setMap(map);
這個是使用label标簽的效果,滑鼠放在mark标注上就展示目前點的地理位置坐标:
如果點數不多這裡提供了兩種寫法:
const allLength=gaoData.length; for(let i = 0; i < allLength; i += 1){ const marker = new AMap.Marker({ position: [gaoData[i].lng, gaoData[i].lat], map:map }); const infoWindow = new AMap.InfoWindow({ anchor: 'bottom-center', content:`
這是資訊窗體!這是資訊窗體!
${gaoData[i].lng}
` , }); // 滑鼠點選marker彈出自定義的資訊窗體 marker.on('click', function () { infoWindow.open(map,[gaoData[i].lng, gaoData[i].lat]) }); }
var infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -30)}); const allLength=gaoData.length; function markerClick(e) { infoWindow.setContent(e.target.content); infoWindow.open(map, e.target.getPosition()); } for(let i = 0; i < allLength; i += 1){ const marker = new AMap.Marker({ position: [gaoData[i].lng, gaoData[i].lat], map:map }); marker.content = '我是第' + (i + 1) + '個Marker'; marker.on('click', markerClick); }
最後附上完整的代碼:
// guidemap.jsimport React, { Component,Fragment } from 'react';const {AMap} = window;class Guide extends Component { constructor(props) { super(props); this.state = { data: props.data, }; } componentDidMount() { this.getCharts(); } // eslint-disable-next-line no-unused-vars componentWillReceiveProps(nextProps, nextContext) { if (nextProps.data.length > 0) { this.setState({ data: nextProps.data, }); setTimeout(() => { this.getCharts(); }, 500); } } getCharts = () => { const { data } = this.state; const gaoData=[]; const massData=[]; // eslint-disable-next-line array-callback-return data.map(item=>{ gaoData.push({ lng:item.longitude, lat:item.latitude, count:item.number}) massData.push({lnglat:[item.longitude,item.latitude],val:item.number}) }); console.log("高德地圖",gaoData); const map = new AMap.Map('gaoDe', { resizeEnable: true, center: [108.5, 34.3], zoom: 4 }); let heatmap; map.plugin(["AMap.Heatmap","AMap.Scale",'AMap.ToolBar',], function () { // 初始化heatmap對象 heatmap = new AMap.Heatmap(map, { radius: 25, // 給定半徑 opacity: [0, 0.8], gradient:{ 0.5: 'blue', 0.65: 'rgb(117,211,248)', 0.7: 'rgb(0, 255, 0)', 0.9: '#ffea00', 1.0: 'red' } }); heatmap.setDataSet({ data: gaoData,// heatmapData max: 10 }); const scale = new AMap.Scale({ visible: true, offset: new AMap.Pixel(70,20), }); map.addControl(scale); map.addControl(new AMap.ToolBar()); }); // 海量點标記 const mass = new AMap.MassMarks(massData, { opacity: 0.8, zIndex: 111, cursor: 'pointer', style: { url: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png', anchor: new AMap.Pixel(6, 6), size: new AMap.Size(15, 15) } }); // var marker = new AMap.Marker({content: ' ', map: map}); // mass.on('mouseover', function (e) { // marker.setPosition(e.data.lnglat); // marker.setLabel({content: e.data.lnglat}) // }); const infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -10)}); mass.on('click', function (e) { infoWindow.setContent(`
标題:熱點詳細資訊
地理位置:${e.data.lnglat.lng}, ${e.data.lnglat.lat}
最近三個月熱力值:${e.data.val}
`); infoWindow.open(map, e.data.lnglat); }); mass.setMap(map); // map.setFitView();// 自适應所有的點 // 點不多,添加mark和資訊窗(方案一) // const allLength=gaoData.length; // for(let i = 0; i < allLength; i += 1){ // const marker = new AMap.Marker({ // position: [gaoData[i].lng, gaoData[i].lat], // map:map // }); // // const infoWindow = new AMap.InfoWindow({ // anchor: 'bottom-center', // content:`
這是資訊窗體!這是資訊窗體!
${gaoData[i].lng}
` , // }); // // 滑鼠點選marker彈出自定義的資訊窗體 // marker.on('click', function () { // infoWindow.open(map,[gaoData[i].lng, gaoData[i].lat]) // }); // } // 點不多,添加mark和資訊窗(方案二) // var infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -30)}); // const allLength=gaoData.length; // function markerClick(e) { // infoWindow.setContent(e.target.content); // infoWindow.open(map, e.target.getPosition()); // } // for(let i = 0; i < allLength; i += 1){ // const marker = new AMap.Marker({ // position: [gaoData[i].lng, gaoData[i].lat], // map:map // }); // marker.content = '我是第' + (i + 1) + '個Marker'; // marker.on('click', markerClick); // } }; render(){ return (
{' '}
10
); }}export default Guide;
然後在其他頁面引入這個地圖:
import Guidemap from './guidemap'; //引入自己寫好的熱力地圖const arry=[ {longitude:120.328789,latitude:34.876575,number:10}, {longitude:120.328789,latitude:34.876575,number:10},]; //直接在頁面引入标簽使用 arry的資料格式你可以有自己的格式,不過你的格式改了的話,guide.js參數使用也得自己改下。