zoukankan      html  css  js  c++  java
  • 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>
        )
      }
    

      

  • 相关阅读:
    ToastCustomUtil【简单的Toast封装类】【自定义Toast的显示风格】
    ToastMiui【仿MIUI的带有动画的Toast】
    ToastCustom【自定义显示风格的Toast】
    用现实生活的例子解释非对称加密
    对称加密、非对称加密、数字签名、数字证书、SSL是什么
    公钥和私钥:确认过眼神 是对的人
    如何拿到美团offer的
    http无状态和鉴权解决四种方案
    java网络编程-面试题
    Java网络编程面试总结
  • 原文地址:https://www.cnblogs.com/wmlcn/p/15082973.html
Copyright © 2011-2022 走看看