地图找房功能实现


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>
)
}
}
我是Eric,手机号是13522679763

浙公网安备 33010602011771号