react项目结合echarts,百度地图实现热力图
一.最近在一个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,百度地图实现热力图的更多相关文章
- react项目中引入百度地图打包报错问题
一.我正常引入百度地图,调试时候是好使的,但是打包时候就报错 引入方法如下: 报错如图 正常调试是好使的,但是打包报这个错,解析不了这个BMap,那么怎么办呢? 然后我就转用了window办法,虽然因 ...
- 几个不错的echarts +百度地图 案例
https://echarts.baidu.com/examples/editor.html?c=map-polygon https://echarts.baidu.com/examples/edit ...
- Android 百度地图开发(一)--- 申请API Key和在项目中显示百度地图
标签: Android百度地图API Key 分类: Android 百度地图开发(2) 最近自己想研究下地图,本来想研究google Map,但是申请API key比较坑爹,于是从百度地 ...
- 数据视化Echarts+百度地图API实现市县区级下钻
开始 这两天公司有个页面需要做数据可视化的展示,数据视化采用的是Echarts+百度地图API做展示,需要用到县级区级下钻的一个联动效果发现网上关于Echarts做到县区级下钻的资料很少,有的话也不是 ...
- 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 ...
- echarts 百度地图 json
百度ECharts地图Json数据在线下载 最近需要写一个echarts地图统计表,苦于弄不到对应的地图json文件, CSDN 上下载的很多不完整或者不能用,功夫不负苦心人找到了这个. 阿里云地图选 ...
- ECharts+百度地图网络拓扑应用
前一篇谈及到了ECharts整合HT for Web的网络拓扑图应用,后来在ECharts的Demo中看到了有关空气质量的相关报表应用,就想将百度地图.ECharts和HT for Web三者结合起来 ...
- 安卓---项目中插入百度地图sdk
百度地图 应用里面 自带地图 搜房网 下载百度地图的sdk 熟悉api 注冊百度开发人员的账号 2.12 仅仅要有一个ak就能够 高版本号须要提供应用程序的包名和签名返回开发人员的序列号 使用百度地图 ...
- 当react框架遇上百度地图
百度地图官方文档的使用指导是这样说的:在页面中引入<script type="text/javascript" src="http://api.map.baid ...
随机推荐
- javascript 数组的组合
javascript 数组的组合 一.前言 二.数组的组合 concat()方法 push(...items) 其他方法 三.结束语 一.前言 今天在开发项目过程中,遇到了一个需求,先请求了30个数据 ...
- neutron plugin 与 extension 编写流程
原文链接:neutron plugin 与 extension 编写流程 参考: 怎样写 OpenStack Neutron 的 Plugin (一)怎样写 OpenStack Neutron 的 P ...
- Mybatis分页插件: pageHelper的使用及其原理解析
在实际工作中,很进行列表查询的场景,我们往往都需要做两个步骤:1. 查询所需页数对应数据:2. 统计符合条件的数据总数:而这,又会导致我们必然至少要写2个sql进行操作.这无形中增加了我们的工作量,另 ...
- python格式化输出及大量案例
python格式化输出符号及大量案例 1.格式化输出符号 python格式化输出符号 格式化符号 含义 %c 转化成字符 %r 优先使用repr()函数进行字符串转化 %s 转换成字符串,优先使用st ...
- 玩转Spring——Spring整合JDBC
传统JDBC代码的弊端在传统的jdbc代码中,即使是执行一条简单的SQL语句,其实现的整个流程也是极为繁琐的,先打开数据库连接执行sql,然后组装结果,最后关闭数据库资源,这中间还有大量的try... ...
- docker部署数据库
搜索数据库镜像images docker search mysql 搜索结果如下图所示: 选择合适自己的mysql版本 因为mysql新版本出来了,很多特性没有学习,所以笔者安装了mysql:5.6 ...
- Lombok 作者因兼容问题讨伐 IntelliJ IDEA(官方已妥协)
今天(08/26),你看到本文应该是昨天了. 栈长上班打开电脑,按往常一样打开 IntelliJ IDEA 正准备撸码,突然收到 IDEA 2020.2.1 的更新提醒: 我现在用的还是 2020.1 ...
- AD18使用原理图优先选项( Preference)调整原理图纸张大小失效问题解决
1.创建新的原理图纸后,在当前点击更改并不会生效 2.想要生效需要去原理图纸的文档详细属性中更新即可生效!以下两种方式可以打开文档选项按钮. a.O->D 打开文档选项 b.右下角选择Prope ...
- 【原】“Error getting 'android:label' attribute”
项目上线过程中遇到“Error getting 'android:label' attribute: attribute is not a string value”这个错误. 备忘下:是因为有act ...
- 使用Loadrunner进行性能测试
一.确定性能测试的范围.要求.配置.工具等 明确测试的系统: 本文档主要指的是web应用. 明确测试要求: 用户提出性能测试,例如,网站首页页面响应时间在3S之内,主要的业务操作时间小于10s,支持3 ...