一.最近在一个react项目(antd pro)中需要展示一个热力地图。需求是:

1.热力地图可缩放;

2.鼠标点击可以展示该点地理坐标,及热力值。

3.初始化时候自适应展示所有的热力点。

4.展示热力标尺。

二.在实现的过程中出现了不少的问题.

引入地图出现问题
1.缩放地图的时候中心点会漂移。
   解决方案:
      a.把地图放到页面的顶部。
      b.每次缩放后获取地图中心点,再次设置中心点。关键代码如下:

     let cp;
bmap.addEventListener("mousemove",function(){ // 加载完成时,触发
cp = bmap.getCenter();
});
bmap.addEventListener("mouseend",function(){ // 加载完成时,触发
cp = bmap.getCenter();
});
bmap.addEventListener("tilesloaded",function(){ // 加载完成时,触发
bmap.setCenter(cp);
});

2.热力图标尺不展示。
   解决方案:
       a.将百度地图引入echanrts图表中,通过配置项加热力标尺。(visualMap属性)

b.手写标尺放入百度地图页面。(可以自己尝试弄,这里我不介绍)

3.热力地图的点不能点击。

解决方案:创建标注(这个标注可能有点丑,如果不想要,可以用透明的图片替代)

这有篇博客写的很详细,https://blog.csdn.net/zjuwwj/article/details/53374947#commentsedit

 // 创建一个标注
var point = new BMap.Point(data[0][0], data[0][1]);
var marker = new BMap.Marker(point); // 创建标注
bmap.addOverlay(marker);

4.百度地图默认不会展示目标点的地理坐标(本来引入echarts,想着直接用tooltip属性,结果不生效,查找原因发现热力点是个映射关系,不是实实在在的坐标点,获取不到坐标信息)。
    解决方案: 获取目标点地理坐标,手动加入悬浮层。

5.初始化时候需要自适应展示所有的热力点(打开地图的时候有默认的比例尺,或者自己设定的固定的比例尺。)

解决方案:计算所有热力点中最远的两个的距离,我是设定数据的第一个点为中心点,计算此点与其他所有点的距离,找出最大值,然后对比百度地图等级设定。

百度地图对应的等级可参考:http://api.map.baidu.com/lbsapi/getpoint/index.html

综合实现这些东西,可费了不少劲呢。

三.先来看看热力地图代码:heatMap.js

这是在react项目里使用了echarts和百度地图。

// heatMap.js

import React, { Component } from 'react';

