perf: 优化高德地图

This commit is contained in:
奔跑的面条 2022-10-29 17:14:47 +08:00
parent f6af081806
commit 016f5b1ccd
9 changed files with 386 additions and 215 deletions

View File

@ -1,79 +1,99 @@
{ {
"point": [ "markers": [
{ {
"name": "北京", "name": "某某地市",
"value": [116.405285, 39.904989, 200] "value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
}, },
{ {
"name": "郑州", "name": "某某地市",
"value": [113.665412, 34.757975, 888] "value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
}, },
{ {
"name": "青海", "name": "某某地市",
"value": [101.778916, 36.623178, 666] "value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
}, },
{ {
"name": "宁夏回族自治区", "name": "某某地市",
"value": [106.278179, 38.46637, 66] "value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
}, },
{ {
"name": "哈尔滨市", "name": "某某地市",
"value": [126.642464, 45.756967, 101] "value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
},
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@integer(100, 130)", "@integer(30, 50)"]
} }
],
"map": [
{
"name": "北京市",
"value": "@integer(0, 1000)"
},
{
"name": "河北省",
"value": "@integer(0, 1000)"
},
{
"name": "江苏省",
"value": "@integer(0, 1000)"
},
{
"name": "福建省",
"value": "@integer(0, 1000)"
},
{
"name": "山东省",
"value": "@integer(0, 1000)"
},
{
"name": "河南省",
"value": "@integer(0, 1000)"
},
{
"name": "湖北省",
"value": "@integer(0, 1000)"
},
{
"name": "广西壮族自治区",
"value": "@integer(0, 1000)"
},
{
"name": "海南省",
"value": "@integer(0, 1000)"
},
{
"name": "青海省",
"value": "@integer(0, 1000)"
},
{
"name": "新疆维吾尔自治区",
"value": "@integer(0, 1000)"
}
],
"pieces": [
{ "gte": 1000, "label": ">1000" },
{ "gte": 600, "lte": 999, "label": "600-999" },
{ "gte": 200, "lte": 599, "label": "200-599" },
{ "gte": 50, "lte": 199, "label": "49-199" },
{ "gte": 10, "lte": 49, "label": "10-49" },
{ "lte": 9, "label": "<9" }
] ]
} }

View File

@ -31,7 +31,7 @@
</SettingItemBox> </SettingItemBox>
<SettingItemBox name="颜色"> <SettingItemBox name="颜色">
<setting-item v-for="(item, index) in optionData.colors" :key="index" :name="`颜色${index}`"> <setting-item v-for="(item, index) in optionData.colors" :key="index" :name="`颜色${index}`">
<n-color-picker v-model:value="optionData.colors[index]" size="small"></n-color-picker> <n-color-picker v-model:value="optionData.colors[index]" size="small" :modes="['hex']"></n-color-picker>
</setting-item> </setting-item>
</SettingItemBox> </SettingItemBox>
</collapse-item> </collapse-item>

View File

