js(react)中使用百度地图

0 需求

依次点击区-镇-小区,展示当前位置的数据列表 ;移动地图(movestart事件),隐藏详情。

js(react)中使用百度地图_第1张图片js(react)中使用百度地图_第2张图片js(react)中使用百度地图_第3张图片js(react)中使用百度地图_第4张图片

1 准备工作 

1.1 引入百度地图并配置ak

jspopularGL | 百度地图API SDK

1.2  根据IP定位获取当前定位

import axios from 'axios';

export const getCurrentCity = () => {
  const localCity=JSON.parse(localStorage.getItem('hkzf_city'))
  if (!localCity) {//localStorage 中是否有定位城市,没有,保存并返回
    return new Promise((resolve, reject) => {
      const curCity = new window.BMapGL.LocalCity();
      curCity.get(async res => {
        try {//成功
          const result = await axios.get(`http://localhost:8080/area/info?name=${res.name}`)
          localStorage.setItem('hkzf_city', JSON.stringify(result.body))
          resolve(res.body)//返回结果为promise:如果直接return,外层函数无法接收到
        } catch(e) {//失败
          reject(e)
        }
      })
    })
  }
  return Promise.resolve(localCity)//有,直接返回:此处的 Promise 不会失败
}

2 代码实现

index.jsx

import React from 'react'
import styles from './index.module.scss'
import NavHeader from '../../components/NavHeader'
import axios from 'axios'
import { Link } from 'react-router-dom'
import { Toast } from 'antd-mobile'

export default class Map extends React.Component {
  // 覆盖物样式
  labelStyle = {
    cursor: 'pointer',
    border: '0px solid rgb(255, 0, 0)',
    padding: '0px',
    whiteSpace: 'nowrap',
    fontSize: '12px',
    color: 'rgb(255, 255, 255)',
    textAlign: 'center'
  }
  state = {
    housesList: [],
    isShowList: false
  }
  componentDidMount () {
    this.initMap();
  }
  initMap () {
    // 1初始化地图实例
    const { label, value } = JSON.parse(localStorage.getItem('hkzf_city'));//当前城市name,id
    var map = new window.BMapGL.Map("container");//在 react 脚手架中全局对象需要使用 window 来访问,否则,会造成 ESLint 校验错误
    this.map = map;
    // 2将地址转换为坐标
    var myGeo = new window.BMapGL.Geocoder(); //创建地址解析器实例
    myGeo.getPoint(label, (point) => {// 将地址解析结果显示在地图上,并调整地图视野
      if (point) {
        // 2.1设置中心点
        map.centerAndZoom(point, 11);
        // 2.2添加地图控件
        map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放
        var scaleCtrl = new window.BMapGL.ScaleControl();// 添加比例尺控件
        map.addControl(scaleCtrl);
        var zoomCtrl = new window.BMapGL.ZoomControl();// 添加缩放控件
        map.addControl(zoomCtrl);
        // 2.3渲染覆盖物
        this.renderOverlays(value)
      } else {
        alert('您选择的地址没有解析到结果!');
      }
    }, label)
    // 给地图绑定移动事件
    map.addEventListener('movestart', () => {
      console.log('movestart')
      if (this.state.isShowList) {
        this.setState({
          isShowList: false
        })
      }
    })
  }

  // 渲染覆盖物
  async renderOverlays (id) {
    try {
      Toast.show({
        icon: 'loading',
        content: '加载中…',
        duration: 0,
      })
      // 获取数据
      const res = await axios.get(
        `http://localhost:8080/area/map?id=${id}`
      )
      Toast.clear()
      const data = res.data.body
      // 获取类型及缩放级别
      const { nextZoom, type } = this.getTypeAndZoom()
      // 渲染数据
      this.map.clearOverlays();
      data.forEach(item => {
        this.createOverlays(item, nextZoom, type)
      })
    } catch (e) {
      Toast.clear()
    }
  }

  // 计算要绘制的覆盖物类型和下一个缩放级别
  getTypeAndZoom () {
    const zoom = this.map.getZoom();
    let nextZoom, type
    if (zoom >= 10 && zoom < 12) {// 区
      nextZoom = 13
      type = 'circle'
    } else if (zoom >= 12 && zoom < 14) {// 镇
      nextZoom = 15
      type = 'circle'
    } else if (zoom >= 14 && zoom < 16) {// 小区
      type = 'rect'
    }
    return { nextZoom, type }
  }

