React中使用百度地图——基本使用
一、React中使用百度地图
官方文档:http://lbsyun.baidu.com/index.php?title=jspopular
百度地图JavaScript API是一套由JavaScript语言编写的应用程序接口,可帮助您在网站中构建功能丰富、交互性强的地图应用,支持PC端和移动端基于浏览器的地图应用开发,且支持HTML5特性的地图开发。
百度地图JavaScript API支持HTTP和HTTPS,免费对外开放,可直接使用。接口使用无次数限制。在使用前,您需先申请密钥(ak)才可使用。在您使用百度地图JavaScript API之前,请先阅读百度地图API使用条款。任何非营利性应用请直接使用,商业应用请参考使用须知。
二、基本使用
首先,在index.html
中添加:
<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=您的密钥">
//v3.0版本的引用方式:src="http://api.map.baidu.com/api?v=3.0&ak=您的密钥"
然后,在脚手架中组件化。如果使用webpack打包,则在webpack.base.config.js
中添加以下配置;
let config = {
externals: {
'BMap': 'BMap',
}
}
最后,在组件中引用:
import BMap from 'BMap';
1、初始化地图
这里使用MapBD组件来封装百度地图,使用组件内导入方式来导入百度地图js,在this.asyncLoading()中调用初始化方法:this.initMap()
let BMap = {};//百度地图工具类,需要先加载库
let map = {};//百度地图控件
export default class MapBD extends React.Component {
render() {
return (
<div className='map-bd' style={this.props.style}>
<div id='map'></div>
</div>
)
}
/**
* 初始化百度地图
*/
initMap() {
//注意:map容器需要指定高度
map = new BMap.Map('map');
//个性化定制地图样式.在线定制:http://lbsyun.baidu.com/custom/
map.setMapStyle({styleJson: BDStyle});
map.centerAndZoom(new BMap.Point(116.404, 39.915), Constant.defaultZoom);
map.enableScrollWheelZoom(true);
}
}
2、添加控件
百度地图提供的控件:
控 件 | 类 名 | 简 介 |
---|---|---|
抽象基类 | Control | 所有控件均继承此类的方法、属性。通过此类您可实现自定义控件 |
平移缩放控件 | NavigationControl | PC端默认位于地图左上方,它包含控制地图的平移和缩放的功能。移动端提供缩放控件,默认位于地图右下方 |
缩略地图 | OverviewMapControl | 默认位于地图右下方,是一个可折叠的缩略地图 |
比例尺 | ScaleControl | 默认位于地图左下方,显示地图的比例关系 |
地图类型 | MapTypeControl | 默认位于地图右上方 |
版权 | CopyrightControl | 默认位于地图左下方 |
定位 | GeolocationControl | 针对移动端开发,默认位于地图左下方 |
添加自带的定位控件:
/**
* 初始化百度地图默认定位图标
*/
initLocationIcon() {
let {locationType = this.state.locationType, onLocation = () => ''} = this.props;
if (locationType !== 1) {
return;
}
// 添加定位控件
let geolocationControl = new BMap.GeolocationControl();
// 定位成功事件
geolocationControl.addEventListener('locationSuccess', function (rs) {
let address = '';
address += rs.addressComponent.province;
address += rs.addressComponent.city;
address += rs.addressComponent.district;
address += rs.addressComponent.street;
address += rs.addressComponent.streetNumber;
let place = {name: address, point: rs.point};
onLocation(place);
});
// 定位失败事件
geolocationControl.addEventListener('locationError', function (rs) {
Toast.fail(rs.message);
});
map.addControl(geolocationControl);
}
注意:有些公司网关会禁用百度地图定位接口,导致定位失败。
3、自定义定位功能
百度地图自带的定位控件一般不满足UI需求,需要自定义定位控件和定位功能。
/**
* 绘制自定义定位图标
*/
renderCustomIcon() {
let {locationType = this.state.locationType} = this.props;
if (locationType !== 2) {
return;
}
return (
<img className='custom-icon' src={imgLocation} alt='定位图标' onClick={this.getLocation}/>
)
}
/**
* 获取当前位置
*/
getLocation() {
let state = this.state;
if (state.locating) {
return
} else {
state.locating = true;
}
let {onLocation = () => ''} = this.props;
onLocation({name: Constant.locating});
geolocation = geolocation || new BMap.Geolocation();
geolocation.getCurrentPosition(function (rs) {
if (!state.locating) {
return;
}
state.locating = false;
if (this.getStatus() === 0) {
let address = '';
address += rs.address.province;
address += rs.address.city;
address += rs.address.district;
address += rs.address.street;
address += rs.address.street_number;
map.centerAndZoom(rs.point, Constant.defaultZoom);
let place = {name: address, point: rs.point};
onLocation(place);
} else {
onLocation({name: Constant.locationFail});
}
}, {enableHighAccuracy: true});
}
4、智能搜索
根据地名从百度地图中检索地址。
**
* 智能搜索
* @param place 需要搜索的地方
* @param callback 搜索结果,格式:[]
*/
search(place, callback = () => '') {
if (!place) {
return;
}
let onSearchComplete = () => {
callback(localSearch.getResults().Gq);
}
localSearch = localSearch || new BMap.LocalSearch(map, {onSearchComplete});
localSearch.search(place);
}
5、添加覆盖物
可以使用map.addOverlay方法向地图添加覆盖物,使用map.removeOverlay方法移除覆盖物,注意此方法不适用于InfoWindow。
覆盖物 | 类 名 | 说 明 |
---|---|---|
抽象基类 | Overlay | 所有的覆盖物均继承此类的方法 |
点 | Marker | 表示地图上的点,可自定义标注的图标 |
文本 | Label | 表示地图上的文本标注,您可以自定义标注的文本内容 |
折线 | Polyline | 表示地图上的折线 |
多边形 | Polygon | 表示地图上的多边形。多边形类似于闭合的折线,另外您也可以为其添加填充颜色 |
圆 | Circle | 表示地图上的圆 |
信息窗口 | InfoWindow | 信息窗口也是一种特殊的覆盖物,它可以展示更为丰富的文字和多媒体信息。注意:同一时刻只能有一个信息窗口在地图上打开 |
地面叠加层 | GoundOverlay | 表示叠加在地图上的图片,图片的链接、大小、位置等属性可以自定义 |
海量点 | PointCollection | 针对点的数量很大的情况,可以使用海量点进行展示 |
自定义覆盖物 | 自定义 | 支持通过继承覆盖物基类Overlay,自定义覆盖物 |
百度地图API支持添加覆盖物,但是使用自定义图标时,一般需要设置偏移。
/**
* 添加点覆盖物
* @param point 添加点
* @param config 配置
* {
img: '',//覆盖物图片,格式:url|Image。默认:imgCenter。
size: [],//覆盖物图片尺寸,格式:[x,y]。默认:[22, 36]。
offset: []//覆盖物图片偏移,格式:[x,y]
}
*/
addPoint(point, config = {}) {
let {img = imgCenter, size = [22, 36], offset} = config;
let bSize = new BMap.Size(size[0], size[1]);
let bOffset = offset ? new BMap.Size(offset[0], offset[1]) : new BMap.Size(0, -size[1] / 2);
let icon = new BMap.Icon(img, bSize);
icon.setImageSize(bSize);
//创建标注。使用自定义图标时,标注的地理坐标点将位于标注所用图标的中心位置。
let marker = new BMap.Marker(point, {offset: bOffset, icon});
map.addOverlay(marker);
return marker;
}
三、测试代码
import React,{Component} from 'react'
import {Row,Col,Button,Input,Form} from 'antd'
import './map.less'
class Map extends Component {
state = {
startSeat: '统一企业', //默认起始位置
endSeat: '景江花园'//默认终点位置
}
componentDidMount() {
//初始化渲染
const {startSeat,endSeat} = this.state;
this.renderMap(startSeat,endSeat);
}
/**
* 百度地图API功能
*/
renderMap = (startSeat,endSeat)=> {
const {BMap} = window;
// 创建Map实例
var map = new BMap.Map("container");
// 初始化地图,用城市名设置地图中心点
// map.centerAndZoom("昆山",15);
// 初始化地图,设置中心点坐标和地图级别
map.centerAndZoom(new BMap.Point(120.984, 31.393), 11);
//添加地图类型控件
map.addControl(new BMap.MapTypeControl());
//开启鼠标滚轮缩放
map.enableScrollWheelZoom(true);
// var p1 = new BMap.Point(121.003346, 31.381632);
// var p2 = new BMap.Point(121.001222, 31.385624);
// //对俩点进行连线,该路线市驾车路线(DrivingRoute)
// var driving = new BMap.DrivingRoute(map,{renderOptions: {map: map, autoViewport: true}});
//对俩点进行连线,该路线市驾车路线(WalkingRoute)
var walking = new BMap.WalkingRoute(map,{renderOptions: {map: map, panel: "r-result", autoViewport: true}});
walking.search(startSeat, endSeat);
}
//点击确定
handleSubmit = () => {
const userInfo = this.props.form.getFieldsValue();
console.log(JSON.stringify(userInfo));
if (userInfo.startSeat && userInfo.endSeat) {
// this.setState({
// // startSeat: userInfo.startSeat,
// // endSeat: userInfo.endSeat
// // })
this.renderMap(userInfo.startSeat,userInfo.endSeat);
}
}
render(){
const { getFieldDecorator } = this.props.form;
const formItemLayout = {
labelCol: {
xs:24,
sm:5
},
wrapperCol: {
xs:24,
sm:15
}
}
return(
<div className="map-wrap">
<Row>
<Col span={24}>
<Form layout="inline">
<Form.Item label="起点:" {...formItemLayout}>
{getFieldDecorator('startSeat', {
})(<Input />)}
</Form.Item>
<Form.Item label="终点:" {...formItemLayout}>
{getFieldDecorator('endSeat', {
})(<Input />)}
</Form.Item>
<Button type="primary" onClick={this.handleSubmit}>确 定</Button>
</Form>
</Col>
</Row>
<Row>
<Col span={17}>
<div id="container"></div>
</Col>
<Col span={7}>
<div id="r-result"></div>
</Col>
</Row>
</div>
)
}
}
export default Form.create()(Map);
待续.....