@ -5,20 +5,76 @@ import { chartInitConfig } from '@/settings/designSetting'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json' import dataJson from './data.json'
export enum ThemeEnum {
NORMAL = 'normal',
DARK = 'dark',
LIGHT = 'light',
WHITES_MOKE = 'whitesmoke',
FRESH = 'fresh',
GREY = 'grey',
GRAFFITI = 'graffiti',
MACARON = 'macaron',
BLUE = 'blue',
DARKBLUE = 'darkblue',
WINE = 'wine'
}
export enum LangEnum {
ZH_CN = 'zh_cn',
EN = 'en',
ZH_EN = 'zh_en'
}
export enum ViewModeEnum {
PLANE = '2D',
STEREOSCOPIC = '3D'
}
export enum FeaturesEnum {
BG = 'bg',
POINT = 'point',
ROAD = 'road',
BUILDING = 'building'
}
export enum MarkerEnum {
// 圆圈
CIRCLE_MARKER = 'CircleMarker',
// 定位标点
MARKER = 'Marker',
// 暂无
NONE = 'none'
}
export const option = { export const option = {
dataset: dataJson, dataset: dataJson,
amapKey: 'aa76ad84f92f661980f710cbe966b7f6', mapOptions: {
amapStyleKey: 'normal', pitch: 60,
amapStyleKeyCustom: '', skyColor: '#53A9DE',
amapLon: 116.397428, amapKey: 'd5f3e16589dbecae64d05fe90e2ba4f2',
amapLat: 39.90923, amapStyleKey: ThemeEnum.DARK,
amapZindex: 10, amapStyleKeyCustom: '',
viewMode: '2D', amapLon: 116.397428,
pitch: 60, amapLat: 39.90923,
skyColor: '#53A9DE', amapZindex: 11,
lang: 'zh_cn', marker: {
features: ['bg', 'point', 'road', 'building'] fillColor: '#E98984FF',
fillOpacity: 0.5,
strokeColor: 'white',
strokeWeight: 2,
strokeOpacity: 0.5,
zIndex: 10,
bubble: true,
cursor: 'pointer',
clickable: true
},
mapMarkerType: MarkerEnum.CIRCLE_MARKER,
viewMode: ViewModeEnum.PLANE,
lang: LangEnum.ZH_CN,
features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING]
}
} }
export default class Config extends PublicConfigClass implements CreateComponentType { export default class Config extends PublicConfigClass implements CreateComponentType {
public key = MapAmapConfig.key public key = MapAmapConfig.key
public attr = { ...chartInitConfig, w: 1000, h: 800, zIndex: -1 } public attr = { ...chartInitConfig, w: 1000, h: 800, zIndex: -1 }

View File

@ -1,52 +1,52 @@
<template> <template>
<collapse-item name="基础配置"> <collapse-item name="基础" :expanded="true">
<setting-item-box name="Key" :alone="true">
<setting-item>
<n-input v-model:value="optionData.amapKey" size="small"></n-input>
</setting-item>
</setting-item-box>
<setting-item-box name="语言类型" :alone="true"> <setting-item-box name="语言类型" :alone="true">
<setting-item> <setting-item>
<n-select size="small" v-model:value="optionData.lang" :options="langOptions" /> <n-select size="small" v-model:value="optionData.mapOptions.lang" :options="langOptions" />
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="主题样式" :alone="true"> <setting-item-box name="Key" :alone="true">
<setting-item> <setting-item name="请务必使用自己的高德应用 key">
<n-select size="small" v-model:value="optionData.amapStyleKey" :options="themeOptions" /> <n-input v-model:value="optionData.mapOptions.amapKey" size="small"></n-input>
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="自定义地图样式ID" :alone="true"> <setting-item-box name="自定义地图样式ID" :alone="true">
<setting-item> <setting-item>
<n-input size="small" v-model:value="optionData.amapStyleKeyCustom" /> <n-input size="small" v-model:value="optionData.mapOptions.amapStyleKeyCustom" />
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
</collapse-item> </collapse-item>
<collapse-item name="地图配置"> <collapse-item name="地图" :expanded="true">
<n-checkbox-group v-model:value="optionData.features"> <setting-item-box name="主题">
<n-space item-style="display: flex;">
<n-checkbox :value="item.value" :label="item.label" v-for="(item, index) in featuresOptions" :key="index" />
</n-space>
</n-checkbox-group>
</collapse-item>
<collapse-item name="相机配置">
<setting-item-box name="经度" :alone="true">
<setting-item> <setting-item>
<n-input-number v-model:value="optionData.amapLon" size="small"></n-input-number> <n-select size="small" v-model:value="optionData.mapOptions.amapStyleKey" :options="themeOptions" />
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="纬度" :alone="true"> <setting-item-box name="内容" :alone="true">
<setting-item> <n-checkbox-group v-model:value="optionData.mapOptions.features">
<n-input-number v-model:value="optionData.amapLat" size="small"></n-input-number> <n-space item-style="display: flex;">
<n-checkbox :value="item.value" :label="item.label" v-for="(item, index) in featuresOptions" :key="index" />
</n-space>
</n-checkbox-group>
</setting-item-box>
<setting-item-box name="位置">
<setting-item name="经度">
<n-input-number v-model:value="optionData.mapOptions.amapLon" :show-button="false" size="small">
<template #suffix>°</template>
</n-input-number>
</setting-item>
<setting-item name="纬度">
<n-input-number v-model:value="optionData.mapOptions.amapLat" :show-button="false" size="small">
<template #suffix>°</template>
</n-input-number>
</setting-item>
<setting-item name="初始缩放">
<n-input-number v-model:value="optionData.mapOptions.amapZindex" :min="0" size="small"></n-input-number>
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="初始缩放" :alone="true"> <setting-item-box name="模式" :alone="true">
<setting-item> <setting-item>
<n-input-number v-model:value="optionData.amapZindex" size="small"></n-input-number> <n-radio-group v-model:value="optionData.mapOptions.viewMode" name="radiogroup">
</setting-item>
</setting-item-box>
<setting-item-box name="展示模式" :alone="true">
<setting-item>
<n-radio-group v-model:value="optionData.viewMode" name="radiogroup">
<n-space> <n-space>
<n-radio v-for="song in viewModeOptions" :key="song.value" :value="song.value"> <n-radio v-for="song in viewModeOptions" :key="song.value" :value="song.value">
{{ song.label }} {{ song.label }}
@ -55,117 +55,145 @@
</n-radio-group> </n-radio-group>
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<template v-if="optionData.viewMode === '3D'"> <template v-if="optionData.mapOptions.viewMode === '3D'">
<setting-item-box name="天空色" :alone="true"> <setting-item-box>
<setting-item> <setting-item name="天空色">
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.skyColor"></n-color-picker> <n-color-picker size="small" :modes="['hex']" v-model:value="optionData.mapOptions.skyColor"></n-color-picker>
</setting-item> </setting-item>
</setting-item-box> <setting-item name="俯仰角">
<setting-item-box name="俯仰角" :alone="true"> <n-input-number v-model:value="optionData.mapOptions.pitch" :min="0" :max="83" size="small"></n-input-number>
<setting-item>
<n-input-number v-model:value="optionData.pitch" :min="0" :max="83" size="small"></n-input-number>
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
</template> </template>
</collapse-item> </collapse-item>
<collapse-item name="标记" :expanded="true">
<setting-item-box name="样式">
<setting-item name="类型">
<n-select size="small" v-model:value="optionData.mapOptions.mapMarkerType" :options="MarkerOptions" />
</setting-item>
<setting-item name="颜色">
<n-color-picker v-model:value="optionData.mapOptions.marker.fillColor" size="small"></n-color-picker>
</setting-item>
</setting-item-box>
</collapse-item>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, ref } from 'vue' import { PropType } from 'vue'
import { option } from './config' import { option, MarkerEnum, ThemeEnum, LangEnum, ViewModeEnum, FeaturesEnum } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
const props = defineProps({
defineProps({
optionData: { optionData: {
type: Object as PropType<typeof option>, type: Object as PropType<typeof option>,
required: true required: true
} }
}) })
const langOptions = ref([
const themeOptions = [
{ {
value: 'zh_cn', value: ThemeEnum.NORMAL,
label: '中文简体'
},
{
value: 'en',
label: '英文'
},
{
value: 'zh_en',
label: '中英文对照'
}
])
const viewModeOptions = ref([
{
value: '2D',
label: '2D'
},
{
value: '3D',
label: '3D'
}
])
const featuresOptions = ref([
{
value: 'bg',
label: '显示地图背景'
},
{
value: 'point',
label: '显示标识'
},
{
value: 'road',
label: '显示道路'
},
{
value: 'building',
label: '显示建筑'
}
])
const themeOptions = ref([
{
value: 'normal',
label: '标准' label: '标准'
}, },
{ {
value: 'dark', value: ThemeEnum.DARK,
label: '幻影黑' label: '幻影黑'
}, },
{ {
value: 'light', value: ThemeEnum.LIGHT,
label: '月光银' label: '月光银'
}, },
{ {
value: 'whitesmoke', value: ThemeEnum.WHITES_MOKE,
label: '远山黛' label: '远山黛'
}, },
{ {
value: 'fresh', value: ThemeEnum.FRESH,
label: '草色青' label: '草色青'
}, },
{ {
value: 'grey', value: ThemeEnum.GREY,
label: '雅士灰' label: '雅士灰'
}, },
{ {
value: 'graffiti', value: ThemeEnum.GRAFFITI,
label: '涂鸦' label: '涂鸦'
}, },
{ {
value: 'macaron', value: ThemeEnum.MACARON,
label: '马卡龙' label: '马卡龙'
}, },
{ {
value: 'blue', value: ThemeEnum.BLUE,
label: '靛青蓝' label: '靛青蓝'
}, },
{ {
value: 'darkblue', value: ThemeEnum.DARKBLUE,
label: '极夜蓝' label: '极夜蓝'
}, },
{ {
value: 'wine', value: ThemeEnum.WINE,
label: '酱籽' label: '酱籽'
} }
]) ]
const langOptions = [
{
value: LangEnum.ZH_CN,
label: '中文简体'
},
{
value: LangEnum.EN,
label: '英文'
},
{
value: LangEnum.ZH_EN,
label: '中英文对照'
}
]
const viewModeOptions = [
{
value: ViewModeEnum.PLANE,
label: '2D'
},
{
value: ViewModeEnum.STEREOSCOPIC,
label: '3D'
}
]
const featuresOptions = [
{
value: FeaturesEnum.BG,
label: '显示地图背景'
},
{
value: FeaturesEnum.POINT,
label: '显示标识'
},
{
value: FeaturesEnum.ROAD,
label: '显示道路'
},
{
value: FeaturesEnum.BUILDING,
label: '显示建筑'
}
]
const MarkerOptions = [
{
value: MarkerEnum.CIRCLE_MARKER,
label: '圆形标点'
},
{
value: MarkerEnum.MARKER,
label: '定位标点'
},
{
value: MarkerEnum.NONE,
label: '隐藏标点'
}
]
</script> </script>

View File

@ -1,17 +1,22 @@
{ {
"points": [ "markers": [
{ {
"icon": "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-1.png", "name": "某某地市",
"position": [116.300467, 39.907761], "value": 10,
"title": "我是一个文本" "title": "1",
"position": [116.300467, 39.907761]
}, },
{ {
"icon": "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-2.png", "name": "某某地市",
"position": [116.368904, 39.913423] "value": 15,
"title": "3",
"position": [116.400567, 39.908761]
}, },
{ {
"icon": "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-3.png", "name": "某某地市",
"position": [116.305467, 39.807761] "value": 20,
"title": "2",
"position": [116.200467, 39.937761]
} }
] ]
} }

View File

@ -1,13 +1,16 @@
<template> <template>
<div class="box"> <div ref="vChartRef"></div>
<div id="container" style="width: 100%; height: 100%; position: relative"></div>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, PropType, toRefs, watch } from 'vue'
import AMapLoader from '@amap/amap-jsapi-loader' import AMapLoader from '@amap/amap-jsapi-loader'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { reactive, ref, shallowRef, PropType, toRefs, watch } from 'vue' import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { MarkerEnum } from './config'
import { isArray } from '@/utils'
const props = defineProps({ const props = defineProps({
chartConfig: { chartConfig: {
type: Object as PropType<CreateComponentType>, type: Object as PropType<CreateComponentType>,
@ -20,25 +23,31 @@ let {
amapLon, amapLon,
amapLat, amapLat,
amapZindex, amapZindex,
mapMarkerType,
lang, lang,
amapStyleKeyCustom, amapStyleKeyCustom,
features, features,
viewMode, viewMode,
pitch, pitch,
skyColor skyColor,
} = toRefs(props.chartConfig.option) marker
} = toRefs(props.chartConfig.option.mapOptions)
let map = shallowRef(null) let mapIns: any = null
let markers = ref([]) let markers: any = []
let AMapIns: any = null
const vChartRef = ref<HTMLElement>()
const ininMap = () => { const initMap = (newData: any) => {
//
AMapLoader.load({ AMapLoader.load({
key: amapKey.value, //apikey--public使 key: amapKey.value, //apikey--public使
version: '1.4.8', // JSAPI 1.4.15 version: '1.4.8', // JSAPI 1.4.15
plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 使 plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 使
}) })
.then(AMap => { .then(AMap => {
map = new AMap.Map('container', { AMapIns = AMap
mapIns = new AMap.Map(vChartRef.value, {
resizeEnable: true, resizeEnable: true,
zoom: amapZindex.value, // zoom: amapZindex.value, //
center: [amapLon.value, amapLat.value], center: [amapLon.value, amapLat.value],
@ -47,31 +56,75 @@ const ininMap = () => {
features: features.value, features: features.value,
pitch: pitch.value, // 0 - 83 pitch: pitch.value, // 0 - 83
skyColor: skyColor.value, skyColor: skyColor.value,
viewMode: viewMode.value // viewMode: viewMode.value, //
}) willReadFrequently: true
markers?.value.forEach((marker: any) => {
//
if (!/\d/.test(marker.icon || marker.position)) {
return
}
var marker = new AMap.Marker({
icon: marker?.icon,
position: [marker.position[0], marker.position[1]],
title: marker?.title,
offset: new AMap.Pixel(-13, -30)
})
marker.setMap(map)
}) })
dataHandle(props.chartConfig.option.dataset)
}) })
.catch(e => {}) .catch(e => {})
} }
watch( const dataHandle = (newData: any) => {
() => props.chartConfig.option, if (!mapIns && !AMapIns) {
newData => { initMap(props.chartConfig.option)
markers.value = newData.dataset.points return
ininMap() }
if (isArray(newData.markers)) {
//
mapIns.remove(markers)
markers = []
//
if (mapMarkerType.value === MarkerEnum.MARKER) {
newData.markers.forEach((markerItem: any) => {
const markerInstance = new AMapIns.Marker({
position: [markerItem.position[0], markerItem.position[1]],
offset: new AMapIns.Pixel(-13, -30)
})
markers.push(markerInstance)
markerInstance.setMap(mapIns)
})
} else if (mapMarkerType.value === MarkerEnum.CIRCLE_MARKER) {
newData.markers.forEach((markerItem: any) => {
const markerInstance = new AMapIns.CircleMarker({
center: [markerItem.position[0], markerItem.position[1]],
radius: markerItem.value,
...marker.value
})
markers.push(markerInstance)
markerInstance.setMap(mapIns)
})
}
}
}
const stopWatch = watch(
() => props.chartConfig.option.mapOptions,
option => {
initMap(option)
}, },
{ immediate: true, deep: true } {
immediate: true,
deep: true
}
) )
watch(
() => props.chartConfig.option.dataset,
newData => {
try {
dataHandle(newData)
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
//
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
stopWatch()
dataHandle(newData)
})
</script> </script>

View File

@ -1 +1,9 @@
// 页面全局样式 // 页面全局样式
// 去除高德地图 logo
.amap-logo {
display: none !important;
opacity: 0 !important;
}
.amap-copyright {
opacity: 0 !important;
}

View File

@ -73,6 +73,7 @@
<n-text>SQL 类型不支持 Get 请求请使用其它方式</n-text> <n-text>SQL 类型不支持 Get 请求请使用其它方式</n-text>
</template> </template>
<template v-else> <template v-else>
<n-tag type="warning">需要后台提供专门处理 sql 的接口</n-tag>
<setting-item-box name="键名"> <setting-item-box name="键名">
<n-tag type="primary" :bordered="false" style="width: 40px; font-size: 16px"> sql </n-tag> <n-tag type="primary" :bordered="false" style="width: 40px; font-size: 16px"> sql </n-tag>
</setting-item-box> </setting-item-box>

View File

@ -274,7 +274,7 @@ $asideBottom: 70px;
flex-direction: column-reverse; flex-direction: column-reverse;
height: auto; height: auto;
right: 20px; right: 20px;
padding: 20px 8px; padding: 30px 8px;
bottom: $asideBottom; bottom: $asideBottom;
overflow: hidden; overflow: hidden;
transition: height ease 0.4s; transition: height ease 0.4s;