IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> js(react)中使用百度地图 -> 正文阅读

[JavaScript知识库]js(react)中使用百度地图

0 需求

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

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 代码实现

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(`
      <div class="${styles.bubble}">
        <p class="${styles.name}">${areaName}</p>
        <p>${count}</p>
      </div>
    `)
    // 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(`
      <div class="${styles.rect}">
        <span class="${styles.housename}">${areaName}</span>
        <span class="${styles.housenum}">${count}套</span>
        <i class="${styles.arrow}"></i>
      </div>
    `)
    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 => (
      <div className={styles.house} key={item.houseCode}>
        <div className={styles.imgWrap}>
          <img
            className={styles.img}
            src={`http://localhost:8080${item.houseImg}`}
            alt=""
          />
        </div>
        <div className={styles.content}>
          <h3 className={styles.title}>{item.title}</h3>
          <div className={styles.desc}>{item.desc}</div>
          <div>
            {item.tags.map(tag => (
              <span
                className={[styles.tag, styles.tag1].join(' ')}
                key={tag}
              >
                {tag}
              </span>
            ))}
          </div>
          <div className={styles.price}>
            <span className={styles.priceNum}>{item.price}</span> 元/月
          </div>
        </div>
      </div>
    ))
  }
  render () {
    return (
      <div className={styles.map}>
        <NavHeader>地图找房</NavHeader>
        <div id="container" className={styles.container}></div>
        {/* 房源列表 */}
        <div
          className={[
            styles.houseList,
            this.state.isShowList ? styles.show : ''
          ].join(' ')}
        >
          <div className={styles.titleWrap}>
            <h1 className={styles.listTitle}>房屋列表</h1>
            <Link className={styles.titleMore} to="/home/list">
              更多房源
            </Link>
          </div>

          <div className={styles.houseItems}>
            {/* 房屋结构 */}
            {this.renderHousesList()}
          </div>
        </div>
      </div>
    )
  }
}

3?代码分析

3.1?封装流程

3.2?代码逻辑?

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

渲染覆盖物

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

? ? ? ? 渲染数据:创建文本标注实例,设置结构和样式后添加到地图上。

点击覆盖物

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

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

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

3.3?中心点移动分析

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:24:08  更:2022-10-17 12:24:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 17:38:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码