好客租房178-添加loading优化体验

简介: 好客租房178-添加loading优化体验
import React from 'react'
// 导入axios
import axios from 'axios'
import { Link } from 'react-router-dom'
import { Toast } from 'antd-mobile'
// 导入封装好的 NavHeader 组件
import NavHeader from '../../components/NavHeader'
// 导入样式
// import './index.scss'
import styles from './index.module.css'
// 解决脚手架中全局变量访问的问题
const BMapGL = window.BMapGL
// 覆盖物样式
const labelStyle = {
  cursor: 'pointer',
  border: '0px solid rgb(255, 0, 0)',
  padding: '0px',
  whiteSpace: 'nowrap',
  fontSize: '12px',
  color: 'rgb(255, 255, 255)',
  textAlign: 'center'
}
export default class Map 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 myGeo = new BMapGL.Geocoder()
    // 将地址解析结果显示在地图上,并调整地图视野
    myGeo.getPoint(
      label,
      async point => {
        if (point) {
          //  初始化地图
          map.centerAndZoom(point, 11)
          // 添加常用控件
          map.addControl(new BMapGL.NavigationControl())
          map.addControl(new BMapGL.ScaleControl())
          // 调用 renderOverlays 方法
          this.renderOverlays(value)
        }
      },
      label
    )
    // 给地图绑定移动事件
    map.addEventListener('movestart', () => {
      // console.log('movestart')
      if (this.state.isShowList) {
        this.setState({
          isShowList: false
        })
      }
    })
  }
  // 渲染覆盖物入口
  // 1 接收区域 id 参数,获取该区域下的房源数据
  // 2 获取房源类型以及下级地图缩放级别
  async renderOverlays(id) {
    try {
      // 开启loading
      Toast.loading('加载中...', 0, null, false)
      const res = await axios.get(`http://localhost:8080/area/map?id=${id}`)
      // 关闭 loading
      Toast.hide()
      const data = res.data.body
      // 调用 getTypeAndZoom 方法获取级别和类型
      const { nextZoom, type } = this.getTypeAndZoom()
      data.forEach(item => {
        // 创建覆盖物
        this.createOverlays(item, nextZoom, type)
      })
    } catch (e) {
      // 关闭 loading
      Toast.hide()
    }
  }
  // 计算要绘制的覆盖物类型和下一个缩放级别
  // 区   -> 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>${count}套</p>
      </div>
    `)
    // 设置样式
    label.setStyle(labelStyle)
    // 添加单击事件
    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.setStyle(labelStyle)
    // 添加单击事件
    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.loading('加载中...', 0, null, false)
      const res = await axios.get(`http://localhost:8080/houses?cityId=${id}`)
      // 关闭 loading
      Toast.hide()
      this.setState({
        housesList: res.data.body.list,
        // 展示房源列表
        isShowList: true
      })
    } catch (e) {
      // 关闭 loading
      Toast.hide()
    }
  }
  // 封装渲染房屋列表的方法
  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, index) => {
              const tagClass = 'tag' + (index + 1)
              return (
                <span
                  className={[styles.tag, styles[tagClass]].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} />
        {/* 房源列表 */}
        {/* 添加 styles.show 展示房屋列表 */}
        <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>
    )
  }
}

总结


完结 完整代码关注微信公众号 前端小歌谣

相关文章
|
Cloud Native Java 编译器
Spring之提前编译:AOT
【1月更文挑战第18天】 一、AOT概述 1、JIT与AOT的区别 2、Graalvm 3、Native Image 二、演示Native Image构建过程 1、GraalVM安装 (1)下载GraalVM (2)配置环境变量 (3)安装native-image插件 2、安装C++的编译环境 (1)下载Visual Studio安装软件 (2)安装Visual Studio (3)添加Visual Studio环境变量 (4)打开工具,在工具中操作 3、编写代码,构建Native Image (1)编写Java代码 (2)复制文件到目录,执行编译 (3)Native Image 进行构建
327 2
|
运维 Prometheus 监控
提升运维效率:容器化技术与自动化工具的结合
在当今信息技术飞速发展的时代,运维工作面临着前所未有的挑战。为了应对这些挑战,本文将探讨如何通过结合容器化技术和自动化工具来提升运维效率。我们将介绍容器化技术的基本概念和优势,然后分析自动化工具在运维中的应用,并给出一些实用的示例。通过阅读本文,您将了解到如何利用这些先进技术来优化您的运维工作流程,提高生产力。
|
6天前
|
云安全 人工智能 安全
AI被攻击怎么办?
阿里云提供 AI 全栈安全能力,其中对网络攻击的主动识别、智能阻断与快速响应构成其核心防线,依托原生安全防护为客户筑牢免疫屏障。
|
16天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
10天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
620 216
|
存储 人工智能 监控
从代码生成到自主决策:打造一个Coding驱动的“自我编程”Agent
本文介绍了一种基于LLM的“自我编程”Agent系统,通过代码驱动实现复杂逻辑。该Agent以Python为执行引擎,结合Py4j实现Java与Python交互,支持多工具调用、记忆分层与上下文工程,具备感知、认知、表达、自我评估等能力模块,目标是打造可进化的“1.5线”智能助手。
860 61
|
8天前
|
人工智能 移动开发 自然语言处理
2025最新HTML静态网页制作工具推荐:10款免费在线生成器小白也能5分钟上手
晓猛团队精选2025年10款真正免费、无需编程的在线HTML建站工具,涵盖AI生成、拖拽编辑、设计稿转代码等多种类型,均支持浏览器直接使用、快速出图与文件导出,特别适合零基础用户快速搭建个人网站、落地页或企业官网。
1330 157