<template>
|
<div class="center-panel">
|
<div class="map-container" ref="mapContainer"></div>
|
</div>
|
</template>
|
|
<script>
|
import AMapLoader from '@amap/amap-jsapi-loader'
|
|
export default {
|
name: 'MapPanel',
|
data() {
|
return {
|
map: null,
|
markers: [],
|
infoWindow: null
|
}
|
},
|
mounted() {
|
this.$nextTick(() => {
|
this.initMap()
|
})
|
},
|
methods: {
|
async initMap() {
|
try {
|
const AMap = await AMapLoader.load({
|
key: '526e04b30ceba8f217c5def5a92392f9',
|
version: '2.0',
|
plugins: ['AMap.ToolBar', 'AMap.Scale']
|
})
|
|
this.map = new AMap.Map(this.$refs.mapContainer, {
|
zoom: 16,
|
center: [91.1172, 29.6487],
|
viewMode: '3D',
|
pitch: 35,
|
mapStyle: 'amap://styles/normal',
|
features: ['bg', 'road', 'building', 'point'],
|
buildingAnimation: true
|
})
|
|
this.map.addControl(new AMap.ToolBar({
|
position: 'RB'
|
}))
|
this.map.addControl(new AMap.Scale({
|
position: 'RB'
|
}))
|
|
this.infoWindow = new AMap.InfoWindow({
|
offset: new AMap.Pixel(0, -30),
|
closeWhenClickMap: true,
|
autoMove: true,
|
anchor: 'bottom-center'
|
})
|
|
this.map.on('click', () => {
|
if (this.infoWindow) {
|
this.infoWindow.close()
|
}
|
})
|
|
this.addMarkers()
|
} catch (error) {
|
console.error('地图加载失败:', error)
|
}
|
},
|
addMarkers() {
|
const houses = [
|
{
|
position: [91.1172, 29.6487],
|
title: '新城大道房源',
|
status: 'waiting',
|
content: `
|
<div class="info-window" data-status="waiting">
|
<div class="info-title">房屋状态:待租出</div>
|
<div class="info-content">
|
<p>房屋编号:新城大道</p>
|
<p>房屋状态:待租出</p>
|
<p>租赁面积:1000/2000㎡</p>
|
<p>本季租金:500/2000元/月</p>
|
</div>
|
</div>
|
`
|
},
|
{
|
position: [91.1272, 29.6587],
|
title: '拉萨路房源',
|
status: 'rented',
|
content: `
|
<div class="info-window" data-status="rented">
|
<div class="info-title">房屋状态:已租出</div>
|
<div class="info-content">
|
<p>房屋编号:拉萨路</p>
|
<p>房屋状态:已租出</p>
|
<p>租赁面积:800/1500㎡</p>
|
<p>本季租金:400/1800元/月</p>
|
</div>
|
</div>
|
`
|
}
|
]
|
|
houses.forEach(house => {
|
const circles = []
|
const baseRadius = 15
|
const numCircles = 3
|
|
const centerCircle = new AMap.Circle({
|
center: house.position,
|
radius: baseRadius / 2,
|
fillColor: house.status === 'waiting' ? '#ff9800' : '#4CAF50',
|
fillOpacity: 0.8,
|
strokeWeight: 0,
|
zIndex: numCircles + 2,
|
bubble: true,
|
cursor: 'pointer'
|
})
|
|
for (let i = 0; i < numCircles; i++) {
|
circles.push(new AMap.Circle({
|
center: house.position,
|
radius: baseRadius * (i + 1),
|
fillColor: house.status === 'waiting' ? '#ff9800' : '#4CAF50',
|
fillOpacity: 0.3 - (i * 0.05),
|
strokeColor: house.status === 'waiting' ? '#ff9800' : '#4CAF50',
|
strokeWeight: 2,
|
strokeOpacity: 0.5 - (i * 0.08),
|
zIndex: numCircles - i,
|
bubble: true,
|
cursor: 'pointer'
|
}))
|
}
|
|
const clickHandler = () => {
|
if (this.infoWindow) {
|
this.infoWindow.setContent(house.content)
|
this.infoWindow.open(this.map, house.position)
|
}
|
}
|
|
centerCircle.on('click', clickHandler)
|
circles.forEach(circle => circle.on('click', clickHandler))
|
|
this.map.add([centerCircle, ...circles])
|
this.markers.push({ center: centerCircle, rings: circles })
|
|
let phase = 0
|
const animate = () => {
|
phase += 0.15
|
const scale = 1 + 0.6 * Math.sin(phase)
|
|
circles.forEach((circle, index) => {
|
const currentRadius = baseRadius * (index + 1)
|
circle.setRadius(currentRadius * scale)
|
|
const baseOpacity = 0.3 - (index * 0.05)
|
const opacityScale = 1 + 0.5 * Math.sin(phase)
|
circle.setOptions({
|
fillOpacity: baseOpacity * opacityScale,
|
strokeOpacity: (0.5 - (index * 0.08)) * opacityScale
|
})
|
})
|
|
requestAnimationFrame(animate)
|
}
|
animate()
|
})
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
.center-panel {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
}
|
|
.map-container {
|
border-radius: 8px;
|
overflow: hidden;
|
background: rgba(255, 255, 255, 0.05);
|
width: 100%;
|
height: 100vh;
|
}
|
|
.info-window {
|
padding: 10px;
|
background: rgba(146, 146, 146, 0.5);
|
border-radius: 8px;
|
z-index: 10003;
|
min-width: 200px;
|
}
|
|
.info-title {
|
font-size: 16px;
|
font-weight: bold;
|
color: #fff;
|
margin-bottom: 12px;
|
padding-bottom: 8px;
|
border-bottom: 1px solid #eee;
|
}
|
|
.info-content {
|
font-size: 12px;
|
color: #fff;
|
}
|
|
.info-content p {
|
margin: 8px 0;
|
line-height: 1.4;
|
}
|
|
.info-window[data-status="waiting"] .info-title {
|
color: #fff;
|
}
|
|
.info-window[data-status="rented"] .info-title {
|
color: #fff;
|
}
|
|
.amap-info {
|
z-index: 10003 !important;
|
display: block !important;
|
}
|
|
.amap-info-content {
|
background: rgba(146, 146, 146, 0.5);
|
padding: 0 !important;
|
}
|
|
.amap-info-sharp {
|
display: none !important;
|
}
|
</style>
|