import echarts from 'echarts/lib/echarts';
// 引入热力图
import 'echarts/lib/chart/heatmap';
// 引入提示框和标题组件
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/extension/bmap/bmap';
import 'echarts/lib/component/visualMap'; class EchartsTest extends Component {
constructor(props) {
super(props);
this.state = {
data: props.data,
};
} componentDidMount() {
this.getCharts();
} // 保证再次请求数据时候,地图重新加载
// eslint-disable-next-line no-unused-vars
componentWillReceiveProps(nextProps, nextContext) {
this.setState({
data: nextProps.data,
});
setTimeout(() => {
if(!nextProps.data.length===0){
this.getCharts();
}
}, 500);
} getCharts = () => {
const { data } = this.state;
// 这里data格式:[[120.122,35.666,67],[120.12323,23.45555,23]] ,里面是经度,维度,热力值
const maxdata = data
.map(item => item[2])
.sort()
.reverse()[0];
const myChart = echarts.init(document.getElementById('main'));
const option = {
animation: false,
// tooltip: { // 悬浮层提示框在热力图上无效
// trigger: 'item',
// triggerOn: 'click',
// },
bmap: {
center: [data[0][0], data[0][1]],
zoom: this.getMapGrade(data),
roam: true,
},
visualMap: {
show: true,
// top: 'top',
bottom: 50,
left: 0,
min: 0,
max: maxdata,
seriesIndex: 0,
calculable: true,
inRange: {
color: ['blue', 'green', 'yellow', 'red'],
},
},
series: [
{
name: 'gid热力值',
type: 'heatmap',
coordinateSystem: 'bmap',
data,
pointSize: 8,
blurSize: 8,
},
],
};
myChart.setOption(option);
// 添加百度地图插件
const bmap = myChart
.getModel()
.getComponent('bmap')
.getBMap(); // 解决地图放大地图中心点漂移的问题。当地图不在页面顶部使用
// let cp;
// bmap.addEventListener("mousemove",function(){ // 加载完成时,触发
// cp = bmap.getCenter();
// });
// bmap.addEventListener("mouseend",function(){ // 加载完成时,触发
// cp = bmap.getCenter();
// });
// bmap.addEventListener("tilesloaded",function(){ // 加载完成时,触发
// bmap.setCenter(cp);
// }); // eslint-disable-next-line no-undef
bmap.addControl(new BMap.NavigationControl()); // 地图平移缩放控件
// eslint-disable-next-line no-undef
bmap.addControl(new BMap.ScaleControl()); // 地图比例尺控件
// 创建一个标注
// var point = new BMap.Point(data[0][0], data[0][1]);
// var marker = new BMap.Marker(point); // 创建标注
// bmap.addOverlay(marker);
// eslint-disable-next-line no-plusplus
for (let i = 0; i < data.length; i++) {
// eslint-disable-next-line no-undef
const hotPoint = new BMap.Point(data[i][0], data[i][1]);
// eslint-disable-next-line no-undef
const marker = new BMap.Marker(hotPoint); // 创建标注
bmap.addOverlay(marker); // 将标注添加到地图中 // eslint-disable-next-line no-use-before-define
// marker.addEventListener("click",getAttr);
// function getAttr(){
// var p = marker.getPosition(); // 获取marker的位置
// p.id = "123";
// console.log("点的位置是" + hotPoint.lng + "," + hotPoint.lat);
// console.log("marker的位置是" + p.lng + "," + p.lat);
// } // eslint-disable-next-line no-undef
const infoWindow = new BMap.InfoWindow(`
<div style="margin:0;line-height:20px;padding:2px;">
标题:热点详细信息
<br/>地理位置:${data[i][0]}, ${data[i][1]}
<br/>最近三个月热力值:${data[i][2]}
</div>`); marker.infoWindow = infoWindow; // 给当前标注新增一个属性以便保存窗口信息infoWindow
marker.addEventListener('click', function(e) {
this.openInfoWindow(e.target.infoWindow); // 点击标注时,打开改标注对打开改标注对应的回调信息
// 如果使用下面的方式,那样就会导致每次标注点击后,弹出的窗口信息都是最后一次循环的infoWindow。因为在click的时候只会去找infoWindow这个变量值,而你的click肯定是在所有循环的,标注都产生完之后,此时infoWindow变量已经被赋值成了最后一次循环的值。
// this.openInfoWindow(infoWindow);
});
}
// eslint-disable-next-line no-undef
bmap.addControl(
// eslint-disable-next-line no-undef
new BMap.MapTypeControl({
mapTypes: [
// eslint-disable-next-line no-undef
BMAP_NORMAL_MAP,
// BMAP_HYBRID_MAP
],
})
);
// 去掉上面的{mapTypes:[...]} 就会显示地图,卫星,三维三个图层
}; // 计算经纬度距离(千米),四个参数分别是点A的纬度,经度,点B的纬度,经度(位置不要搞错了,我就弄错了,搞了好久)
getDistance =(lat1, lng1, lat2, lng2)=>{
const radLat1 = lat1*Math.PI / 180.0;
const radLat2 = lat2*Math.PI / 180.0;
const a = radLat1 - radLat2;
const b = lng1*Math.PI / 180.0 - lng2*Math.PI / 180.0;
// eslint-disable-next-line no-restricted-properties
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
// eslint-disable-next-line no-restricted-properties
Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
s *=6378.137 ;
s = Math.round(s * 10000) / 10000;
return s;
}; // 计算地图初始化所有地理坐标中距离最大值
getZoom = (val)=>{
const arr = [];
if(val.length===1){
arr.push(1)
}else{
for(let i=1;i<val.length;i+=1){
arr.push(this.getDistance(val[0][1],val[0][0],val[i][1],val[i][0]))
}
}
// console.log("所有距离",arr);
return Math.max(...arr)
}; // 计算比例尺对应的百度地图等级
getMapGrade=(val)=>{
// console.log("数据 ",val);
const num=this.getZoom(val);
// console.log("最大距离",num);
let zoom=0;
if(num<=1){
zoom=15
}else if(num>1&&num<=50){
zoom=10
}else if(num>50&&num<=100){
zoom=9
}else if(num>100&&num<=500){
zoom=7
}else if(num>500&&num<=1000){
zoom=6
}else{
zoom=4
}
return zoom
}; render() {
return (
<div id="main" style={{ width: '100%', height: 600 }}></div>
);
}
} export default EchartsTest;

四.引用

1.在项目的入口html文件中引入:

需要自己申请百度地图的密钥,直接用下面的密钥也可以:

<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=Imejyag6D5IPg4lOfu0LiDUWBGh2SNmc"></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/Heatmap/2.0/src/Heatmap_min.js"></script>
<script type="text/javascript" src="http://echarts.baidu.com/gallery/vendors/echarts/extension/bmap.min.js"></script>

2.在自己页面中引入heatMap.js

import HeatMap from './heatMap';  //引入自己写好的热力地图
const arry=[
[120.1234555,35.234234,56],
[120.3287898,34.876575,10],
];
<HeatMap data={arry} /> //直接在页面引入标签使用 arry的数据格式你可以有自己的格式,不过你的格式改了的话,heatMap.js参数使用也得自己改下。

