技术
- React -----> 用于构建用户界面的 JavaScript 库。
- 百度地图 JavaScript API ------->在web端使用的百度地图api(支持3D)
- antd design pro----->开箱即用的React中台前端/设计解决方案。
1. 获取百度地图api
进入百度地图开放平台获取百度地图api,按照步骤完成账号注册和获取密钥
2. 在项目中引入百度地图api
找到src/pages/document.ejs,
<script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=你的密钥"></script>
这是在前端上层html模板中使用
3. 配置webpack
在config.js文件的export中加入
externals: { BMapGL: 'window.BMapGL' }
引入外部变量,这样react组件就能用import的方式导入百度地图的命名空间,从而使用api里面的所有方法。
import BMapGL from 'BMapGL';
4. 简单封装一个地图组件
import React, { PureComponent, Fragment } from 'react';
import BMapGL from 'BMapGL'; // eslint-disable-line
import PropTypes from "prop-types";
export default class BaiduMap extends PureComponent {
static propTypes = {
mapProps: PropTypes.object,
style: PropTypes.object,
getMapInstance: PropTypes.func,
};
static defaultProps = {
mapProps: {
lng:116.280190,
lat:40.049191,
zoom:17,
minZoom:5,
maxZoom:20,
enableScrollWheelZoom:true,
enableDragging:true,
heading:0,
tilt:0,
style:null,
controls:[],
markers:[],
infoWindows:[]
},
style:{
width:'100%',
height:'100%'
},
getMapInstance:null
};
constructor(props) {
super(props);
this.state = {
}
}
componentDidMount(){
const { mapProps:{
lng,
lat,
zoom,
minZoom,
maxZoom,
enableScrollWheelZoom,
enableDragging,
heading,
tilt,
style,
controls,
markers,
infoWindows
},
getMapInstance
}=this.props;
const map = new BMapGL.Map("container"); // 创建Map实例
map.centerAndZoom(new BMapGL.Point(lng, lat), zoom); // 初始化地图,设置中心点坐标和地图级别
map.setMinZoom(minZoom);
map.setMaxZoom(maxZoom);
if(enableScrollWheelZoom){
map.enableScrollWheelZoom(); // 开启鼠标滚轮缩放
}
if(!enableDragging){
map.disableDragging(); // 禁用地图拖拽
}
map.setHeading(heading);
map.setTilt(tilt);
if(style!==null){
if(style.styleId){
map.setMapStyleV2({styleId: style.styleId});
}else if(style.styleJson){
const styleJson=require(`./Style/mapStyle_${style.styleJson}`) // eslint-disable-line
if(styleJson!==null){
map.setMapStyleV2({styleJson});
}
}
}
// 渲染控件
controls.forEach(item=>{
const controltype=item.type;
let control=null;
let opt={};
if(item.option){
const [width,height]=item.option.offset;
opt={
// 控件的停靠位置
anchor: item.option.anchor,
// 控件基于停靠位置的偏移量(可选)
offset: new BMapGL.Size(width, height)
}
}
switch (controltype) {
case 'scale':
control=new BMapGL.ScaleControl(opt);
break;
case 'zoom':
control=new BMapGL.ZoomControl(opt);
break;
case 'location':
control=new BMapGL.LocationControl(opt);
break;
case 'cityList':
control=new BMapGL.CityListControl(opt);
break;
case '3D':
control=new BMapGL.NavigationControl3D(opt);
break;
default:;
}
if(control!==null){
map.addControl(control);
}
})
// 渲染点覆盖物
markers.forEach(item=>{
if(item.position&&item.position.length===2){
const position=new BMapGL.Point(item.position[0], item.position[1])
const opt={};
if(item.option){
if(item.option.offset&&item.option.offset.length===2){
opt.offset=new BMapGL.Size(item.option.offset[0],item.option.offset[1]);
}
if(item.option.icon&&item.option.icon.url&&item.option.icon.size){
opt.icon=new BMapGL.Icon(item.option.icon.url, new BMapGL.Size(item.option.icon.size[0], item.option.icon.size[1]));
}
if(item.title){
opt.title=item.option.title;
}
}
const marker = new BMapGL.Marker(position,opt);
item.events.forEach(event=>{
marker.addEventListener(event.type,event.eventFunc);
})
map.addOverlay(marker);
}
})
// 渲染信息窗口
infoWindows.forEach(item=>{
if(item.position&&item.position.length===2){
const position=new BMapGL.Point(item.position[0], item.position[1])
let opts={};
if(item.option){
opts=item.option;
}
const infoWindow=new BMapGL.InfoWindow(item.content,opts)
map.openInfoWindow(infoWindow, position);
}
})
getMapInstance(map)
}
render() {
const { style }=this.props;
return (
<Fragment>
<div style={style} id="container" />
</Fragment>
);
}
}
通过props.getMapInstance将地图实例返回给父组件,以便在地图组件外也可以进行地图操作。
5. 调用地图组件
import React, { PureComponent, Fragment } from 'react';
import car from '@/assets/car5.png';
import {Button, Row} from "antd";
import BaiduMap from "@/components/Aardvark/BaiduMap";
export default class Bmap extends PureComponent {
state={
mapInstance:null
}
getMapInstance=(instance)=>{
this.setState({
mapInstance:instance
})
}
setZoomIn=()=>{
const {mapInstance}=this.state;
mapInstance.zoomIn()
}
setZoomOut=()=>{
const {mapInstance}=this.state;
mapInstance.zoomOut()
}
render() {
const mapProps={
lng:116.280190, // 经度
lat:40.049191, // 纬度
zoom:20, // 级别
minZoom:5, // 最小级别
maxZoom:25, // 最小级别
enableScrollWheelZoom:true, // 地图可被鼠标滚轮缩放
enableDragging:true, // 地图拖拽
heading:60, // 旋转角度
tilt:70, // 俯角
style:{
styleId:'6b5ed52e4b01d6674be71c30adabaaf4',
styleJson:'blue'
}, // 地图样式
controls:[
{
type:'scale',
option:{
anchor:'BMAP_ANCHOR_BOTTOM_LEFT',
offset: [60,30]
}
},
{
type:'zoom',
},
{
type:'location',
},
{
type:'cityList',
},
{
type:'3D',
},
],
markers:[
{
position: [116.280190, 40.049191],
option: {
offset: [20, 20],
icon: {
url: car,
size: [52, 26]
},
title: '文本标注'
},
events: [
{
type:'click',
eventFunc:()=> {
console.log('marker被点击')
},
}
]
}
],
infoWindows:[
{
position:[116.280195, 40.049198],
option:{
width: 600,
height: 300,
title: '故宫博物院'
},
content:`<h4 style='margin:0 0 5px 0;'>天安门</h4>
<img style='float:right;margin:0 4px 22px' id='imgDemo' src='../img/tianAnMen.jpg' width='139' height='104'/>
<p style='margin:0;line-height:1.5;font-size:13px;text-indent:2em'>
天安门坐落在中国北京市中心,故宫的南侧,与天安门广场隔长安街相望,是清朝皇城的大门...
</p></div>`
}
]
}
return (
<Fragment>
<Row>
<Button style={{zIndex:99}} onClick={this.setZoomIn}>增加zoom</Button>
<Button style={{zIndex:99}} onClick={this.setZoomOut}>减小zoom</Button>
</Row>
<Row>
<div style={{width:'100%',height:800}}>
<BaiduMap mapProps={mapProps} getMapInstance={this.getMapInstance} style={{width:'100%',height:'100%'}} />
</div>
</Row>
</Fragment>
);
}
}