【类 型】:feat 写地图选择控件

【原  因】:切换地图
【过  程】:调用控件
【影  响】:留好缓存地图设置
This commit is contained in:
tk 2024-07-25 21:33:52 +08:00
parent 9667b718b5
commit 6a80d87ddd
2 changed files with 151 additions and 73 deletions

View File

@ -19,58 +19,59 @@ export default {
wayLngLats: [], // 线 wayLngLats: [], // 线
takeoffLngLats: [], // 线 takeoffLngLats: [], // 线
isflow: false, // isflow: false, //
currentStyleIndex: 0, //
// //
GoogleRasterStyle: { mapStyles: [
// mapbox // mapbox
name: 'Mapbox Streets', {
sprite: this.$store.state.settings.host + '/Public/map/sprite', name: '谷歌卫星',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', sprite: this.$store.state.settings.host + '/Public/map/sprite',
version: 8, glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
sources: { version: 8,
google: { sources: {
type: 'raster', google: {
tileSize: 256, type: 'raster',
tiles: ['https://sb.im/google-maps/vt?lyrs=s&x={x}&y={y}&z={z}'] tileSize: 256,
} tiles: ['https://sb.im/google-maps/vt?lyrs=s&x={x}&y={y}&z={z}']
}
},
layers: [{ id: 'GoogleRasterLayer', type: 'raster', source: 'google' }]
}, },
layers: [{ id: 'GoogleRasterLayer', type: 'raster', source: 'google' }]
},
MapBoxglRasterStyle: 'mapbox://styles/mapbox/outdoors-v12', // mapbox
MapBoxglSatellite: 'mapbox://styles/mapbox/satellite-streets-v12', // mapbox
GaodeVectorStyle: {
// //
name: 'Gaode Vector', {
sprite: this.$store.state.settings.host + '/Public/map/sprite', name: '高德矢量',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', sprite: this.$store.state.settings.host + '/Public/map/sprite',
version: 8, glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
sources: { version: 8,
gaode: { sources: {
type: 'raster', gaode: {
tileSize: 256, // 256 512 type: 'raster',
tiles: [ tileSize: 256, // 256 512
'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}' tiles: [
] 'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
} ]
}
},
layers: [{ id: 'GaodeVectorLayer', type: 'raster', source: 'gaode' }]
}, },
layers: [{ id: 'GaodeVectorLayer', type: 'raster', source: 'gaode' }]
},
GaodeRasterStyle: {
// //
name: 'Gaode Raster', {
sprite: this.$store.state.settings.host + '/Public/map/sprite', name: '高德卫星',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', sprite: this.$store.state.settings.host + '/Public/map/sprite',
version: 8, glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
sources: { version: 8,
gaode: { sources: {
type: 'raster', gaode: {
tileSize: 256, // 256 512 type: 'raster',
tiles: [ tileSize: 256, // 256 512
'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}' tiles: [
] 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}'
} ]
}, }
layers: [{ id: 'GaodeRasterLayer', type: 'raster', source: 'gaode' }] },
} layers: [{ id: 'GaodeRasterLayer', type: 'raster', source: 'gaode' }]
}
]
} }
}, },
computed: { computed: {
@ -159,7 +160,7 @@ export default {
// map // map
this.map = new mapboxgl.Map({ this.map = new mapboxgl.Map({
container: 'map', container: 'map',
style: this.GoogleRasterStyle, style: this.mapStyles[0],
center: this.defaultLnglat, center: this.defaultLnglat,
zoom: this.defaultZoom, zoom: this.defaultZoom,
pitch: 0, pitch: 0,
@ -174,15 +175,9 @@ export default {
// //
this.map.addControl(new CustomFullscreenControl(this.handleResize), 'top-right') this.map.addControl(new CustomFullscreenControl(this.handleResize), 'top-right')
//
//
MapboxStyleSwitcherControl.DEFAULT_STYLES = [
{ title: '谷歌卫星', uri: 'mapbox://styles/mapbox/streets-v11' },
{ title: '高德卫星', uri: 'mapbox://styles/mapbox/satellite-v9' }
//
]
// //
const styleSwitcherControl = new MapboxStyleSwitcherControl([], 'iconfont icon-duozhang f-s-20') //
const styleSwitcherControl = new MapboxStyleSwitcherControl(this.mapStyles, 'iconfont icon-duozhang f-s-20', this.currentStyleIndex)
this.map.addControl(styleSwitcherControl, 'top-right') this.map.addControl(styleSwitcherControl, 'top-right')
// //
@ -597,5 +592,4 @@ export default {
background-size: cover; background-size: cover;
cursor: pointer; cursor: pointer;
} }
</style> </style>

View File

@ -1,58 +1,142 @@
import mapboxgl from 'mapbox-gl' import mapboxgl from 'mapbox-gl'
/**
* 自定义地图样式切换控件
* 用于在 Mapbox 地图上添加一个控件允许用户选择不同的地图样式
*/
export class MapboxStyleSwitcherControl { export class MapboxStyleSwitcherControl {
constructor (styles = [], defaultIconClass = '') { /**
this.styles = styles.length ? styles : MapboxStyleSwitcherControl.DEFAULT_STYLES * 构造函数
this.defaultIconClass = defaultIconClass // 用于设置自定义图标的类名 * @param {Array} styles - 可选的样式列表每个样式包含 name URI默认为空数组
this.controlContainer = null * @param {String} defaultIconClass - 自定义图标的 CSS 类名默认为空字符串
this.map = null * @param {Number} currentStyleIndex - 当前选中的样式索引默认为 0
this.styleButton = null */
this.styleDropdown = null constructor (styles = [], defaultIconClass = '', currentStyleIndex = 0) {
this.styles = styles
this.defaultIconClass = defaultIconClass
this.currentStyleIndex = currentStyleIndex // 当前样式索引
this.controlContainer = null // 控件容器
this.map = null // 地图实例
this.styleButton = null // 切换样式的按钮
this.styleDropdown = null // 样式选择的下拉菜单
} }
/**
* 添加控件到地图上
* @param {MapboxMap} map - Mapbox 地图实例
* @returns {HTMLElement} 控件的容器元素
*/
onAdd (map) { onAdd (map) {
this.map = map this.map = map
// 创建控件的容器元素
this.controlContainer = document.createElement('div') this.controlContainer = document.createElement('div')
this.controlContainer.className = 'mapboxgl-ctrl mapboxgl-ctrl-group' this.controlContainer.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'
this.controlContainer.style.display = 'flex'
this.controlContainer.style.flexDirection = 'column'
this.controlContainer.style.alignItems = 'center'
this.controlContainer.style.justifyContent = 'center'
this.controlContainer.style.overflow = 'hidden'
// 创建切换样式的按钮
this.styleButton = document.createElement('button') this.styleButton = document.createElement('button')
this.styleButton.className = this.defaultIconClass || 'style-switcher-button' // 如果提供了自定义类名,则使用它 this.styleButton.className = this.defaultIconClass || 'style-switcher-button' // 如果提供了自定义类名,则使用它
this.styleButton.onclick = this._toggleDropdown.bind(this) this.styleButton.onclick = this._toggleDropdown.bind(this) // 绑定按钮点击事件
// 让按钮内容(图标)居中
this.styleButton.style.display = 'flex'
this.styleButton.style.alignItems = 'center'
this.styleButton.style.justifyContent = 'center'
this.styleButton.style.width = '29px' // 可以根据需要调整
this.styleButton.style.height = '29px' // 可以根据需要调整
// 创建样式选择的下拉菜单
this.styleDropdown = document.createElement('div') this.styleDropdown = document.createElement('div')
this.styleDropdown.className = 'style-dropdown' this.styleDropdown.className = 'style-dropdown'
this.styleDropdown.style.display = 'none' this.styleDropdown.style.display = 'none' // 初始状态为隐藏
this.styles.forEach(style => { this.styleDropdown.style.cursor = 'pointer' // 鼠标样式
// 为每个样式创建选择项并添加到下拉菜单中
this.styles.forEach((style, index) => {
const styleOption = document.createElement('div') const styleOption = document.createElement('div')
styleOption.className = 'style-option' styleOption.className = 'style-option'
styleOption.innerHTML = style.title styleOption.innerHTML = style.name // 使用 name 作为显示内容
styleOption.onclick = () => this._changeStyle(style.uri) styleOption.style.padding = '5px 5px'
styleOption.style.borderTop = '1px solid #ddd'
styleOption.style.overflow = 'hidden'
// 如果当前样式索引与选中样式索引匹配,添加高亮样式
if (this.currentStyleIndex === index) {
styleOption.style.color = '#409EFF' // 设置选中项字体颜色
} else {
styleOption.style.color = 'black' // 设置默认字体颜色
}
styleOption.onclick = () => this._changeStyle(style, index) // 绑定样式选择事件
// 添加鼠标经过效果
styleOption.addEventListener('mouseover', () => {
styleOption.style.backgroundColor = '#f0f0f0' // 鼠标经过时的背景颜色
})
styleOption.addEventListener('mouseout', () => {
styleOption.style.backgroundColor = 'transparent' // 鼠标移开时的背景颜色
})
this.styleDropdown.appendChild(styleOption) this.styleDropdown.appendChild(styleOption)
}) })
// 将按钮和下拉菜单添加到控件容器中
this.controlContainer.appendChild(this.styleButton) this.controlContainer.appendChild(this.styleButton)
this.controlContainer.appendChild(this.styleDropdown) this.controlContainer.appendChild(this.styleDropdown)
return this.controlContainer return this.controlContainer
} }
/**
* 从地图上移除控件
*/
onRemove () { onRemove () {
this.controlContainer.parentNode.removeChild(this.controlContainer) this.controlContainer.parentNode.removeChild(this.controlContainer)
this.map = null this.map = null
} }
/**
* 切换下拉菜单的显示状态
*/
_toggleDropdown () { _toggleDropdown () {
if (this.styleDropdown.style.display === 'none') { if (this.styleDropdown.style.display === 'none') {
this.styleDropdown.style.display = 'block' this.styleDropdown.style.display = 'block' // 显示下拉菜单
this.styleButton.style.width = '100%' // 可以根据需要调整
} else { } else {
this.styleDropdown.style.display = 'none' this.styleDropdown.style.display = 'none' // 隐藏下拉菜单
this.styleButton.style.width = '29px' // 可以根据需要调整
} }
} }
_changeStyle (styleURI) { /**
this.map.setStyle(styleURI) * 切换地图样式
this.styleDropdown.style.display = 'none' * @param {Object} style - 要切换到的样式对象
* @param {Number} index - 要切换到的样式索引
*/
_changeStyle (style, index) {
this.map.setStyle(style) // 设置地图样式
this.styleDropdown.style.display = 'none' // 隐藏下拉菜单
this.styleButton.style.width = '29px' // 可以根据需要调整
this.currentStyleIndex = index // 更新当前选中的样式索引
this._updateStyleOptions() // 更新下拉菜单中的样式选项
}
/**
* 更新下拉菜单中的样式选项
*/
_updateStyleOptions () {
const styleOptions = this.styleDropdown.querySelectorAll('.style-option')
styleOptions.forEach((option, index) => {
if (this.currentStyleIndex === index) {
option.style.color = '#409EFF' // 高亮选中项
} else {
option.style.color = 'black' // 默认字体颜色
}
})
} }
} }