Ken428965 2022-10-08 16:11 采纳率: 53.9%
浏览 52
已结题

react,获取房源数据,以覆盖物的形式分别显示在区、镇、小区级别的地图上,出现了比例尺重叠、地图放大级别不能灵活匹配数据等问题?

在使用的react版本如下:

img


已写的代码如下:

import React from 'react'
// 导入封装好的NavHeader组件
import NavHeader from '../../components/NavHeader'
// 导入 HouseItem 组件
import HouseItem from '../../components/HouseItem'
import { API } from '../../utils/api'
import { Link } from 'react-router-dom'
import { Toast } from 'antd-mobile'
import { BASE_URL } from '../../utils/url'
import styles from './style.module.css'
// 解决脚手架中全局访问变量的问题
const BMapGL = window.BMapGL

export default class Mymap extends React.Component {
  state = {
  // 小区下的房源列表
        housesList: [],
  // 表示是否展示房源列表
  isShowList: false
  }
  
    // 初始化地图实例
    componentDidMount() {
      this.initMap()
    }
    initMap() {
      // 获取当前定位城市
      const {label, value} = JSON.parse(localStorage.getItem('hkzf_city'))
      const map = new BMapGL.Map("container")
      // 作用:能够在其他方法中通过this来获取地图对象
      this.map = map
    // 设置中心点坐标
      // const point = new BMapGL.Point(116.404, 39.915)
    //创建地址解析器实例
      const myGeo = new BMapGL.Geocoder();
    // 将地址解析结果显示在地图上,并调整地图视野
      myGeo.getPoint(
        label,
        async point => {
      if (point) {
        // 初始化地图
        map.centerAndZoom(point, 11);
        // 添加控件
        const scaleCtrl = new BMapGL.ScaleControl();  // 添加比例尺控件
        map.addControl(scaleCtrl);
        const zoomCtrl = new BMapGL.ZoomControl();  // 添加缩放控件
        map.addControl(zoomCtrl);
        const cityCtrl = new BMapGL.CityListControl();  // 添加城市列表控件
        map.addControl(cityCtrl);
        // 调用renderOverlays方法
        this.renderOverlays(value)
      }
    },
    label
      )

      // 给地图绑定移动事件
    map.addEventListener('movestart', () => {
      if (this.state.isShowList) {
        this.setState({
          isShowList: false
        })
      }
    })
  }

      // 渲染覆盖物入口
  async renderOverlays(id) {
    try {
      // 开启loading
      Toast.show({
        icon: 'loading',
        content: '加载中…',
    })

      const res = await API.get(`/area/map?id=${id}`)
      // 关闭 loading
      Toast.clear()
      const data = res.data.body

      // 调用 getTypeAndZoom 方法获取级别和类型
      const { nextZoom, type } = this.getTypeAndZoom()

      data.forEach(item => {
        // 创建覆盖物
        this.createOverlays(item, nextZoom, type)
      })
    } catch (e) {
      // 关闭 loading
      Toast.clear()
    }
  }

  // 计算要绘制的覆盖物类型和下一个缩放级别
  // 区   -> 11 ,范围:>=10 <12
  // 镇   -> 13 ,范围:>=12 <14
  // 小区 -> 15 ,范围:>=14 <16
  getTypeAndZoom() {
    // 调用地图的 getZoom() 方法,来获取当前缩放级别
    const zoom = this.map.getZoom()
    let nextZoom, type

    // console.log('当前地图缩放级别:', zoom)
    if (zoom >= 10 && zoom < 12) {
      // 区
      // 下一个缩放级别
      nextZoom = 13
      // circle 表示绘制圆形覆盖物(区、镇)
      type = 'circle'
    } else if (zoom >= 12 && zoom < 14) {
      // 镇
      nextZoom = 15
      type = 'circle'
    } else if (zoom >= 14 && zoom < 16) {
      // 小区
      type = 'rect'
    }

    return {
      nextZoom,
      type
    }
  }

  // 创建覆盖物
  createOverlays(data, zoom, type) {
    const {
      coord: { longitude, latitude },
      label: areaName,
      count,
      value
    } = data

    // 创建坐标对象
    const areaPoint = new BMapGL.Point(longitude, latitude)

    if (type === 'circle') {
      // 区或镇
      this.createCircle(areaPoint, areaName, count, value, zoom)
    } else {
      // 小区
      this.createRect(areaPoint, areaName, count, value)
    }
  }

