|
|
@@ -1,328 +0,0 @@
|
|
|
-<template>
|
|
|
- <div
|
|
|
- id="container"
|
|
|
- class="mapContainer"
|
|
|
- />
|
|
|
- <div
|
|
|
- v-if="Item.contrlSelect.option.length"
|
|
|
- class="mapContainer-menus"
|
|
|
- >
|
|
|
- <p>
|
|
|
- <icon
|
|
|
- :name="Item.contrlSelect.icon"
|
|
|
- :size="22"
|
|
|
- style="margin-right: 10px;"
|
|
|
- />
|
|
|
- {{ Item.contrlSelect.title }}
|
|
|
- </p>
|
|
|
- <n-checkbox-group
|
|
|
- v-model:value="checkBoxs"
|
|
|
- checked
|
|
|
- @update:value="checkBoxsChange"
|
|
|
- >
|
|
|
- <n-checkbox
|
|
|
- v-for="(item, index) in Item.contrlSelect.option"
|
|
|
- :key="index"
|
|
|
- :value="item.value"
|
|
|
- >
|
|
|
- <icon
|
|
|
- :name="item.icon"
|
|
|
- :size="20"
|
|
|
- />
|
|
|
- {{ item.label }}
|
|
|
- </n-checkbox>
|
|
|
- </n-checkbox-group>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup lang='ts'>
|
|
|
-import AMapLoader from '@amap/amap-jsapi-loader'
|
|
|
-import { onMounted, ref, watch } from 'vue'
|
|
|
-import useStore from '@/pages/store/index'
|
|
|
-import { useNotification } from 'naive-ui'
|
|
|
-import carIcon from '@/assets/img/39.svg'
|
|
|
-import NetService from '@/services/net.service'
|
|
|
-
|
|
|
-const store = useStore()
|
|
|
-const netService = new NetService()
|
|
|
-const notification = useNotification()
|
|
|
-const props = withDefaults(defineProps<{
|
|
|
- zoom?: number,
|
|
|
- Item?: { contrlSelect: { title: string, option: Any[], icon: string, checked:number[] }, key:string }
|
|
|
-}>(), {
|
|
|
- zoom: 13,
|
|
|
- Item: () => ({
|
|
|
- key: '',
|
|
|
- contrlSelect: {
|
|
|
- title: '', option: [], icon: '', checked: []
|
|
|
- }
|
|
|
- })
|
|
|
-})
|
|
|
-const emit = defineEmits<{(evt: 'update:contrlSelect', value: Any): void
|
|
|
-}>()
|
|
|
-let Maps = null as Any
|
|
|
-let AMaps = null as Any
|
|
|
-window._AMapSecurityConfig = {
|
|
|
- securityJsCode: '184c86be3bbd9a8a941bcaaf6b09c7cd'
|
|
|
-}
|
|
|
-const marks = {} as Any
|
|
|
-const checkBoxs = ref(props.Item.contrlSelect.checked)
|
|
|
-
|
|
|
-function getAllRings(feature: { geometry: { coordinates: Any[]; }; }) {
|
|
|
- const coords = feature.geometry.coordinates
|
|
|
- const rings = []
|
|
|
- for (let i = 0, len = coords.length; i < len; i++) {
|
|
|
- rings.push(coords[i][0])
|
|
|
- }
|
|
|
- return rings
|
|
|
-}
|
|
|
-
|
|
|
-function getLongestRing(feature: { geometry: { coordinates: Any[]; }; }) {
|
|
|
- const rings = getAllRings(feature)
|
|
|
- rings.sort((a, b) => b.length - a.length)
|
|
|
- return rings[0]
|
|
|
-}
|
|
|
-
|
|
|
-function colorRandom() {
|
|
|
- const r = Math.floor(Math.random() * 256)
|
|
|
- const g = Math.floor(Math.random() * 256)
|
|
|
- const b = Math.floor(Math.random() * 256)
|
|
|
- return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`
|
|
|
-}
|
|
|
-
|
|
|
-function addMark(position: number[], icon?: string, size?: { w: number, h: number }) {
|
|
|
- if (!Maps) return
|
|
|
- const mark = new AMaps.Marker({
|
|
|
- position,
|
|
|
- cursor: 'pointer',
|
|
|
- icon: new AMaps.Icon({
|
|
|
- image: icon || carIcon,
|
|
|
- imageSize: new AMaps.Size(size?.w || 24, size?.h || 24)
|
|
|
- }),
|
|
|
- autoRotation: true,
|
|
|
- offset: new AMaps.Pixel(-5, -20),
|
|
|
- angle: 0,
|
|
|
- anchor: 'center',
|
|
|
- extData: '1'// 设置自定义属性
|
|
|
- })
|
|
|
- Maps.add(mark)
|
|
|
- return mark
|
|
|
-}
|
|
|
-
|
|
|
-function addLine(path: number[][], color?: string, width?: number) {
|
|
|
- if (!Maps) return
|
|
|
- const polyline = new AMaps.Polyline({
|
|
|
- path,
|
|
|
- strokeWeight: width || 5,
|
|
|
- borderWeight: width || 5, // 线条宽度,默认为 1
|
|
|
- strokeColor: color || 'red', // 线条颜色
|
|
|
- lineJoin: 'bevel', // 折线拐点连接处样式
|
|
|
- geodesic: true
|
|
|
- })
|
|
|
- Maps.add(polyline)
|
|
|
- return polyline
|
|
|
-}
|
|
|
-
|
|
|
-// checkBox勾选
|
|
|
-function checkBoxsChange(params:number[], mate:{actionType:string, value:number}) {
|
|
|
- console.log('勾选', marks[props.Item.key][mate.value])
|
|
|
-
|
|
|
- if (!Object.keys(marks[props.Item.key][mate.value]).length) return
|
|
|
- for (const key in marks[props.Item.key][mate.value]) {
|
|
|
- if (marks[props.Item.key][mate.value][key] && marks[props.Item.key][mate.value][key].markMap) {
|
|
|
- if (mate.actionType === 'check') {
|
|
|
- marks[props.Item.key][mate.value][key].markMap.show()
|
|
|
- } else {
|
|
|
- marks[props.Item.key][mate.value][key].markMap.hide()
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// homePAGE路线
|
|
|
-async function getLines() {
|
|
|
- const { data } = await netService.get('/busLine/getList')
|
|
|
- console.log(666, data)
|
|
|
- if (data && data.length) {
|
|
|
- for (let k = 0; k < data.length; k++) {
|
|
|
- const el = data[k]
|
|
|
- const { modeStationsList } = el.lineModeList[el.lineModeList.length - 1]
|
|
|
- const paths = modeStationsList?.map((es: { longitude: string; latitude: string }) => ([ +es.longitude, +es.latitude ]))
|
|
|
- const color = colorRandom()
|
|
|
- marks[props.Item.key][3][el.lid] = { markMap: addLine(paths, color) }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-function _initMap() {
|
|
|
- AMapLoader.load({
|
|
|
- key: '0c5c83112cafefa77154769b4433c3df',
|
|
|
- version: '2.0',
|
|
|
- plugins: [ 'AMap.DistrictSearch', 'AMap.Weather', 'AMap.Bounds', 'AMap.Driving' ],
|
|
|
- AMapUI: {
|
|
|
- version: '1.1',
|
|
|
- plugins: [ 'geo/DistrictExplorer' ]
|
|
|
- }
|
|
|
- }).then((AMap) => {
|
|
|
- const map = new AMap.Map('container', { // 设置地图容器id
|
|
|
- zoom: props.zoom, // 设置当前显示级别
|
|
|
- expandZoomRange: true, // 开启显示范围设置
|
|
|
- zooms: [ 9, 20 ], // 最小显示级别为7,最大显示级别为20
|
|
|
- center: [ 103.062334, 30.012488 ], // 设置地图中心点位置
|
|
|
- mapStyle: 'amap://styles/grey'
|
|
|
- })
|
|
|
- // 限制位置 getBounds()
|
|
|
- const bounds = new AMap.Bounds(
|
|
|
- [ 103.395136, 30.936781 ], // 右上角经纬度 northEast
|
|
|
- [ 101.93598, 28.845463 ] // 左下角经纬度 southWest
|
|
|
- )
|
|
|
- map.setLimitBounds(bounds)
|
|
|
- // 天气
|
|
|
- const weather = new AMap.Weather()
|
|
|
- weather.getLive('雅安市', (err: any, data: Any) => {
|
|
|
- console.log('天气', err, data)
|
|
|
- if (err) {
|
|
|
- notification.warning({
|
|
|
- content: '天气获取失败',
|
|
|
- duration: 2000
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
- store.setWeather(data)
|
|
|
- })
|
|
|
- // 镂空雅安 511800 adcode
|
|
|
- AMapUI.loadUI([ 'geo/DistrictExplorer' ], (DistrictExplorer: any) => {
|
|
|
- const districtExplorer = new DistrictExplorer({ map })
|
|
|
- districtExplorer.loadMultiAreaNodes([ 100000, 511800 ], (error: any, areaNodes: string | any[]) => {
|
|
|
- const countryNode = areaNodes[0]
|
|
|
- const cityNodes = areaNodes.slice(1)
|
|
|
- const path = []
|
|
|
- // 首先放置背景区域,这里是大陆的边界
|
|
|
- path.push(getLongestRing(countryNode.getParentFeature()))
|
|
|
-
|
|
|
- for (let i = 0, len = cityNodes.length; i < len; i++) {
|
|
|
- // 逐个放置需要镂空的市级区域
|
|
|
- path.push(...getAllRings(cityNodes[i].getParentFeature()))
|
|
|
- }
|
|
|
- // 绘制带环多边形
|
|
|
- const polygon = new AMap.Polygon({
|
|
|
- bubble: true,
|
|
|
- lineJoin: 'round',
|
|
|
- strokeColor: '#030E25', // 线颜色
|
|
|
- strokeOpacity: 1, // 线透明度
|
|
|
- strokeWeight: 1, // 线宽
|
|
|
- fillColor: '#030E25', // 填充色
|
|
|
- fillOpacity: 1, // 填充透明度
|
|
|
- map,
|
|
|
- path
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- Maps = map
|
|
|
- AMaps = AMap
|
|
|
-
|
|
|
- // 初始化marks
|
|
|
- marks[props.Item.key] = {}
|
|
|
- for (let k = 0; k < props.Item.contrlSelect.checked.length; k++) {
|
|
|
- const el = props.Item.contrlSelect.checked[k]
|
|
|
- marks[props.Item.key][el] = {}
|
|
|
- }
|
|
|
-
|
|
|
- // 初始化路线
|
|
|
- getLines()
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-onMounted(() => _initMap())
|
|
|
-
|
|
|
-// 车位置更新
|
|
|
-watch(() => store.socektData, (v) => {
|
|
|
- if (v && v.BUS_LINE_INFO && props.Item.key === 'homePage' && checkBoxs.value.includes(1)) {
|
|
|
- for (let k = 0; k < v.BUS_LINE_INFO.length; k++) {
|
|
|
- const el = v.BUS_LINE_INFO[k]
|
|
|
- for (let j = 0; j < el.inboundAndOutboundStations.length; j++) {
|
|
|
- const es = el.inboundAndOutboundStations[j]
|
|
|
- if (marks[props.Item.key][1][es.vehicleId]) {
|
|
|
- // 更新位置
|
|
|
- marks[props.Item.key][1][es.vehicleId].markMap.setPosition([ es.lng, es.lat ])
|
|
|
- marks[props.Item.key][1][es.vehicleId].markMap.show()
|
|
|
- } else {
|
|
|
- // 添加位置
|
|
|
- marks[props.Item.key][1][es.vehicleId] = { ...es, markMap: addMark([ es.lng, es.lat ]) }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}, { deep: true })
|
|
|
-
|
|
|
-// 菜单切换显示隐藏
|
|
|
-watch(() => props.Item.key, (v) => {
|
|
|
- console.log('菜单切换', v)
|
|
|
- for (const k in marks) {
|
|
|
- for (const j in marks[k]) {
|
|
|
- if (Object.keys(marks[k][j]).length) {
|
|
|
- for (const z in marks[k][j]) {
|
|
|
- if (k === props.Item.key) {
|
|
|
- marks[k][j][z].markMap.show()
|
|
|
- } else {
|
|
|
- marks[k][j][z].markMap.hide()
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-})
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="scss" scoped>
|
|
|
-.mapContainer {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- mask-image: radial-gradient(circle at center, #030E25 70%, transparent 76%);
|
|
|
-
|
|
|
- &-menus {
|
|
|
- min-width: 180px;
|
|
|
- position: absolute;
|
|
|
- bottom: 240px;
|
|
|
- right: 300px;
|
|
|
- z-index: 3;
|
|
|
- border-top-left-radius: 5px;
|
|
|
- border-top-right-radius: 5px;
|
|
|
- overflow: hidden;
|
|
|
- box-sizing: border-box;
|
|
|
- font-size: 20px;
|
|
|
-
|
|
|
- &>p:first-child {
|
|
|
- color: #FFFFFF;
|
|
|
- background: rgba(33, 133, 232, 1);
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- height: 40px;
|
|
|
- padding: 0 10px;
|
|
|
- }
|
|
|
-
|
|
|
- &>div:last-child {
|
|
|
- background: rgba(25, 39, 56, 0.6);
|
|
|
- border: solid 1px rgba(33, 133, 232, 1);
|
|
|
- ;
|
|
|
- }
|
|
|
-
|
|
|
- :deep(.n-checkbox) {
|
|
|
- padding: 5px 10px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- .n-checkbox__label {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- font-size: 20px;
|
|
|
-
|
|
|
- &>svg {
|
|
|
- margin-right: 5px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|