内容简介:在对于周边房源的显示逻辑大致如下,
在 全网稀缺,完整链家地图找房的实现(一) 章节中,我们已经实现了地图找房中地图的初始化、区域气泡和区域边界的显示及交互,那么在本文中我们要做的就是地图周边房源的显示及交互。
周边房源的显示
对于周边房源的显示逻辑大致如下,
-
用户点击某个区域气泡,地图缩放层级增大(此时地图的 zoom 更新为区域气泡消失的临界值 ZOOMBOUNDARY 加1,this.zoom = ZOOMBOUNDARY + 1),此时周边房源气泡和周边房源总数提示(dataToast)出现,区域气泡和区域边界消失
-
用户放大地图,当缩放层级大于临界值的时候,同上;小于临界值的时候区域气泡出现,周边房源和周边房源总数提示消失
-
在地图缩放层级大于临界值时,用户拖动地图,拖动结束后更新周边房源(也就是发送 get请求,参数需要和后端同学沟通好,我这里是通过地图当前的中心点坐标查询)
在分析完周边房源显示的场景之后,我们就分为三步来逐步实现。
step1 -- 用户点击某个区域气泡
首先我们需要抽象一个周边房源组件 -- aroundOverlay,该组件和区域气泡组件(zoneOverlay)差不多,样式和内容稍作修改即可,
<template>
<bm-overlay
ref="customOverlay"
class="around"
pane="labelPane"
@draw="draw">
<div>
<!-- div中的内容可自己调整 -->
<p>{{text.title}}</p>
<p>{{Math.ceil(text.initialPrice / 10000)}}万</p>
</div>
</bm-overlay>
</template>
<script>
export default {
props: ['text', 'position', 'active'],
watch: {
position: {
handler () {
this.$refs.customOverlay.reload()
},
deep: true
}
},
methods: {
draw ({el, BMap, map}) {
const {lng, lat} = this.position
const pixel = map.pointToOverlayPixel(new BMap.Point(lng, lat))
// 让周边房源气泡的中心和坐标对应上
el.style.left = pixel.x - 61 + 'px'
el.style.top = pixel.y - 18 + 'px'
}
}
}
</script>
<style lang="stylus" scoped>
.around
overflow: hidden
width: 122px
height: 36px
padding: 5px
box-shadow: 0 0 1px #bbb
background-color: rgba(58,126,255,0.9)
color: #fff
text-align: center
position: absolute
font-size: 12px
line-height: 13px
border-radius: 5px
box-sizing: border-box
div
display: flex
flex-wrap: wrap
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
justify-content: space-between
p
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
width: 100%
text-align: center
</style>
复制代码
以及周边房源提示组件 -- dataToast
<template>
<div class="toast">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'dataToast'
}
</script>
<style lang="scss" scoped>
.toast{
position: fixed;
left: 0;
right: 0;
bottom: 20px;
width: 340px;
height: 26px;
margin: auto;
padding: 3px 10px;
background-color: rgba(0,0,0,.7);
color: #fff;
font-size: 12px;
line-height: 20px;
box-sizing: border-box;
}
</style>
复制代码
在地图容器中使用 aroundOverlay 组件,
<baidu-map id="bm-view" class="bm-view" :center="center" :zoom="zoom" :scroll-wheel-zoom="true" :inertial-dragging="true" @ready="handler" @zoomend="syncCenterAndZoom">
<bm-boundary v-if="showBoundary" :name="zoneBoundary" :strokeWeight="2" strokeColor="blue" fillColor="skyblue" :fillOpacity="0.4"></bm-boundary>
<div v-if="showZone">
<zone-overlay
v-for="(item, index) in zoneGeoPoints" :key="index"
:position="{lng: item.lng, lat: item.lat}"
:text="item"
@mouseover.native="selectZone(item, index)"
@mouseleave.native="cancelZone"
@click.native="selZone(item, index)">
</zone-overlay>
</div>
<div v-if="!showZone">
<around-overlay
v-for="(item, index) in aroundGeoPoints" :key="index"
:position="{lng: item.lng, lat: item.lat}"
:text="item">
</around-overlay>
</div>
</baidu-map>
复制代码
用户点击某个区域气泡,也就是对应的selZine事件,此时区域气泡和区域边界消失,而周边房源出现,设置地图缩放层级 zoom为临界值ZOOMBOUNDARY加1,并且设置地图中心点的经纬度 center,最后发送请求获取周边房源数据,
selZone (item, index) {
this.showZone = false
this.$set(this.center, 'lng', item.lng)
this.$set(this.center, 'lat', item.lat)
this.zoneBoundary = ''
this.showBoundary = false
this.zoom = ZOOMBOUNDARY + 1
// updateHouseList 获取周边房源,使用vuex存储部分数据,这里需要自己设计
this.updateHouseList(item.lng, item.lat)
},
复制代码
对于 dataToast 组件,我是放在地图容器外面,这里需要把和地图相关的部分放在一个组件里(我抽象成了 searchMap 组件),然后和其他的内容放在一个容器div里面,
<div>
<searchMap></searchMap>
<!-- 在上面的updateHouseList方法中将缩放层级存储在vuex中,消失和显示与周边房源组件同步,aroundCnt对应周边房源总数 -->
<dataToast v-if="this.$store.state.showAround > ZOOMBOUNDARY ">视野内共有{{aroundCnt}}个房源,拖动地图查看更多~</dataToast>
</div>
复制代码
searchMap 组件
<div>
<!-- 把之前的baidu-map搬过来就行了,下面是简写 -->
<baidu-map></baidu-map>
</div>
复制代码
step2 -- 用户缩放地图
在这个过程中我们需要双向绑定地图的缩放层级更新 zoom,并且获取当前经纬度,再比较 zoom 和临界值 ZOOMBOUNDARY 显示和隐藏周边房源气泡,对 @zoomend="syncCenterAndZoom" 作如下修改
syncCenterAndZoom (e) {
this.zoom = e.target.getZoom() // 更新 zoom
if (this.zoom > ZOOMBOUNDARY) {
this.showZone = false
// 获取周边房源数据,仅供参考
const {lng, lat} = e.target.getCenter()
this.updateHouseList(lng, lat)
} else {
this.showZone = true
}
}
复制代码
step3 -- 用户移动地图
这个过程需要双向绑定地图当前经纬度,并根据经纬度更新周边房源
<baidu-map id="bm-view" class="bm-view" :center="center" :zoom="zoom" :scroll-wheel-zoom="true" :inertial-dragging="true" @ready="handler" @zoomend="syncCenterAndZoom" @moveend="syncCenterAndZoom_"></baidu-map> 复制代码
@moveend="syncCenterAndZoom_" 表示在地图移动结束时触发 syncCenterAndZoom_,我们在此方法中双向当前的绑定经纬度
syncCenterAndZoom_ (e) {
const zoom = e.target.getZoom()
if (zoom > ZOOMBOUNDARY) {
// 更新周边房源数据,仅供参考
const {lng, lat} = e.target.getCenter()
this.updateHouseList(lng, lat)
}
}
复制代码
周边房源的交互
css :hover伪类
同区域气泡一样,当鼠标滑入某个周边房源时,该气泡高亮,鼠标滑出时,该气泡恢复,由于气泡的onmouseover 和 onmouseleave 没有缓动效果,所以换用css的hover伪类,修改 aroundOverlay 的stylus
.around
transition: background-color .15s ease-in-out /* 缓动效果,可自己调整 */
overflow: hidden
width: 122px
height: 36px
padding: 5px
box-shadow: 0 0 1px #bbb
background-color: rgba(58,126,255,0.9)
color: #fff
text-align: center
position: absolute
font-size: 12px
line-height: 13px
border-radius: 5px
box-sizing: border-box
&:hover
z-index: 1
background-color: rgba(240,65,52,.9)
color: #fff
div
display: flex
flex-wrap: wrap
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
justify-content: space-between
p
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
width: 100%
text-align: center
/* .active是动态的类名,在后面的鼠标点击事件会用到,主要用于高亮显示 */
.around.active
z-index: 1
background-color: rgba(240,65,52,.9)
color: #fff
复制代码
气泡 hover 时 z-index 为1是为了让高亮的气泡不会被其他气泡遮盖住,因为层叠上下文的原因,所以只需设置 z-index 为1即可,如果还不知道层叠上下文的话,可以去看张鑫旭老师的 深入理解CSS中的层叠上下文和层叠顺序
鼠标点击事件 @click.native
我们希望不仅要在鼠标滑入某个周边房源气泡时,该气泡高亮,而且希望鼠标点击也同样高亮,这里就要用到 @click.native (native是修饰符,会把组件当成普通的html标签),动态绑定一个类名,作如下修改
<div v-if="!showZone && this.$store.state.toggleAround">
<around-overlay
v-for="(item, index) in aroundGeoPoints" :key="index"
v-show="!item.isShow"
:class="curAround === item.id?'active':''"
:position="{lng: item.lng, lat: item.lat}"
:text="item"
@click.native="selAround(item, index)">
</around-overlay>
</div>
selAround (item, index) {
this.curAround = item.id
}
复制代码
这里我踩了一个坑,一开始我是根据 index 来动态绑定类名,
:class="curAround === index?'active':''"
selAround (item, index) {
this.curAround = index
}
复制代码
这样是不行的,因为数组 aroundGeoPoints 更新之后(拖动地图结束后发送请求更新周边房源),会出现原来在 aroundGeoPoints 下标为5的元素下标变成了8,原来下标为5的元素是高亮的,数组更新之后就不高亮了,因为他的下标变成了8,因此换成了根据元素的 id(从后台获取) 来绑定类名,因为元素的 id 是唯一的。
房源详情气泡 -- detailOverlay
最后就是房源详情气泡了,类似于一张卡片,展示房源的信息,抽象 detailOverlay 组件
<template>
<bm-overlay
ref="customOverlay"
class="detail"
pane="labelPane"
@draw="draw">
<slot></slot>
</bm-overlay>
</template>
<script>
export default {
props: ['text', 'position', 'active'],
watch: {
position: {
handler () {
this.$refs.customOverlay.reload()
},
deep: true
}
},
methods: {
draw ({el, BMap, map}) {
const {lng, lat} = this.position
const pixel = map.pointToOverlayPixel(new BMap.Point(lng, lat))
el.style.left = pixel.x - 200 + 'px'
el.style.top = pixel.y - 180 + 'px' // 详情气泡底端距房源气泡顶端的距离,可自己调整
}
}
}
</script>
<style lang="stylus" scoped>
.detail
z-index: 9
transition: background-color .15s ease-in-out
width: 400px
height: 140px
padding: 20px
box-shadow: 0 0 10px #bbb
background-color: #fff
color: #fff
text-align: center
position: absolute
font-size: 12px
line-height: 13px
border-radius: 5px
box-sizing: border-box
div
display: flex
flex-wrap: wrap
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
justify-content: space-between
p
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
width: 100%
text-align: center
&:after
content: ''
display: block
position: absolute
left: 50%
bottom: -20px
width: 0
height: 0
margin-left: -10px
border: 10px solid transparent
border-top-color: #fff
</style>
复制代码
在 baidu-map 中使用
<baidu-map>
<div v-if="toggleDetail">
<detail-overlay
:detailGeo="detailGeo"
:position="{lng: detailGeo.lng, lat: detailGeo.lat}">
<!-- info-wrapper 中的内容需要自己替换,仅供参考 -->
<div class="info-wrapper" v-if="toggleDetail">
<div class="img">
<img :src="detailGeo.pic_url" alt="房源图片">
</div>
<div class="info">
<h4 class="title">{{detailGeo.title}}</h4>
<div class="price">
<div>
<p>当前价</p>
<p>{{parseInt(detailGeo.currentPrice / 100) / 100}}万</p>
</div>
<div>
<p>法院评估价</p>
<p>{{parseInt(detailGeo.consultPrice / 100) / 100}}万</p>
</div>
<div>
<p>市场评估价</p>
<p>{{parseInt(detailGeo.marketPrice / 100) / 100}}万</p>
</div>
</div>
</div>
</div>
</detail-overlay>
</div>
</baidu-map>
复制代码
当鼠标滑入房源气泡时,详情气泡出现,鼠标滑出时,详情气泡消失,所以在 aroundOverlay 组件加上 onmouseover 和 onmouseleave
<around-overlay
v-for="(item, index) in aroundGeoPoints" :key="index"
v-show="!item.isShow"
:class="curAround === item.id?'active':''"
:position="{lng: item.lng, lat: item.lat}"
:text="item"
@click.native="selAround(item, index)"
@mouseover.native="showCurInfo(item, index)"
@mouseleave.native="hideCurInfo">
</around-overlay>
// 下面我做了防抖处理, deBounce 是引入的防抖函数
showCurInfo (item, index) {
this.infoPromise = new Promise(resolve => {
deBounce(() => {
this.detailGeo = item
this.toggleDetail = true
resolve()
})
})
return this.infoPromise
},
hideCurInfo () {
this.infoPromise.then(() => {
this.toggleDetail = false
})
}
复制代码
现在我们已经实现了区域气泡、区域边界、周边房源及其详情、周边房源数量提示的展示和交互,效果如下
最后就剩下画圈找房还没实现了,感谢阅读,to be continued~
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 动态路由实现OSPF和RIP协议实现全网互连互通
- 看我如何在赛门铁克邮件安全网关上实现弱口令到RCE漏洞执行
- 全网最全 Dalvik 指令集解析 !
- 全网最全 | MySQL EXPLAIN 完全解读
- 全网最全Flutter常用工具类
- 全网最通透的 Java 8 版本特性讲解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Design Accessible Web Sites
Jeremy Sydik / Pragmatic Bookshelf / 2007-11-05 / USD 34.95
It's not a one-browser web anymore. You need to reach audiences that use cell phones, PDAs, game consoles, or other "alternative" browsers, as well as users with disabilities. Legal requirements for a......一起来看看 《Design Accessible Web Sites》 这本书的介绍吧!