maptile/web/components/maplibre/map.vue

146 lines
3.7 KiB
Vue

<script setup>
import maplibregl, { GlobeControl } from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css";
import * as turf from "@turf/turf";
import MapboxDraw from "@mapbox/mapbox-gl-draw";
import "@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css";
import Code from "./code.vue";
import Editor from "./editor.vue";
import { StyleSpecification } from "maplibre-gl";
const mapContainer = useTemplateRef("mapContainer");
/**
* @type {Ref<maplibregl.Map>}
*/
const map = ref();
const { feature } = useApi();
MapboxDraw.constants.classes.CANVAS = "maplibregl-canvas";
MapboxDraw.constants.classes.CONTROL_BASE = "maplibregl-ctrl";
MapboxDraw.constants.classes.CONTROL_PREFIX = "maplibregl-ctrl-";
MapboxDraw.constants.classes.CONTROL_GROUP = "maplibregl-ctrl-group";
MapboxDraw.constants.classes.ATTRIBUTION = "maplibregl-ctrl-attrib";
MapboxDraw.lib.theme.find((x) => x.id === "gl-draw-lines").paint[
"line-dasharray"
] = [0.2, 2];
/**
* @type {Ref<StyleSpecification & {id string}>}
*/
const styleJSON = ref({
version: 8,
sources: {},
layers: [],
});
onMounted(async () => {
styleJSON.value = await fetch("/style.json").then((res) => res.json());
if (!mapContainer.value) return;
map.value = new maplibregl.Map({
container: mapContainer.value, // container id
// style: "https://demotiles.maplibre.org/style.json", // style URL
// style: "/style.json",
style: styleJSON.value,
center: [120.147376, 30.272934], // starting position [lng, lat]
zoom: 7, // starting zoom
});
map.value.removeControl(map.value._controls[0]);
const draw = new MapboxDraw({
displayControlsDefault: false,
controls: {
point: true,
line_string: true,
polygon: true,
trash: true,
// combine_features: true,
// uncombine_features: true,
},
});
const updateArea = (e) => {
const data = draw.getAll();
console.log(data);
};
map.value.addControl(draw, "top-right");
map.value.on("draw.create", updateArea);
map.value.on("draw.delete", updateArea);
map.value.on("draw.update", updateArea);
map.value.on("draw.selectionchange", (e) => {
console.log(e);
});
map.value.on("load", () => {
handleData();
});
map.value.addControl(new GlobeControl());
});
onUnmounted(() => {
if (map.value) map.value.remove();
});
const featureResult = await feature.list({ page: 1, size: 10 });
const handleData = () => {
if (featureResult.status.value !== "success") return;
let jsonData = turf.featureCollection(
featureResult.data.value.data.map((x) =>
turf.feature(x.geometry, {
id: x.id,
name: x.name,
})
)
);
map.value.addSource("data", { type: "geojson", data: jsonData });
// map.value.addLayer({
// id: "data-symbol",
// type: "symbol",
// source: "data",
// paint: {
// "text-color": "#000",
// },
// layout: {
// "text-field": ["get", "name"],
// "text-size": 12,
// },
// });
// map.value.addLayer({
// id: "data-fill",
// type: "fill",
// source: "data",
// paint: {
// "fill-color": "#000",
// "fill-opacity": 0.5,
// "fill-outline-color": "#FF0000", // 添加边界线颜色
// },
// });
};
const handleCodesChange = (codes) => {
if (!map.value) return;
console.log(codes);
map.value.setStyle(codes);
};
</script>
<template>
<div class="w-full h-full flex justify-between">
<Code
class="h-full flex-[0_0_20%] overflow-hidden"
:codes="styleJSON"
@update:codes="handleCodesChange"
></Code>
<Editor
class="h-full flex-[0_0_20%] overflow-x-hidden overflow-y-auto"
:map-style="styleJSON"
></Editor>
<div ref="mapContainer" class="h-full flex-[0_0_50%]"></div>
</div>
</template>