add: basemap selector

map
g 3 years ago
parent 78df895fe9
commit ed609322fa

@ -1,228 +1,266 @@
<template>
<div class="map-wrap">
<div id="map" class="map" ref="mapContainer"></div>
</div>
<div class="map-wrap">
<div id="basemap-selector"><va-select v-model="valuebm" :options="options"/></div>
<div id="map" class="map" ref="mapContainer"></div>
</div>
</template>
<script>
import maplibregl from "maplibre-gl";
import { markRaw, onMounted, onUnmounted, reactive, shallowRef, watch } from "vue";
import {
markRaw,
onMounted,
onUnmounted,
reactive,
shallowRef,
watch,
} from "vue";
export default {
name: "map-component",
props: {
idlist: {
type: Array,
required: true,
}
name: "map-component",
props: {
idlist: {
type: Array,
required: true,
},
setup(props, context) {
const mapContainer = shallowRef(null);
const map = shallowRef(null);
let currentFadr = reactive({ "fadr": [] });
const apiKey = "pk.eyJ1IjoiZ2hlcm1hbnQiLCJhIjoiY2pncDUwcnRmNDQ4ZjJ4czdjZXMzaHZpNyJ9.3rFyYRRtvLUngHm027HZ7A";
},
data() {
return {
valuebm: '',
options: ['Карта', 'Спутник', 'Монохром']
}
},
setup(props, context) {
const mapContainer = shallowRef(null);
const map = shallowRef(null);
let currentFadr = reactive({ fadr: [] });
const apiKey =
"pk.eyJ1IjoiZ2hlcm1hbnQiLCJhIjoiY2pncDUwcnRmNDQ4ZjJ4czdjZXMzaHZpNyJ9.3rFyYRRtvLUngHm027HZ7A";
watch(
() => [...props.idlist],
(_currentValue, _oldValue) => {
updateSamplesLayer();
}
);
const buildMap = () => {
map.value = markRaw(
new maplibregl.Map({
container: mapContainer.value, // container id
// DOCS: https://maplibre.org/maplibre-gl-js-docs/style-spec/
style: {
version: 8,
sources: {},
layers: [],
},
center: [80, 40], // starting position [lng, lat]
zoom: 2, // starting zoom
maxZoom: 10,
})
);
map.value.on("load", () => {
map.value.addSource("topo-basemap", {
type: "raster",
tiles: [
`https://api.mapbox.com/styles/v1/ghermant/cl9vd1nji002n15s2xxj25f4m/tiles/256/{z}/{x}/{y}@2x?access_token=${apiKey}`,
],
});
map.value.addSource("satellite-basemap", {
type: "raster",
tiles: [
`https://api.mapbox.com/styles/v1/ghermant/cl9olarp0002i14vq9a2d0e7g/tiles/256/{z}/{x}/{y}@2x?access_token=${apiKey}`,
],
});
watch(() => [...props.idlist], (_currentValue, _oldValue) => {
updateSamplesLayer()
map.value.addSource("mono-basemap", {
type: "raster",
tiles: [
`https://api.mapbox.com/styles/v1/ghermant/cl9vd7xwi004u14nxu3j83scj/tiles/256/{z}/{x}/{y}@2x?access_token=${apiKey}`,
],
});
const buildMap = () => {
map.value = markRaw(new maplibregl.Map({
container: mapContainer.value, // container id
// DOCS: https://maplibre.org/maplibre-gl-js-docs/style-spec/
style: {
version: 8,
sources: {},
layers: []
},
center: [80, 40], // starting position [lng, lat]
zoom: 2, // starting zoom
maxZoom: 10
}));
map.value.on('load', () => {
map.value.addSource('basemap-source', {
'type': 'raster',
'tiles': [`https://api.mapbox.com/styles/v1/ghermant/cl8vg2r97001m14o4c2qzw9t6/tiles/256/{z}/{x}/{y}@2x?access_token=${apiKey}`]
})
map.value.addLayer(
{
'id': 'basemap-layer',
'type': 'raster',
'source': 'basemap-source',
'paint': {}
}
);
map.value.addSource('samples', {
'type': 'vector',
"tiles": ["http://localhost:8080/martin/public.geodata/{z}/{x}/{y}.pbf"],
'promoteId': 'fadr',
});
map.value.addLayer({
'id': 'samples-layer',
'source': 'samples',
'source-layer': 'public.geodata',
'type': 'circle',
'paint': {
'circle-stroke-width': 1,
'circle-stroke-color': '#FFFFFF',
'circle-color': [
'case',
['boolean', ['feature-state', 'beenClicked'], false],
'#fec44f',
'#d95f0e'
],
'circle-opacity': 0.8,
'circle-radius': 8
},
filter: ["match", ["get", "internal_id"], props.idlist, true, false]
});
});
const popup = new maplibregl.Popup({
closeButton: false,
closeOnClick: false,
})
map.value.on('mouseover', 'samples-layer', (e) => {
// Change the cursor style as a UI indicator.
map.value.getCanvas().style.cursor = 'pointer';
// Populate the popup and set its coordinates
// based on the feature found.
popup
.setLngLat(e.lngLat)
.setHTML(`Записей в точке: <b>${e.features.length}</b>`)
.addTo(map.value);
});
map.value.on('mouseleave', 'samples-layer', (e) => {
map.value.getCanvas().style.cursor = '';
popup.remove();
});
map.value.on('click', 'samples-layer', (e) => {
let newFadr = e.features[0].properties["fadr"];
let newFadrFound = currentFadr["fadr"].indexOf(newFadr)
if (newFadrFound > -1) {
//remove old paint
map.value.setFeatureState(
{
source: 'samples',
sourceLayer: 'public.geodata',
id: newFadr
},
{ beenClicked: false }
);
// remove from filters
currentFadr["fadr"].splice(newFadrFound, 1)
} else {
// apply new paint
map.value.setFeatureState(
{
source: 'samples',
sourceLayer: 'public.geodata',
id: newFadr
},
{ beenClicked: true }
);
// add to filters
currentFadr["fadr"].push(newFadr);
}
context.emit('mapClick', currentFadr);
});
map.value.on('click', (e) => {
const features = map.value.queryRenderedFeatures(e.point)
if (!features.length) {
currentFadr["fadr"].forEach((oldFadr) => {
map.value.setFeatureState(
{
source: 'samples',
sourceLayer: 'public.geodata',
id: oldFadr
},
{ beenClicked: false }
);
})
currentFadr["fadr"].length = 0;
}
context.emit('mapClick', currentFadr);
});
};
const updateSamplesLayer = () => {
if (map.value.getLayer('samples-layer')) {
map.value.removeLayer('samples-layer');
}
if (props.idlist.length) {
map.value.addLayer({
'id': 'samples-layer',
'source': 'samples',
'source-layer': 'public.geodata',
'type': 'circle',
'paint': {
'circle-stroke-width': 1,
'circle-stroke-color': '#FFFFFF',
'circle-color': [
'case',
['boolean', ['feature-state', 'beenClicked'], false],
'#fec44f',
'#d95f0e'
],
'circle-opacity': 0.8,
'circle-radius': 8
},
filter: ["match", ["get", "internal_id"], props.idlist, true, false]
});
}
};
onMounted(() => {
buildMap()
map.value.addLayer({
id: "basemap-layer",
type: "raster",
source: "topo-basemap",
paint: {},
});
onUnmounted(() => {
// TODO: remove even listeners too
map.value?.remove();
})
map.value.addSource("samples", {
type: "vector",
tiles: [
"http://localhost:8080/martin/public.geodata/{z}/{x}/{y}.pbf",
],
promoteId: "fadr",
});
return {
map, mapContainer, currentFadr
map.value.addLayer({
id: "samples-layer",
source: "samples",
"source-layer": "public.geodata",
type: "circle",
paint: {
"circle-stroke-width": 1,
"circle-stroke-color": "#FFFFFF",
"circle-color": [
"case",
["boolean", ["feature-state", "beenClicked"], false],
"#fec44f",
"#d95f0e",
],
"circle-opacity": 0.8,
"circle-radius": 8,
},
filter: ["match", ["get", "internal_id"], props.idlist, true, false],
});
});
const popup = new maplibregl.Popup({
closeButton: false,
closeOnClick: false,
});
map.value.on("mouseover", "samples-layer", (e) => {
// Change the cursor style as a UI indicator.
map.value.getCanvas().style.cursor = "pointer";
// Populate the popup and set its coordinates
// based on the feature found.
popup
.setLngLat(e.lngLat)
.setHTML(`Записей в точке: <b>${e.features.length}</b>`)
.addTo(map.value);
});
map.value.on("mouseleave", "samples-layer", (e) => {
map.value.getCanvas().style.cursor = "";
popup.remove();
});
map.value.on("click", "samples-layer", (e) => {
let newFadr = e.features[0].properties["fadr"];
let newFadrFound = currentFadr["fadr"].indexOf(newFadr);
if (newFadrFound > -1) {
//remove old paint
map.value.setFeatureState(
{
source: "samples",
sourceLayer: "public.geodata",
id: newFadr,
},
{ beenClicked: false }
);
// remove from filters
currentFadr["fadr"].splice(newFadrFound, 1);
} else {
// apply new paint
map.value.setFeatureState(
{
source: "samples",
sourceLayer: "public.geodata",
id: newFadr,
},
{ beenClicked: true }
);
// add to filters
currentFadr["fadr"].push(newFadr);
}
}
}
</script>
context.emit("mapClick", currentFadr);
});
map.value.on("click", (e) => {
const features = map.value.queryRenderedFeatures(e.point);
if (!features.length) {
currentFadr["fadr"].forEach((oldFadr) => {
map.value.setFeatureState(
{
source: "samples",
sourceLayer: "public.geodata",
id: oldFadr,
},
{ beenClicked: false }
);
});
currentFadr["fadr"].length = 0;
}
context.emit("mapClick", currentFadr);
});
};
const updateSamplesLayer = () => {
if (map.value.getLayer("samples-layer")) {
map.value.removeLayer("samples-layer");
}
if (props.idlist.length) {
map.value.addLayer({
id: "samples-layer",
source: "samples",
"source-layer": "public.geodata",
type: "circle",
paint: {
"circle-stroke-width": 1,
"circle-stroke-color": "#FFFFFF",
"circle-color": [
"case",
["boolean", ["feature-state", "beenClicked"], false],
"#fec44f",
"#d95f0e",
],
"circle-opacity": 0.8,
"circle-radius": 8,
},
filter: ["match", ["get", "internal_id"], props.idlist, true, false],
});
}
};
onMounted(() => {
buildMap();
});
onUnmounted(() => {
// TODO: remove even listeners too
map.value?.remove();
});
return {
map,
mapContainer,
currentFadr,
};
},
};
</script>
<style lang="css">
.map-wrap {
position: relative;
height: 100vh;
width: 100%;
position: relative;
height: 100vh;
width: 100%;
}
.map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
/* z-index: -1; */
position: absolute;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: -1;
}
#basemap-selector {
position: absolute;
top: 1rem;
left: 1rem;
}
</style>

Loading…
Cancel
Save