  // 创建区、镇覆盖物
  createCircle(point, name, count, id, zoom) {
    // 创建覆盖物
    const label = new BMapGL.Label('', {
      position: point,
      offset: new BMapGL.Size(-35, -35)
    })

    // 给 label 对象添加一个唯一标识
    label.id = id

    // 设置房源覆盖物内容
    label.setContent(`
      <div class="${styles.bubble}">
        <p class="${styles.name}">${name}</p>
        <p class="${styles.name}">${count}套</p>
      </div>
    `)

    // 添加单击事件
    label.addEventListener('click', () => {
      // 调用 renderOverlays 方法,获取该区域下的房源数据
      this.renderOverlays(id)

      // 放大地图,以当前点击的覆盖物为中心放大地图
      this.map.centerAndZoom(point, zoom)

      // 解决清除覆盖物时,百度地图API的JS文件自身报错的问题
      setTimeout(() => {
        // 清除当前覆盖物信息
        this.map.clearOverlays()
      }, 0)
    })

    // 添加覆盖物到地图中
    this.map.addOverlay(label)
  }

  // 创建小区覆盖物
  createRect(point, name, count, id) {
    // 创建覆盖物
    const label = new BMapGL.Label('', {
      position: point,
      offset: new BMapGL.Size(-50, -28)
    })

    // 给 label 对象添加一个唯一标识
    label.id = id

    // 设置房源覆盖物内容
    label.setContent(`
      <div class="${styles.rect}">
        <span class="${styles.housename}">${name}</span>
        <span class="${styles.housenum}">${count}套</span>
        <i class="${styles.arrow}"></i>
      </div>
    `)

    // 添加单击事件
    label.addEventListener('click', e => {
      // 获取并渲染房源数据
      this.getHousesList(id)

      // 获取当前被点击项
      const target = e.changedTouches[0]
      this.map.panBy(
        window.innerWidth / 2 - target.clientX,
        (window.innerHeight - 330) / 2 - target.clientY
      )
    })

    // 添加覆盖物到地图中
    this.map.addOverlay(label)
  }

  // 获取小区房源数据
  async getHousesList(id) {
    try {
      // 开启loading
      Toast.show({
        icon: 'loading',
        content: '加载中…',
    })

      const res = await API.get(`/houses?cityId=${id}`)
      // 关闭 loading
      Toast.clear()

      this.setState({
        housesList: res.data.body.list,
        // 展示房源列表
        isShowList: true
      })
    } catch (e) {
      // 关闭 loading
      Toast.clear()
    }
  }

  // 封装渲染房屋列表的方法
  renderHousesList() {
    return this.state.housesList.map(item => (
      <HouseItem
        onClick={() => this.props.history.push(`/detail/${item.houseCode}`)}
        key={item.houseCode}
        src={BASE_URL + item.houseImg}
        title={item.title}
        desc={item.desc}
        tags={item.tags}
        price={item.price}
      />
    ))
  }
  
    render() {
        return <div className={styles.map}>
          {/* 顶部导航栏组件 */}
          <NavHeader>
            地图找房
          </NavHeader>
            {/* 地图容器元素 */}
            <div id='container' className={styles.container} style={{ height: window.innerHeight -45 }}/>
            {/* 房源列表 */}
        {/* 添加 styles.show 展示房屋列表 */}
        <div
          className={[
            // styles.houseList,
            styles.housesList,
            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>
    }
}

希望实现如下效果:
1、进入此页面后,首先显示区级别的地图,同时显示区级别对应的覆盖物:

img


2、点击其中一个覆盖物后,地图放大到镇街级别,同时显示镇街级别对应的覆盖物:

img


3、点击其中一个覆盖物后,地图放大到小区级别的地图,同时显示小区级别对应的覆盖物:

img


4、点击其中一个覆盖物后,地图底部向上拉出一个房源基本信息框,同时让被点的房源移动到地图范围内的中央位置:

img

目前效果如下:
1、放大地图级别后,上一级别的比例尺仍继续显示并与新一级别的重叠显示:

img


2、区、镇街、小区对应不同的地图放大级别,地图处于不同放大级别时不会自动显示对应的区、镇街和小区数据:

img


3、点击小区级别的房源时,chrome浏览器报错:

img


请问代码出了什么问题?如何修改?

  • 写回答

2条回答 默认 最新

  • wan8140870 2022-10-08 17:37
    关注

    state里写错了,是housesList:[],少了个s

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月14日
  • 已采纳回答 10月9日
  • 修改了问题 10月9日
  • 修改了问题 10月9日
  • 展开全部

悬赏问题

  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥15 键盘指令混乱情况下的启动盘系统重装