一、React中使用百度地圖
? 官方文檔:http://lbsyun.baidu.com/index.php?title=jspopular
? 百度地圖JavaScript API是一套由JavaScript語言編寫的應(yīng)用程序接口,可幫助您在網(wǎng)站中構(gòu)建功能豐富、交互性強(qiáng)的地圖應(yīng)用,支持PC端和移動(dòng)端基于瀏覽器的地圖應(yīng)用開發(fā),且支持HTML5特性的地圖開發(fā)。
? 百度地圖JavaScript API支持HTTP和HTTPS,免費(fèi)對外開放,可直接使用。接口使用無次數(shù)限制。在使用前,您需先申請密鑰(ak)才可使用。在您使用百度地圖JavaScript API之前,請先閱讀百度地圖API使用條款。任何非營利性應(yīng)用請直接使用,商業(yè)應(yīng)用請參考使用須知。
二、基本使用
? 首先,在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組件來封裝百度地圖,使用組件內(nèi)導(dǎo)入方式來導(dǎo)入百度地圖js,在this.asyncLoading()中調(diào)用初始化方法: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');
//個(gè)性化定制地圖樣式.在線定制: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 | 所有控件均繼承此類的方法、屬性。通過此類您可實(shí)現(xiàn)自定義控件 |
| 平移縮放控件 | NavigationControl | PC端默認(rèn)位于地圖左上方,它包含控制地圖的平移和縮放的功能。移動(dòng)端提供縮放控件,默認(rèn)位于地圖右下方 |
| 縮略地圖 | OverviewMapControl | 默認(rèn)位于地圖右下方,是一個(gè)可折疊的縮略地圖 |
| 比例尺 | ScaleControl | 默認(rèn)位于地圖左下方,顯示地圖的比例關(guān)系 |
| 地圖類型 | MapTypeControl | 默認(rèn)位于地圖右上方 |
| 版權(quán) | CopyrightControl | 默認(rèn)位于地圖左下方 |
| 定位 | GeolocationControl | 針對移動(dòng)端開發(fā),默認(rèn)位于地圖左下方 |
? 添加自帶的定位控件:
/**
* 初始化百度地圖默認(rèn)定位圖標(biāo)
*/
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);
}
? 注意:有些公司網(wǎng)關(guān)會(huì)禁用百度地圖定位接口,導(dǎo)致定位失敗。
3、自定義定位功能
? 百度地圖自帶的定位控件一般不滿足UI需求,需要自定義定位控件和定位功能。
/**
* 繪制自定義定位圖標(biāo)
*/
renderCustomIcon() {
let {locationType = this.state.locationType} = this.props;
if (locationType !== 2) {
return;
}
return (
<img className='custom-icon' src={imgLocation} alt='定位圖標(biāo)' onClick={this.getLocation}/>
)
}
/**
* 獲取當(dāng)前位置
*/
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、智能搜索
? 根據(jù)地名從百度地圖中檢索地址。
**
* 智能搜索
* @param place 需要搜索的地方
* @param callback 搜索結(jié)果,格式:[]
*/
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 | 所有的覆蓋物均繼承此類的方法 |
| 點(diǎn) | Marker | 表示地圖上的點(diǎn),可自定義標(biāo)注的圖標(biāo) |
| 文本 | Label | 表示地圖上的文本標(biāo)注,您可以自定義標(biāo)注的文本內(nèi)容 |
| 折線 | Polyline | 表示地圖上的折線 |
| 多邊形 | Polygon | 表示地圖上的多邊形。多邊形類似于閉合的折線,另外您也可以為其添加填充顏色 |
| 圓 | Circle | 表示地圖上的圓 |
| 信息窗口 | InfoWindow | 信息窗口也是一種特殊的覆蓋物,它可以展示更為豐富的文字和多媒體信息。注意:同一時(shí)刻只能有一個(gè)信息窗口在地圖上打開 |
| 地面疊加層 | GoundOverlay | 表示疊加在地圖上的圖片,圖片的鏈接、大小、位置等屬性可以自定義 |
| 海量點(diǎn) | PointCollection | 針對點(diǎn)的數(shù)量很大的情況,可以使用海量點(diǎn)進(jìn)行展示 |
| 自定義覆蓋物 | 自定義 | 支持通過繼承覆蓋物基類Overlay,自定義覆蓋物 |
? 百度地圖API支持添加覆蓋物,但是使用自定義圖標(biāo)時(shí),一般需要設(shè)置偏移。
/**
* 添加點(diǎn)覆蓋物
* @param point 添加點(diǎn)
* @param config 配置
* {
img: '',//覆蓋物圖片,格式:url|Image。默認(rèn):imgCenter。
size: [],//覆蓋物圖片尺寸,格式:[x,y]。默認(rèn):[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);
//創(chuàng)建標(biāo)注。使用自定義圖標(biāo)時(shí),標(biāo)注的地理坐標(biāo)點(diǎn)將位于標(biāo)注所用圖標(biāo)的中心位置。
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: '統(tǒng)一企業(yè)', //默認(rèn)起始位置
endSeat: '景江花園'//默認(rèn)終點(diǎn)位置
}
componentDidMount() {
//初始化渲染
const {startSeat,endSeat} = this.state;
this.renderMap(startSeat,endSeat);
}
/**
* 百度地圖API功能
*/
renderMap = (startSeat,endSeat)=> {
const {BMap} = window;
// 創(chuàng)建Map實(shí)例
var map = new BMap.Map("container");
// 初始化地圖,用城市名設(shè)置地圖中心點(diǎn)
// map.centerAndZoom("昆山",15);
// 初始化地圖,設(shè)置中心點(diǎn)坐標(biāo)和地圖級別
map.centerAndZoom(new BMap.Point(120.984, 31.393), 11);
//添加地圖類型控件
map.addControl(new BMap.MapTypeControl());
//開啟鼠標(biāo)滾輪縮放
map.enableScrollWheelZoom(true);
// var p1 = new BMap.Point(121.003346, 31.381632);
// var p2 = new BMap.Point(121.001222, 31.385624);
// //對倆點(diǎn)進(jìn)行連線,該路線市駕車路線(DrivingRoute)
// var driving = new BMap.DrivingRoute(map,{renderOptions: {map: map, autoViewport: true}});
//對倆點(diǎn)進(jìn)行連線,該路線市駕車路線(WalkingRoute)
var walking = new BMap.WalkingRoute(map,{renderOptions: {map: map, panel: "r-result", autoViewport: true}});
walking.search(startSeat, endSeat);
}
//點(diǎn)擊確定
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="起點(diǎn):" {...formItemLayout}>
{getFieldDecorator('startSeat', {
})(<Input />)}
</Form.Item>
<Form.Item label="終點(diǎn):" {...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);
待續(xù).....