React+AntdUi实现《好客租房系统》地图导航03

一、地图导航界面分为四个模块,首部的导航栏,地图上的遮盖物,尺寸和放大缩小模块

 

 

  1.  首部的导航栏NavBar使用自己封装的组件
  2. 地图渲染
     // 一加载界面就初始化地图
      initMap = async () => {
        // 由于使用了百度地图API,则有一个BMap对象,将该对象挂载到实例上
        this.BMap = window.BMap;
        // 创建地图实例 
        this.map = new this.BMap.Map("container");
        // 获取定位城市
        const { value, label } = await getCurrCity();
        // 处理重置
        this.cityId = value;
        // 创建地址解析器实例     
        let myGeo = new this.BMap.Geocoder();
        // 将地址解析结果显示在地图上,并调整地图视野    
        myGeo.getPoint(null, async (point) => {
          if (point) {
            // 初始化地图,设置中心点坐标和地图级别
            this.initPoint = point;
            this.map.centerAndZoom(point, 11);
            // 添加控件,放大缩小控件和标尺
            this.map.addControl(new this.BMap.NavigationControl());
            this.map.addControl(new this.BMap.ScaleControl());
            // 渲染覆盖物
            this.renderOverlays(value)
          }
        },
          label);
        this.map.addEventListener('movestart', () => {
          if (this.state.isShowList) {
            this.setState({
              isShowList: false
            })
          }
        })
      }
  3. 创建覆盖物
  • 获取数据

    // 请求接口,获取房源数据
    let res = await axios.get(`http://localhost:8080/area/map?id=${value}`)
    // 遍历房源信息,创建对应的覆盖物
    res.data.body.map(item => {
        // 给每一条数据添加覆盖物
        // 得到返回的经纬度信息
        let { coord: { longitude, latitude }, label: areaName, count, value } = item
        // 创建覆盖物
        let label = new window.BMap.Label('', {
            position: new window.BMap.Point(longitude, latitude),
            offset: new window.BMap.Size(-35, -35)
        })
        // 设置覆盖物内容
        label.setContent(`<div class="${styles.bubble}">
        <p class="${styles.name}">${areaName}</p>
        <p>${count}套</p>
      </div>`)
        // 设置样式
        label.setStyle(labelStyle)
        // 添加点击事件
        label.addEventListener('click', function () {
            // 当点击了覆盖物,要以当前点击的覆盖物为中心来放大地图
            map.centerAndZoom(this.K.position, 13);
            // 解决清除覆盖物的时候,百度地图js报错问题
            setTimeout(function () {
                map.clearOverlays()
            }, 0)
        })
        // 给label添加唯一标识
        label.id = value
        // 添加到地图上
        map.addOverlay(label)
    }) 
  •  渲染覆盖物

      // 根据区域渲染覆盖物
      renderOverlays = async (id) => {
        // Toast.loading('加载中...', 0);
        // 初始化区覆盖物
        let { status, data } = await getMapHouses(id);
        // Toast.hide();
        // =========获取覆盖物类型和下一层缩放级别========
        const { type, nextLevel } = this.getTypeAndZoom();
        if (status === 200) {
          data.forEach((item) => {
            this.createOverlays(type, item, nextLevel)
          })
        }
      }
  • 创建覆盖物
      // 创建覆盖物
      createOverlays = (type, item, nextLevel) => {
        const {
          coord: { longitude, latitude },
          label: areaName,
          count,
          value
        } = item;
        // 转换地理位置坐标
        const ipoint = new this.BMap.Point(longitude, latitude);
        if (type === 'rect') {
          this.createRect(ipoint, areaName, count, value)
        } else {
          this.createCircle(ipoint, areaName, count, value, nextLevel)
        }
      }
  • 按级别创建覆盖物  

     // 处理小区情况
      createRect = (ipoint, areaName, count, value) => {
        // 绘制覆盖物
        const opts = {
          position: ipoint,    // 指定文本标注所在的地理位置
          offset: new this.BMap.Size(-50, -28)    //设置文本偏移量
        }
        const label = new this.BMap.Label(null, opts);  // 创建文本标注对象
        label.setContent(`
          <div class="${styles.rect}">
            <span class="${styles.housename}">${areaName}</span>
            <span class="${styles.housenum}">${count}</span>
            <i class="${styles.arrow}"></i>
          </div>
         `
        )
        // 去除默认样式
        label.setStyle({
          border: 'none'
        });
        // 添加点击事件
        label.addEventListener('click', (e) => {
          console.log('点击小区', value);
          // this.map.centerAndZoom(ipoint, 15)
          // this.map.panTo(ipoint)
          console.log(e);
          this.moveToArea(e);
          this.handlerHouseList(value)
        })
        this.map.addOverlay(label);
      }
     // 处理区和镇的情况
      createCircle = (ipoint, areaName, count, value, nextLevel) => {
        // 绘制覆盖物
        const opts = {
          position: ipoint,    // 指定文本标注所在的地理位置
          offset: new this.BMap.Size(0, 0)    //设置文本偏移量
        }
        const label = new this.BMap.Label(null, opts);  // 创建文本标注对象
        // 给label添加唯一ID
        // label.id = value;
        label.setContent(
          `
                  <div class="${styles.bubble}">
                  <p class="${styles.bubbleName}">${areaName}</p>
                  <p>${count}</p>
                  </div>
                  `
        )
        // 去除默认样式
        label.setStyle({
          border: 'none'
        });
        // 添加点击事件
        label.addEventListener('click', () => {
          // 设置显示下一区域的位置和缩放级别
          this.map.centerAndZoom(ipoint, nextLevel);
          this.renderOverlays(value);
          // 清除第一层覆盖物
          // map.clearOverlays();
          setTimeout(() => this.map.clearOverlays());
        })
        this.map.addOverlay(label);
      }

4.展示该区域内的房屋列表

使用地图的 panBy() 方法,移动地图到中间位置
垂直位移:(window.innerHeight(屏幕高度)-330(房源列表高度)/2) - target.clientY(目标覆盖层的位置)
水平位移:window.innerWidth(屏幕宽度)/2 - target.clientX
移动地图的时候(监听movestart事件),隐藏房源列表
点击遮盖物的时候展示房源列表,由于展示房源列表的组件在条件找房页面也会使用,则将其封装成一个组件HouseItem并将获取的数据以参数传入
// 渲染小区下房屋列表
  renderHouseList = () => {
    return (
      <div
        className={[
          styles.houseList,
          this.state.isShowList ? styles.show : ''
        ].join(' ')}
      >
        <div className={styles.titleWrap}>
          <h1 className={styles.listTitle}>房屋列表</h1>
          <a className={styles.titleMore} href="/home/house">
            更多房源
    </a>
        </div>

        <div className={styles.houseItems}>
          {/* 房屋结构 */}
          {
            this.state.list.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}
              />
            ))
          }
        </div>
      </div>
    )
  }

  

 

posted @ 2021-07-31 00:04  AoYeDDM  阅读(104)  评论(0编辑  收藏  举报