Files
dvcp_v2_webapp/ui/packages/tools/AiMap.vue
2023-04-24 16:24:34 +08:00

266 lines
6.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<section class="AiMap" :class="{mask}">
<div ref="amap" class="map"/>
<div v-if="mask" class="mask"/>
</section>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader";
export default {
name: "AiMap",
props: {
plugins: {default: () => ['AMap.DistrictSearch', 'AMap.LineSearch']},
map: Object,
lib: Object,
mapStyle: String,
areaId: String,
is3d: Boolean,
ops: {default: () => ({})},
markers: {default: () => []},
mask: Boolean,
searchBus: {default: "2"},
pulseLines: Boolean,
onlyShowArea: Boolean,
satellite: Boolean
},
computed: {
viewMode() {
return this.is3d ? '3D' : '2D'
}
},
data() {
return {
amap: null,
mapLib: null,
loca: null,
}
},
watch: {
markers: {
deep: true, handler() {
this.addMarkers()
}
}
},
methods: {
initMap(c = 0) {
let {plugins, viewMode, mapStyle} = this
AMapLoader.load({
key: '54a02a43d9828a8f9cd4f26fe281e74e',
version: '2.0',
plugins,
Loca: {version: '2.0.0'}
}).then(AMap => {
this.mapLib = AMap
this.$emit('update:lib', AMap)
if (this.$refs.amap) {
this.amap = new AMap.Map(this.$refs.amap, {
mapStyle,
viewMode,
terrain: true,
resizeEnable: true,
skyColor: "#082243",
zoom: 11,
...this.ops
})
this.amap.on('complete', () => {
this.amap.setFitView();//视口自适应
})
/*增加卫星图层*/
if (this.satellite) {
this.amap.add([new AMap.TileLayer.RoadNet({zIndex: 11}), new AMap.TileLayer.Satellite({zIndex: 10})])
}
/* end */
this.$emit('update:map', this.amap)
this.$emit("loaded")
this.mapLoaded()
}
}).catch(() => c < 10 ? this.initMap(++c) : new Error("地图加载有问题"))
},
getMapArea() {
const {mapLib: AMap} = this
if (!!AMap) {
new AMap.DistrictSearch({
subdistrict: 0, //获取边界不需要返回下级行政区
extensions: 'all', //返回行政区边界坐标组等具体信息
level: 'district' //查询行政级别为 市
}).search(this.areaId.substring(0, 6), (status, result) => {
const area = result?.districtList?.[0],
bounds = area?.boundaries || [];
let polygons = []
if (this.onlyShowArea) {
const mask = bounds.map(e => [e])
polygons = bounds.map(path => new AMap.Polygon({
path: path.map(e => [e.lng, e.lat]),
strokeWeight: 1,
fillOpacity: 0,
strokeStyle: 'dashed',
strokeColor: '#0091ea'
}))
this.amap.setMask(mask)
this.amap.setPitch(65)
} else {
polygons = bounds.map(path => new AMap.Polygon({
strokeWeight: 1,
path: path.map(e => [e.lng, e.lat]),
strokeStyle: 'dashed',
fillOpacity: 0.1,
fillColor: '#80d8ff',
strokeColor: '#0091ea'
}))
}
this.amap.add(polygons)
this.amap.setCenter(area.center, true)
})
}
},
mapLoaded() {
this.areaId && this.getMapArea()
this.addPulseLines(this.areaId?.substring(0, 6))
this.addMarkers()
},
addMarkers() {
if (this.markers.length > 0 && this.mapLib && this.amap) {
let markers = this.markers.map(e => {
let {label, icon = "https://cdn.cunwuyun.cn/dvcp/h5/Location2.png"} = e
return new this.mapLib.Marker({
content: e.content || `<div class="marker">
<img src="${icon}"/>
<span>${label}</span>
</div>`,
position: [e.lng, e.lat]
})
})
this.amap.add(markers)
}
},
addPulseLines(city) {
let {amap: map, mapLib: lib, pulseLines} = this
if (pulseLines && lib && map && city) {
this.loca = new Loca.Container({map: this.amap})
let ls = new lib.LineSearch({pageSize: 1, pageNum: 1, city}), lines = {
type: "FeatureCollection",
features: []
}
Promise.all(Array.from("0123456789").map(i => new Promise((resolve) => {
ls.search(i, (e, res) => {
if (e == "complete" && res.info == "OK") {
res.lineInfo?.map(line => {
lines.features.push({
type: "Feature",
properties: {},
geometry: {
type: "LineString",
coordinates: line.path?.map(p => [p.lng, p.lat]) || []
}
})
})
}
resolve()
})
}))).then(() => {
let layer = new Loca.PulseLineLayer({
zIndex: 10,
opacity: 1,
visible: true,
zooms: [2, 22],
})
let geo = new Loca.GeoJSONSource({data: lines})
layer.setSource(geo)
layer.setStyle({
altitude: 0,
lineWidth: 2,
// 脉冲头颜色
headColor: "#B5FBFF",
// 脉冲尾颜色
trailColor: 'rgba(0,0,0,0)',
// 脉冲长度0.25 表示一段脉冲占整条路的 1/4
interval: 0.25,
// 脉冲线的速度,几秒钟跑完整段路
duration: 15000,
})
this.loca.add(layer)
this.loca.animate.start()
})
}
}
},
mounted() {
this.initMap()
},
destroyed() {
this.amap?.destroy()
}
}
</script>
<style lang="scss" scoped>
.AiMap {
width: 100%;
height: 100%;
flex: 1;
min-width: 0;
min-height: 0;
position: relative;
&.mask {
box-shadow: 0 0 40px 20px rgba(#000, .8);
}
.map {
height: 100%;
}
.mask {
pointer-events: none;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 8;
background: radial-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .6) 40%, #000 100%);
}
:deep( .marker ) {
position: relative;
& > img {
width: 50px;
height: 50px;
}
& > span {
display: none;
}
&:hover > span {
position: absolute;
left: 50%;
bottom: 0;
transform: translate(-50%, 100%);
display: block;
color: #fff;
font-size: 14px;
white-space: nowrap;
}
}
:deep( .amap-logo), :deep( .amap-copyright ) {
display: none !important;
}
:deep( .amap-icon ) {
width: 40px !important;
height: 40px !important;
img {
width: 100%;
height: 100%;
}
}
}
</style>