  // 创建覆盖物
  createOverlays (item, nextZoom, type) {
    const {
      coord: { longitude, latitude },
      label: areaName,
      count, value
    } = item;
    // 将经纬度转化为坐标
    var pointArea = new window.BMapGL.Point(longitude, latitude);
    if (type === 'circle') {
      this.createCircle(pointArea, areaName, count, value, nextZoom)
    } else {
      this.createRect(pointArea, areaName, count, value)
    }
  }

  // 创建区、镇覆盖物
  createCircle (pointArea, areaName, count, value, nextZoom) {
    // 1创建文本标注覆盖物实例
    var content = "文本覆盖物";
    var labelTXT = new window.BMapGL.Label(content, {
      position: pointArea,// 设置标注的地理位置
      offset: new window.BMapGL.Size(-35, -35)// 设置标注的偏移量
    })
    // 2设置结构
    labelTXT.setContent(`
      

${areaName}

${count}

`) // 3设置样式 labelTXT.setStyle(this.labelStyle) this.map.addOverlay(labelTXT);// 将标注添加到地图中 // 4监听标注事件 labelTXT.addEventListener('click', (e) => { this.renderOverlays(value) this.map.centerAndZoom(pointArea, nextZoom); }); } // 创建小区覆盖物 createRect (pointArea, areaName, count, value) { var content = ""; var labelTXT = new window.BMapGL.Label(content, { position: pointArea, offset: new window.BMapGL.Size(-50, -28) }) labelTXT.setContent(`
${areaName} ${count}套
`) labelTXT.setStyle(this.labelStyle) this.map.addOverlay(labelTXT); labelTXT.addEventListener('click', (e) => { // 获取小区房源数据 this.getHouseList(value); const { x, y, width, height } = e.target.domElement.getBoundingClientRect() console.log(x, y, width, height) // 将被点击的房源移动到中心位置 this.map.panBy( window.innerWidth / 2 - x, (window.innerHeight - 330) / 2 - y ) }); } // 获取小区房源数据 async getHouseList (id) { try { Toast.show({ icon: 'loading', content: '加载中…', duration: 0, }) const res = await axios.get(`http://localhost:8080/houses?cityId=${id}`) Toast.clear() this.setState({ housesList: res.data.body.list, isShowList: true }) } catch (e) { Toast.clear() } } // 渲染小区房源数据 renderHousesList () { return this.state.housesList.map(item => (

{item.title}

{item.desc}
{item.tags.map(tag => ( {tag} ))}
{item.price} 元/月
)) } render () { return (
地图找房
{/* 房源列表:动态类名显示 */}

房屋列表

更多房源
{/* 房屋结构 */} {this.renderHousesList()}
) } }

index.module.scss 

/* 房源列表样式: */
.houseList {
  position: fixed;//固定定位
  bottom: 0;
  left: 0;
  width: 100%;
  height: 330px;
  transition: all 1s;//过渡效果
  transform: translate3d(0, 330px, 0);//向下移动列表的高度
  background: #fff;
  z-index: 5;
}
.show {
  transform: translate3d(0, 0, 0);//恢复原位置
}

.houseItems {
  padding: 0 10px;
  overflow-y: auto;//占满垂直方向剩余高度
  height: 100%;
  padding-bottom: 45px;
}

3 代码分析

3.1 封装流程

js(react)中使用百度地图_第5张图片

3.2 代码逻辑 

初始化渲染:创建map实例,以当前定位为中心点渲染地图(使用IP定位),并添加控件;

渲染覆盖物

        获取数据:接口需返回的数据信息包括:位置id,位置name,当前位置的经纬度;

        渲染数据:将经纬度转换为坐标;初始化当前类型和下一级缩放级别;创建文本标注实例,设置结构和样式后添加到地图上。

点击覆盖物

        圆形:放大地图;渲染下一级数据。

        矩形:移动地图;渲染列表数据。

        注意:事件对象中e的clientX=undefined,需要借助getBoundingClientRect()将数据移动到中心点位置。

3.3 中心点移动分析

js(react)中使用百度地图_第6张图片

你可能感兴趣的:(可视化,前端)