地图找房功能实现

 
 

 

 

 

 

 

 

import React, { PureComponent } from 'react'

import axios from 'axios'
import { Link } from 'react-router-dom'
import { Toast } from 'antd-mobile'

import NavHeader from '../../components/NavHeader'
 
import styles from './index.module.css'

const BMap = window.BMap
let baseUrl = "http://localhost:8080"
export default class Map extends PureComponent {

    constructor(props){
        super(props)
        this.state = {
            // 小区下的房源列表
            houseList:[],
            isShowList: false
        }
    }
  
    componentDidMount() { 
        this.initMap();  
    }

    // 初始化地图
    initMap(){
        // 1 获取当前城市
        const {label,value} = JSON.parse(localStorage.getItem('hkzf_city'))  
        // console.log(label,value) 
        // 初始化地图实例 
        const map = new BMap.Map('container') 
        this.map = map 
        // 设置中心点坐标 
        var myGeo = new BMap.Geocoder();
        // 将地址解析结果显示在地图上,并调整地图视野
        myGeo.getPoint(label, async point => { 
            if(point){
                // 初始化地图
                map.centerAndZoom(point, 11) 
                // map.addOverlay(new BMap.Marker(point, {title: '北京市海淀区上地10街'})) 
                // 添加缩放控件
                map.addControl(new BMap.NavigationControl()) 
                // 添加地图控件
                map.addControl(new BMap.ScaleControl()) 
                
                this.renderOverlays(value) 
               
            } 
        }, label)

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

    async renderOverlays(id){
         // 开启 loading  0 表示不需要关闭
         Toast.loading('加载中...',0,null,false)
          //  获取房源数据
          const res = await axios.get(`${baseUrl}/area/map?id=${id}`)
          const data =  res.data.body
          // console.log(data) 
          const { nextZoom, type } = this.getTypeAndZoom()
 
          // 关闭 loading
          Toast.hide()

          data.forEach(item => { 
            // 创建覆盖物
            this.createOverlays(item,nextZoom, type)
          }); 
    }

    // 获取地图级别 和 类型
    getTypeAndZoom(){
        // 获取当前地图级别
        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
            // circle 表示绘制原型覆盖物
            type = 'circle'
        }else if (zoom >= 14 && zoom < 16){ 
            // circle 表示绘制原型覆盖物
            type = 'rect'
        }

        return {
            nextZoom,
            type
        }
    }

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

        // 创建坐标对象
        const arteaPoint =  new BMap.Point(longitude,latitude)
        
        if(type === 'circle'){
            // 区 和 镇 
            this.createCircle(arteaPoint,areaName,count,value,zoom)
        }else{
            // 小区
            this.createRect(arteaPoint,areaName,count,value,zoom)
        }
    }
     // 区 和 镇 
    createCircle(point,name,count,id,zoom){
        const opts = {
            position: point,
            offset: new BMap.Size(35, -35)
        }
          // 设置 setContent 后 ,第一个参数 为空就行
        const label = new BMap.Label('', opts)  
        // 设置唯一值
        label.id = id 
        // 设置房源覆盖物内容
        label.setContent(`
            <div class="${styles.bubble}">
                <p class="${styles.name}">${name}</p>
                <p>${count}套</p>
            </div>
        `)

        // 设置样式
        label.setStyle({
            cursor: 'pointer',
            border: '0px solid rgb(255.0,0)',
            padding: '0', 
            whiteSpace: 'nowrap',
            fontSize:'12px',
            color: 'rgb(255,255,255)',
            textAlign:'center'
        }) 

        // 添加单击事件
        label.addEventListener('click', () => {

            // 调用 renderOverlays 方法 获取该区域下的房源数据
            this.renderOverlays(label.id) 
            // 以当前点击的覆盖物为中心 放大地图
            this.map.centerAndZoom(point, zoom);  
            // 解决 百度js从报错问题
            setTimeout(()=>{
                // 清除当前覆盖物信息
                this.map.clearOverlays()
            })
        
        }) 
        // 将文本覆盖物添加到地图中
        this.map.addOverlay(label) 
    }

    // 绘制小区覆盖物
    createRect(point,name,count,id,zoom){
        const opts = {
            position: point,
            offset: new BMap.Size(-50,-28)
        }
          // 设置 setContent 后 ,第一个参数 为空就行
        const label = new BMap.Label('', opts)  
        // 设置唯一值
        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({
            cursor: 'pointer',
            border: '0px solid rgb(255.0,0)',
            padding: '0', 
            whiteSpace: 'nowrap',
            fontSize:'12px',
            color: 'rgb(255,255,255)',
            textAlign:'center'
        }) 

        // 添加单击事件
        label.addEventListener('click', (e) => {
            // console.log(id)
            this.getHouseList(id)

            // 获取当前被点击项
            const target = e.changedTouches[0]
            // console.log(target)
            // 移动到坐标中心点
            this.map.panBy(window.innerWidth / 2 - target.clientX, 
                (window.innerHeight - 330) / 2 - target.clientY)
        })  
        // 将文本覆盖物添加到地图中
        this.map.addOverlay(label) 
    }  
    
    // 获取小区房源数据
    async getHouseList(id){   
        // 开启 loading  0 表示不需要关闭
        Toast.loading('加载中...',0,null,false)
        const res = await axios.get(`${baseUrl}/houses?cityId=${id}`)
        // 关闭 loading
        Toast.hide()
        // console.log(res)
        this.setState({
            houseList:res.data.body.list,
            isShowList:true
        })
    }

    // 封装渲染房屋列表的方法
    renderHousesList() {
        let {houseList} = this.state 
        if(!houseList.length) return
        return houseList.map(item => (
            <div className={styles.house} key={item.houseCode}> 
                <div className={styles.imgWrap}>
                <img className={styles.img} src={`${baseUrl}${item.houseImg}`} alt="" />
                </div>

                <div className={styles.content}>
                    <h3 className={styles.title}>{item.title}</h3>
                    <div className={styles.desc}>{item.desc}</div> 
                </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> 
        ))
    }

    render() {
        return (
            <div className={styles.map}> 
                <div className={styles.mapAmNavbar}>
                  <NavHeader>地图找房</NavHeader> 
                </div> 
                <div id="container" className={styles.container}></div>  

                {/* 房源列表 */}
                {/* 添加 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>
        )
    }

}
posted @ 2021-09-13 17:31  13522679763-任国强  阅读(749)  评论(0)    收藏  举报