提交 3d06cc53 作者: 方治民

feat: 添加天地图瓦片图层切换支持

上级 7fd1c23e
...@@ -34,6 +34,31 @@ ...@@ -34,6 +34,31 @@
map.addControl(new mapboxgl.FullscreenControl()) map.addControl(new mapboxgl.FullscreenControl())
map.addControl(new GeolocateInfoControl(), 'bottom-left') map.addControl(new GeolocateInfoControl(), 'bottom-left')
map.addControl(new mapboxgl.ScaleControl()) map.addControl(new mapboxgl.ScaleControl())
map.on('load', () => {
map.addControl(
new LayerControl({
tk: '44357a2d96d38be1388bb43304032c82',
layers: [
{
label: '影像',
value: 'img,cia',
image: '../../assets/images/img_w.png',
active: false
},
{
label: '矢量',
value: 'vec,cva',
image: '../../assets/images/vec_w.png'
},
{
label: '地形',
value: 'ter,cta',
image: '../../assets/images/ter_w.png'
}
]
})
)
})
</script> </script>
</body> </body>
</html> </html>
...@@ -22,8 +22,13 @@ function downloadFile(url, filepath) { ...@@ -22,8 +22,13 @@ function downloadFile(url, filepath) {
res => { res => {
if (res.statusCode === 200) { if (res.statusCode === 200) {
//使用数据流写入 //使用数据流写入
res.pipe(fs.createWriteStream(filepath)) const file = fs.createWriteStream(filepath)
resolve() file.on('finish', () => {
file.close()
resolve()
})
file.on('error', reject)
res.pipe(file)
} else { } else {
res.resume() res.resume()
console.log(`Request Failed With a Status Code: ${res.statusCode}`) console.log(`Request Failed With a Status Code: ${res.statusCode}`)
......
...@@ -171,6 +171,31 @@ ...@@ -171,6 +171,31 @@
map.addControl(new GeolocateInfoControl(), 'bottom-left') map.addControl(new GeolocateInfoControl(), 'bottom-left')
map.addControl(new mapboxgl.ScaleControl()) map.addControl(new mapboxgl.ScaleControl())
map.showTileBoundaries = true map.showTileBoundaries = true
map.on('load', () => {
map.addControl(
new LayerControl({
tk: '44357a2d96d38be1388bb43304032c82',
layers: [
{
label: '影像',
value: 'img,cia',
image: '../../assets/images/img_w.png',
active: false
},
{
label: '矢量',
value: 'vec,cva',
image: '../../assets/images/vec_w.png'
},
{
label: '地形',
value: 'ter,cta',
image: '../../assets/images/ter_w.png'
}
]
})
)
})
const popup = new mapboxgl.Popup({ const popup = new mapboxgl.Popup({
closeButton: false, closeButton: false,
......
...@@ -22,3 +22,61 @@ ...@@ -22,3 +22,61 @@
opacity: 0; opacity: 0;
z-index: -10; z-index: -10;
} }
// 自定义图层控制器样式
.mapboxgl-ctrl button.-active svg {
color: #4264fb;
}
.mapboxgl-ctrl .mapboxgl-ctrl-layer-button .mapboxgl-ctrl-icon {
background-image: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="m13.387 3.425l6.365 4.243a1 1 0 0 1 0 1.664l-6.365 4.244a2.5 2.5 0 0 1-2.774 0L4.248 9.332a1 1 0 0 1 0-1.664l6.365-4.243a2.5 2.5 0 0 1 2.774 0Zm6.639 8.767a2.002 2.002 0 0 1-.577.598l-6.05 4.084a2.5 2.5 0 0 1-2.798 0l-6.05-4.084a2 2 0 0 1-.779-2.29l6.841 4.56a2.5 2.5 0 0 0 2.613.098l.16-.098l6.841-4.56a1.996 1.996 0 0 1-.201 1.692Zm0 3.25a2.002 2.002 0 0 1-.577.598l-6.05 4.084a2.5 2.5 0 0 1-2.798 0l-6.05-4.084a2 2 0 0 1-.779-2.29l6.841 4.56a2.5 2.5 0 0 0 2.613.098l.16-.098l6.841-4.56a1.996 1.996 0 0 1-.201 1.692Z"%2F%3E%3C%2Fsvg%3E') !important;
}
.mapboxgl-ctrl-layer-button {
position: relative;
}
.mapboxgl-ctrl-layer-wrap {
display: none;
justify-items: center;
align-items: center;
position: absolute;
top: 0;
right: 40px;
padding: 10px;
border-radius: 3px;
box-shadow: 0 0 3px #333;
background-color: #fff;
}
.mapboxgl-ctrl-layer {
width: 60px;
height: 60px;
display: flex;
justify-content: center;
border: 2px solid #fff;
position: relative;
}
.mapboxgl-ctrl-layer.active {
border-color: #3385ff;
}
.mapboxgl-ctrl-layer img {
width: 100%;
height: 100%;
}
.mapboxgl-ctrl-layer span {
display: inline-flex;
justify-content: center;
background-color: rgb(0 0 0 / 60%);
color: white;
position: absolute;
bottom: 0;
width: 100%;
}
.mapboxgl-ctrl-layer-button.-active .mapboxgl-ctrl-layer-wrap {
display: flex;
}
function buildTdtTileUrl(id, tk) {
return `${location.origin}/api/tdt/cache/${id}/{z}/{y}/{x}/${tk}?v=2022`
}
/** /**
* 经纬度坐标拾取控件 * 经纬度坐标拾取控件
*/ */
...@@ -53,3 +57,99 @@ class GeolocateInfoControl { ...@@ -53,3 +57,99 @@ class GeolocateInfoControl {
this.map = undefined this.map = undefined
} }
} }
/**
* 图层控件
* 目前仅支持天地图图层
*/
class LayerControl {
constructor(options) {
this.tk = options.tk
this.layers = options.layers
}
onAdd(map) {
this.map = map
this.container = document.createElement('div')
this.container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group mapbox-control'
const layersWrapHtml = []
if (this.layers) {
layersWrapHtml.push('<div class="mapboxgl-ctrl-layer-wrap">')
this.layers.forEach(layer => {
layersWrapHtml.push(`
<div class="mapboxgl-ctrl-layer ${
layer.active ? 'active' : ''
}" data-layer-ids="${layer.value}">
<img src="${layer.image}" alt="${layer.label}" />
<span>${layer.label}</span>
</div>
`)
for (const id of layer.value.split(',')) {
map.addLayer(
{
id: 't_' + id,
type: 'raster',
source: {
type: 'raster',
tiles: [buildTdtTileUrl(id, this.tk)],
tileSize: 256,
maxzoom: 18
},
layout: { visibility: layer.active ? 'visible' : 'none' }
},
'background'
)
}
})
layersWrapHtml.push('</div>')
}
this.container.innerHTML = `
<button type="button" class="mapboxgl-ctrl-layer-button" title="地图样式选择">
<span class="mapboxgl-ctrl-icon" aria-hidden="true" title="Layer"></span>
${layersWrapHtml.join('')}
</button>
`
this.container.addEventListener('click', e => {
const target = e.target
const parent = target.parentElement
if (parent.classList.contains('mapboxgl-ctrl-layer')) {
const ids = parent.getAttribute('data-layer-ids')
const list = parent.parentElement.children
for (let i = 0; i < list.length; i++) {
const item = list[i]
if (item.classList.contains('mapboxgl-ctrl-layer')) {
if (item.getAttribute('data-layer-ids') === ids) {
item.classList.toggle('active')
} else {
item.classList.remove('active')
}
}
}
this.layers.forEach(layer => {
for (const id of layer.value.split(',')) {
map.setLayoutProperty(`t_${id}`, 'visibility', 'none')
}
})
if (parent.classList.contains('active')) {
for (const id of ids.split(',')) {
map.setLayoutProperty(`t_${id}`, 'visibility', 'visible')
}
}
return
}
this.container.querySelector('button').classList.toggle('-active')
})
return this.container
}
onRemove() {
this.container.parentNode.removeChild(this.container)
this.map = undefined
}
}
...@@ -8,6 +8,12 @@ ...@@ -8,6 +8,12 @@
}, },
"layers": [ "layers": [
{ {
"id": "background",
"type": "background",
"layout": { "visibility": "none" },
"paint": { "background-color": "hsla(0, 0%, 0%, 0)" }
},
{
"id": "admin", "id": "admin",
"type": "line", "type": "line",
"source": "admin", "source": "admin",
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论