feat: initialize TJWater WebGIS frontend
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
import type { StyleSpecification, VectorSourceSpecification } from "maplibre-gl";
|
||||
|
||||
import { GEOSERVER_WORKSPACE, MAP_URL } from "../../../lib/config";
|
||||
import { MAP_STYLE_TOKENS } from "./map-colors";
|
||||
|
||||
export const WATER_NETWORK_GLOBAL_VIEW = {
|
||||
bbox3857: [
|
||||
13508801.930066336,
|
||||
3608163.3499832638,
|
||||
13555650.638648884,
|
||||
3633685.137885742
|
||||
]
|
||||
} as const;
|
||||
|
||||
export const SOURCE_LAYERS = {
|
||||
pipes: "geo_pipes_mat",
|
||||
junctions: "geo_junctions_mat",
|
||||
valves: "geo_valves",
|
||||
reservoirs: "geo_reservoirs",
|
||||
scada: "geo_scada",
|
||||
pumps: "geo_pumps",
|
||||
tanks: "geo_tanks"
|
||||
} as const;
|
||||
|
||||
export const WATER_NETWORK_SOURCE_IDS = [
|
||||
"pipes",
|
||||
"junctions",
|
||||
"valves",
|
||||
"reservoirs",
|
||||
"scada",
|
||||
"pumps",
|
||||
"tanks"
|
||||
] as const;
|
||||
|
||||
export type WaterNetworkSourceId = (typeof WATER_NETWORK_SOURCE_IDS)[number];
|
||||
|
||||
export type SupplyLayerCatalogItem = {
|
||||
id: WaterNetworkSourceId;
|
||||
sourceLayer: (typeof SOURCE_LAYERS)[WaterNetworkSourceId];
|
||||
geometry: "line" | "point";
|
||||
available: boolean;
|
||||
label: string;
|
||||
icon: string;
|
||||
};
|
||||
|
||||
export const SUPPLY_LAYER_CATALOG = [
|
||||
{
|
||||
id: "pipes",
|
||||
sourceLayer: SOURCE_LAYERS.pipes,
|
||||
geometry: "line",
|
||||
available: true,
|
||||
label: "管线",
|
||||
icon: "pipe"
|
||||
},
|
||||
{
|
||||
id: "junctions",
|
||||
sourceLayer: SOURCE_LAYERS.junctions,
|
||||
geometry: "point",
|
||||
available: true,
|
||||
label: "节点",
|
||||
icon: "junction"
|
||||
},
|
||||
{
|
||||
id: "valves",
|
||||
sourceLayer: SOURCE_LAYERS.valves,
|
||||
geometry: "point",
|
||||
available: true,
|
||||
label: "阀门",
|
||||
icon: "valve"
|
||||
},
|
||||
{
|
||||
id: "reservoirs",
|
||||
sourceLayer: SOURCE_LAYERS.reservoirs,
|
||||
geometry: "point",
|
||||
available: true,
|
||||
label: "水库",
|
||||
icon: "reservoir"
|
||||
},
|
||||
{
|
||||
id: "scada",
|
||||
sourceLayer: SOURCE_LAYERS.scada,
|
||||
geometry: "point",
|
||||
available: true,
|
||||
label: "SCADA",
|
||||
icon: "scada-pressure"
|
||||
},
|
||||
{
|
||||
id: "pumps",
|
||||
sourceLayer: SOURCE_LAYERS.pumps,
|
||||
geometry: "point",
|
||||
available: false,
|
||||
label: "水泵",
|
||||
icon: "pump"
|
||||
},
|
||||
{
|
||||
id: "tanks",
|
||||
sourceLayer: SOURCE_LAYERS.tanks,
|
||||
geometry: "point",
|
||||
available: false,
|
||||
label: "水箱",
|
||||
icon: "tank"
|
||||
}
|
||||
] as const satisfies readonly SupplyLayerCatalogItem[];
|
||||
|
||||
export const AVAILABLE_WATER_NETWORK_SOURCE_IDS = SUPPLY_LAYER_CATALOG
|
||||
.filter((layer) => layer.available)
|
||||
.map((layer) => layer.id) as Extract<WaterNetworkSourceId, "pipes" | "junctions" | "valves" | "reservoirs" | "scada">[];
|
||||
|
||||
export type AvailableWaterNetworkSourceId = (typeof AVAILABLE_WATER_NETWORK_SOURCE_IDS)[number];
|
||||
|
||||
export function isAvailableWaterNetworkSourceId(value: string): value is AvailableWaterNetworkSourceId {
|
||||
return (AVAILABLE_WATER_NETWORK_SOURCE_IDS as readonly string[]).includes(value);
|
||||
}
|
||||
|
||||
export function createWaterNetworkSources() {
|
||||
return Object.fromEntries(
|
||||
SUPPLY_LAYER_CATALOG
|
||||
.filter((layer) => layer.available)
|
||||
.map((layer) => [layer.id, createGeoServerVectorSource(layer.sourceLayer)])
|
||||
) as Record<AvailableWaterNetworkSourceId, VectorSourceSpecification>;
|
||||
}
|
||||
|
||||
function createGeoServerVectorSource(
|
||||
sourceLayer: (typeof SOURCE_LAYERS)[keyof typeof SOURCE_LAYERS]
|
||||
): VectorSourceSpecification {
|
||||
return {
|
||||
type: "vector",
|
||||
promoteId: "id",
|
||||
tiles: [
|
||||
`${MAP_URL}/gwc/service/wmts/rest/${GEOSERVER_WORKSPACE}:${sourceLayer}/WebMercatorQuad/{z}/{y}/{x}?format=application/vnd.mapbox-vector-tile`
|
||||
],
|
||||
minzoom: 0,
|
||||
maxzoom: 24
|
||||
};
|
||||
}
|
||||
|
||||
export function createBaseStyle(mapboxToken?: string): StyleSpecification {
|
||||
const sources: StyleSpecification["sources"] = {};
|
||||
const layers: StyleSpecification["layers"] = [
|
||||
{
|
||||
id: "background",
|
||||
type: "background",
|
||||
paint: {
|
||||
"background-color": MAP_STYLE_TOKENS.canvas.primary
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
if (mapboxToken) {
|
||||
sources["mapbox-light"] = {
|
||||
type: "raster",
|
||||
tiles: [
|
||||
`https://api.mapbox.com/styles/v1/mapbox/light-v11/tiles/512/{z}/{x}/{y}@2x?access_token=${mapboxToken}`
|
||||
],
|
||||
tileSize: 512,
|
||||
attribution:
|
||||
'© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
};
|
||||
sources["mapbox-satellite"] = {
|
||||
type: "raster",
|
||||
tiles: [
|
||||
`https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v12/tiles/512/{z}/{x}/{y}@2x?access_token=${mapboxToken}`
|
||||
],
|
||||
tileSize: 512,
|
||||
attribution:
|
||||
'© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
};
|
||||
|
||||
layers.push({
|
||||
id: "mapbox-light",
|
||||
type: "raster",
|
||||
source: "mapbox-light",
|
||||
paint: {
|
||||
"raster-opacity": 0.82,
|
||||
"raster-saturation": -0.22,
|
||||
"raster-contrast": 0.04
|
||||
}
|
||||
});
|
||||
layers.push({
|
||||
id: "mapbox-satellite",
|
||||
type: "raster",
|
||||
source: "mapbox-satellite",
|
||||
layout: {
|
||||
visibility: "none"
|
||||
},
|
||||
paint: {
|
||||
"raster-opacity": 0.86,
|
||||
"raster-saturation": -0.16,
|
||||
"raster-contrast": 0.02
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
version: 8,
|
||||
glyphs: "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf",
|
||||
sources,
|
||||
layers
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user