react项目结合echarts,百度地图实现热力图的更多相关文章

  1. react项目中引入百度地图打包报错问题

    一.我正常引入百度地图,调试时候是好使的,但是打包时候就报错 引入方法如下: 报错如图 正常调试是好使的,但是打包报这个错,解析不了这个BMap,那么怎么办呢? 然后我就转用了window办法,虽然因 ...

  2. 几个不错的echarts +百度地图 案例

    https://echarts.baidu.com/examples/editor.html?c=map-polygon https://echarts.baidu.com/examples/edit ...

  3. Android 百度地图开发(一)--- 申请API Key和在项目中显示百度地图

      标签: Android百度地图API Key  分类: Android 百度地图开发(2)    最近自己想研究下地图,本来想研究google Map,但是申请API key比较坑爹,于是从百度地 ...

  4. 数据视化Echarts+百度地图API实现市县区级下钻

    开始 这两天公司有个页面需要做数据可视化的展示,数据视化采用的是Echarts+百度地图API做展示,需要用到县级区级下钻的一个联动效果发现网上关于Echarts做到县区级下钻的资料很少,有的话也不是 ...

  5. Android Studio 项目中集成百度地图SDK报Native method not found: com.baidu.platform.comjni.map.commonmemcache.JNICommonMemCache.Create:()I错误

    Android Studio 项目中集成百度地图SDK报以下错误: java.lang.UnsatisfiedLinkError: Native method not found: com.baidu ...

  6. echarts 百度地图 json

    百度ECharts地图Json数据在线下载 最近需要写一个echarts地图统计表,苦于弄不到对应的地图json文件, CSDN 上下载的很多不完整或者不能用,功夫不负苦心人找到了这个. 阿里云地图选 ...

  7. ECharts+百度地图网络拓扑应用

    前一篇谈及到了ECharts整合HT for Web的网络拓扑图应用,后来在ECharts的Demo中看到了有关空气质量的相关报表应用,就想将百度地图.ECharts和HT for Web三者结合起来 ...

  8. 安卓---项目中插入百度地图sdk

    百度地图 应用里面 自带地图 搜房网 下载百度地图的sdk 熟悉api 注冊百度开发人员的账号 2.12 仅仅要有一个ak就能够 高版本号须要提供应用程序的包名和签名返回开发人员的序列号 使用百度地图 ...

  9. 当react框架遇上百度地图

      百度地图官方文档的使用指导是这样说的:在页面中引入<script type="text/javascript" src="http://api.map.baid ...

随机推荐

  1. openvswitch 流表测试 ovs-appctl

    [root@ostack170 ~]# ovs-appctl ofproto/trace br-mirror in_port=,dl_vlan=,dl_src=:ea:cb:5d:e4:ee,dl_d ...

  2. MySQL引擎【转】

    数据库引擎介绍MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎,就必须重新编译MYSQL.在缺省情况下,MYSQL支持三个引擎:ISAM.MYISAM和HEAP.另外 ...

  3. Java面试题(Kafka篇+zookeeper 篇)

    Kafka 152.kafka 可以脱离 zookeeper 单独使用吗?为什么? kafka 不能脱离 zookeeper 单独使用,因为 kafka 使用 zookeeper 管理和协调 kafk ...

  4. Qt 绘图(QBitmap,QPixmap,QImage,QPicture)

    QPainter绘图绘图设备(QPixmap,QImage,QBitmap,QPicture) 重写绘图事件,虚函数 如果窗口绘图,必须放在绘图事件里实现 绘图事件内部自动调用,窗口需要重绘的时候,状 ...

  5. JavaScript中pipe实战

    JavaScript中pipe原理 代码示例 const pipe = (...fns) => x => fns.reduce((y, f) => f(y), x); 原理 一行代码 ...

  6. win10下MinGW的安装与配置(详细步骤)

    一.安装mingw软件 1.进入官网 www.mingw.org 2.点击下载downloads 3.点击下载图标 4.点击install z 5.先选择安装的地址,再点击continue 6.等待相 ...

  7. 力扣Leetcode 202. 快乐数 -快慢指针 快乐就完事了

    快乐数 编写一个算法来判断一个数 n 是不是快乐数. 「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不 ...

  8. PostgreSQL在不同的表空间移动数据文件

    一.背景 在工作中,可能会遇到将表从一个表空间移动另一个表空间.例如 * 对数据进行冷处理 * 表空间所在的磁盘空间不足 * 建表时分配错了表空间 以上等等,可能需要你将一个表移动表空间. 二.表空间 ...

  9. Blazor带我重玩前端(六)

    本文主要讨论Blazor事件内容,由于blazor事件部分很多,所以会分成上下两篇,本文为第二篇. 双向绑定 概述 如图所示 当点击单项绑定的时候,MyOnewayComponent里的属性值会发生变 ...

  10. Rakefile

    Rakefile https://www.jianshu.com/p/b18a6e42455a RAKE – Ruby Make http://docs.seattlerb.org/rake/ bun ...