更新 valve 图层,新增 pump、tank 图层;更新环境变量
This commit is contained in:
@@ -29,6 +29,7 @@ import VectorLayer from "ol/layer/Vector";
|
|||||||
import { Icon, Style } from "ol/style.js";
|
import { Icon, Style } from "ol/style.js";
|
||||||
import { FeatureLike } from "ol/Feature";
|
import { FeatureLike } from "ol/Feature";
|
||||||
import { Point } from "ol/geom";
|
import { Point } from "ol/geom";
|
||||||
|
import VectorTileLayer from "ol/layer/VectorTile";
|
||||||
|
|
||||||
interface MapComponentProps {
|
interface MapComponentProps {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
@@ -193,7 +194,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
// 定义 reservoirs 图层的样式函数,使用固定图标
|
// 定义 reservoirs 图层的样式函数,使用固定图标
|
||||||
const reservoirsStyle = () => {
|
const reservoirStyle = () => {
|
||||||
const reserviorIcon = "/icons/reservior.svg";
|
const reserviorIcon = "/icons/reservior.svg";
|
||||||
return new Style({
|
return new Style({
|
||||||
image: new Icon({
|
image: new Icon({
|
||||||
@@ -203,8 +204,19 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
// 定义 tanks 图层的样式函数,使用固定图标
|
||||||
|
const tankStyle = () => {
|
||||||
|
const tankIcon = "/icons/tank.svg";
|
||||||
|
return new Style({
|
||||||
|
image: new Icon({
|
||||||
|
src: tankIcon,
|
||||||
|
scale: 0.1, // 根据需要调整图标大小
|
||||||
|
anchor: [0.5, 0.5], // 图标锚点居中
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
};
|
||||||
// 定义 valves 图层的样式函数,使用固定图标
|
// 定义 valves 图层的样式函数,使用固定图标
|
||||||
const valvesStyle = function (feature: FeatureLike) {
|
const valveStyle = function (feature: FeatureLike) {
|
||||||
const styles = [];
|
const styles = [];
|
||||||
const valveIcon = "/icons/valve.svg";
|
const valveIcon = "/icons/valve.svg";
|
||||||
|
|
||||||
@@ -238,31 +250,76 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
}
|
}
|
||||||
return styles;
|
return styles;
|
||||||
};
|
};
|
||||||
|
// 定义 pumps 图层的样式函数,使用固定图标
|
||||||
|
const pumpStyle = function (feature: FeatureLike) {
|
||||||
|
const styles = [];
|
||||||
|
const pumpIcon = "/icons/pump.svg";
|
||||||
|
|
||||||
|
const geometry = feature.getGeometry();
|
||||||
|
const lineCoords =
|
||||||
|
geometry?.getType() === "LineString"
|
||||||
|
? (geometry as any).getCoordinates()
|
||||||
|
: null;
|
||||||
|
if (geometry) {
|
||||||
|
const lineCoordsWGS84 = lineCoords.map((coord: []) => {
|
||||||
|
const [lon, lat] = toLonLat(coord);
|
||||||
|
return [lon, lat];
|
||||||
|
});
|
||||||
|
// 计算中点
|
||||||
|
const lineStringFeature = lineString(lineCoordsWGS84);
|
||||||
|
const lineLength = length(lineStringFeature);
|
||||||
|
const midPoint = along(lineStringFeature, lineLength / 2).geometry
|
||||||
|
.coordinates;
|
||||||
|
// 在中点添加 icon 样式
|
||||||
|
const midPointMercator = toMercator(midPoint);
|
||||||
|
styles.push(
|
||||||
|
new Style({
|
||||||
|
geometry: new Point(midPointMercator),
|
||||||
|
image: new Icon({
|
||||||
|
src: pumpIcon,
|
||||||
|
scale: 0.12,
|
||||||
|
anchor: [0.5, 0.5],
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return styles;
|
||||||
|
};
|
||||||
// 矢量瓦片数据源和图层
|
// 矢量瓦片数据源和图层
|
||||||
const junctionSource = new VectorTileSource({
|
const junctionSource = new VectorTileSource({
|
||||||
url: `${MAP_URL}/gwc/service/tms/1.0.0/${MAP_WORKSPACE}:geo_junctions_mat@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
|
url: `${MAP_URL}/gwc/service/tms/1.0.0/${MAP_WORKSPACE}:geo_junctions@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
|
||||||
format: new MVT(),
|
format: new MVT(),
|
||||||
projection: "EPSG:3857",
|
projection: "EPSG:3857",
|
||||||
});
|
});
|
||||||
const pipeSource = new VectorTileSource({
|
const pipeSource = new VectorTileSource({
|
||||||
url: `${MAP_URL}/gwc/service/tms/1.0.0/${MAP_WORKSPACE}:geo_pipes_mat@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
|
url: `${MAP_URL}/gwc/service/tms/1.0.0/${MAP_WORKSPACE}:geo_pipes@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
|
||||||
format: new MVT(),
|
format: new MVT(),
|
||||||
projection: "EPSG:3857",
|
projection: "EPSG:3857",
|
||||||
});
|
});
|
||||||
|
const valveSource = new VectorTileSource({
|
||||||
|
url: `${MAP_URL}/gwc/service/tms/1.0.0/${MAP_WORKSPACE}:geo_valves@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
|
||||||
|
format: new MVT(),
|
||||||
|
projection: "EPSG:3857",
|
||||||
|
});
|
||||||
|
const reservoirSource = new VectorSource({
|
||||||
|
url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_reservoirs&outputFormat=application/json`,
|
||||||
|
format: new GeoJson(),
|
||||||
|
});
|
||||||
|
const pumpSource = new VectorSource({
|
||||||
|
url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_pumps&outputFormat=application/json`,
|
||||||
|
format: new GeoJson(),
|
||||||
|
});
|
||||||
|
const tankSource = new VectorSource({
|
||||||
|
url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_tanks&outputFormat=application/json`,
|
||||||
|
format: new GeoJson(),
|
||||||
|
});
|
||||||
const scadaSource = new VectorSource({
|
const scadaSource = new VectorSource({
|
||||||
url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_scada&outputFormat=application/json`,
|
url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_scada&outputFormat=application/json`,
|
||||||
format: new GeoJson(),
|
format: new GeoJson(),
|
||||||
});
|
});
|
||||||
const reservoirsSource = new VectorSource({
|
|
||||||
url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_reservoirs&outputFormat=application/json`,
|
|
||||||
format: new GeoJson(),
|
|
||||||
});
|
|
||||||
const valvesSource = new VectorSource({
|
|
||||||
url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_valves&outputFormat=application/json`,
|
|
||||||
format: new GeoJson(),
|
|
||||||
});
|
|
||||||
// WebGL 渲染优化显示
|
// WebGL 渲染优化显示
|
||||||
const junctionLayer = new WebGLVectorTileLayer({
|
const junctionsLayer = new WebGLVectorTileLayer({
|
||||||
source: junctionSource as any, // 使用 WebGL 渲染
|
source: junctionSource as any, // 使用 WebGL 渲染
|
||||||
style: defaultFlatStyle,
|
style: defaultFlatStyle,
|
||||||
extent: MAP_EXTENT, // 设置图层范围
|
extent: MAP_EXTENT, // 设置图层范围
|
||||||
@@ -282,7 +339,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const pipeLayer = new WebGLVectorTileLayer({
|
const pipesLayer = new WebGLVectorTileLayer({
|
||||||
source: pipeSource as any, // 使用 WebGL 渲染
|
source: pipeSource as any, // 使用 WebGL 渲染
|
||||||
style: defaultFlatStyle,
|
style: defaultFlatStyle,
|
||||||
extent: MAP_EXTENT, // 设置图层范围
|
extent: MAP_EXTENT, // 设置图层范围
|
||||||
@@ -307,6 +364,58 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const valvesLayer = new VectorTileLayer({
|
||||||
|
source: valveSource,
|
||||||
|
style: valveStyle,
|
||||||
|
extent: MAP_EXTENT, // 设置图层范围
|
||||||
|
maxZoom: 24,
|
||||||
|
minZoom: 12,
|
||||||
|
properties: {
|
||||||
|
name: "阀门", // 设置图层名称
|
||||||
|
value: "valves",
|
||||||
|
type: "linestring",
|
||||||
|
properties: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const reservoirsLayer = new VectorLayer({
|
||||||
|
source: reservoirSource,
|
||||||
|
style: reservoirStyle,
|
||||||
|
extent: MAP_EXTENT, // 设置图层范围
|
||||||
|
maxZoom: 24,
|
||||||
|
minZoom: 12,
|
||||||
|
properties: {
|
||||||
|
name: "水库", // 设置图层名称
|
||||||
|
value: "reservoirs",
|
||||||
|
type: "point",
|
||||||
|
properties: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const pumpsLayer = new VectorLayer({
|
||||||
|
source: pumpSource,
|
||||||
|
style: pumpStyle,
|
||||||
|
extent: MAP_EXTENT, // 设置图层范围
|
||||||
|
maxZoom: 24,
|
||||||
|
minZoom: 12,
|
||||||
|
properties: {
|
||||||
|
name: "水泵", // 设置图层名称
|
||||||
|
value: "pumps",
|
||||||
|
type: "linestring",
|
||||||
|
properties: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const tanksLayer = new VectorLayer({
|
||||||
|
source: tankSource,
|
||||||
|
style: tankStyle,
|
||||||
|
extent: MAP_EXTENT, // 设置图层范围
|
||||||
|
maxZoom: 24,
|
||||||
|
minZoom: 12,
|
||||||
|
properties: {
|
||||||
|
name: "水箱", // 设置图层名称
|
||||||
|
value: "tanks",
|
||||||
|
type: "point",
|
||||||
|
properties: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
const scadaLayer = new VectorLayer({
|
const scadaLayer = new VectorLayer({
|
||||||
source: scadaSource,
|
source: scadaSource,
|
||||||
style: scadaStyle,
|
style: scadaStyle,
|
||||||
@@ -320,32 +429,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
properties: [],
|
properties: [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const reservoirsLayer = new VectorLayer({
|
|
||||||
source: reservoirsSource,
|
|
||||||
style: reservoirsStyle,
|
|
||||||
extent: MAP_EXTENT, // 设置图层范围
|
|
||||||
maxZoom: 24,
|
|
||||||
minZoom: 12,
|
|
||||||
properties: {
|
|
||||||
name: "水库", // 设置图层名称
|
|
||||||
value: "reservoirs",
|
|
||||||
type: "point",
|
|
||||||
properties: [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const valvesLayer = new VectorLayer({
|
|
||||||
source: valvesSource,
|
|
||||||
style: valvesStyle,
|
|
||||||
extent: MAP_EXTENT, // 设置图层范围
|
|
||||||
maxZoom: 24,
|
|
||||||
minZoom: 12,
|
|
||||||
properties: {
|
|
||||||
name: "阀门", // 设置图层名称
|
|
||||||
value: "valves",
|
|
||||||
type: "linestring",
|
|
||||||
properties: [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!mapRef.current) return;
|
if (!mapRef.current) return;
|
||||||
// 缓存 junction、pipe 数据,提供给 deck.gl 显示标签使用
|
// 缓存 junction、pipe 数据,提供给 deck.gl 显示标签使用
|
||||||
@@ -462,20 +546,72 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
console.error("Pipe tile load error:", error);
|
console.error("Pipe tile load error:", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 监听 junctionLayer 的 visible 变化
|
// 监听 junctionsLayer 的 visible 变化
|
||||||
const handleJunctionVisibilityChange = () => {
|
const handleJunctionVisibilityChange = () => {
|
||||||
const isVisible = junctionLayer.getVisible();
|
const isVisible = junctionsLayer.getVisible();
|
||||||
setShowJunctionTextLayer(isVisible);
|
setShowJunctionTextLayer(isVisible);
|
||||||
};
|
};
|
||||||
// 监听 pipeLayer 的 visible 变化
|
// 监听 pipesLayer 的 visible 变化
|
||||||
const handlePipeVisibilityChange = () => {
|
const handlePipeVisibilityChange = () => {
|
||||||
const isVisible = pipeLayer.getVisible();
|
const isVisible = pipesLayer.getVisible();
|
||||||
setShowPipeTextLayer(isVisible);
|
setShowPipeTextLayer(isVisible);
|
||||||
};
|
};
|
||||||
// 添加事件监听器
|
// 添加事件监听器
|
||||||
junctionLayer.on("change:visible", handleJunctionVisibilityChange);
|
junctionsLayer.on("change:visible", handleJunctionVisibilityChange);
|
||||||
pipeLayer.on("change:visible", handlePipeVisibilityChange);
|
pipesLayer.on("change:visible", handlePipeVisibilityChange);
|
||||||
|
const availableLayers: any[] = [];
|
||||||
|
config.MAP_AVAILABLE_LAYERS.forEach((layerValue) => {
|
||||||
|
switch (layerValue) {
|
||||||
|
case "junctions":
|
||||||
|
availableLayers.push(junctionsLayer);
|
||||||
|
break;
|
||||||
|
case "pipes":
|
||||||
|
availableLayers.push(pipesLayer);
|
||||||
|
break;
|
||||||
|
case "valves":
|
||||||
|
availableLayers.push(valvesLayer);
|
||||||
|
break;
|
||||||
|
case "reservoirs":
|
||||||
|
availableLayers.push(reservoirsLayer);
|
||||||
|
break;
|
||||||
|
case "pumps":
|
||||||
|
availableLayers.push(pumpsLayer);
|
||||||
|
break;
|
||||||
|
case "tanks":
|
||||||
|
availableLayers.push(tanksLayer);
|
||||||
|
break;
|
||||||
|
case "scada":
|
||||||
|
availableLayers.push(scadaLayer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 重新排列图层顺序,确保顺序 点>线>面
|
||||||
|
availableLayers.sort((a, b) => {
|
||||||
|
// 明确顺序(点类优先)
|
||||||
|
const order = [
|
||||||
|
"junctions",
|
||||||
|
"reservoirs",
|
||||||
|
"tanks",
|
||||||
|
"scada",
|
||||||
|
"pipes",
|
||||||
|
"valves",
|
||||||
|
"pumps",
|
||||||
|
].reverse();
|
||||||
|
// 取值时做安全检查,兼容不同写法(properties.value 或 直接 value)
|
||||||
|
const getValue = (layer: any) => {
|
||||||
|
const props = layer.get ? layer.get("properties") : undefined;
|
||||||
|
return (props && props.value) || layer.get?.("value") || "";
|
||||||
|
};
|
||||||
|
const aVal = getValue(a);
|
||||||
|
const bVal = getValue(b);
|
||||||
|
let ia = order.indexOf(aVal);
|
||||||
|
let ib = order.indexOf(bVal);
|
||||||
|
// 如果未在 order 中找到,放到末尾
|
||||||
|
if (ia === -1) ia = order.length;
|
||||||
|
if (ib === -1) ib = order.length;
|
||||||
|
return ia - ib;
|
||||||
|
});
|
||||||
|
console.log("Available Layers:", availableLayers);
|
||||||
const map = new OlMap({
|
const map = new OlMap({
|
||||||
target: mapRef.current,
|
target: mapRef.current,
|
||||||
view: new View({
|
view: new View({
|
||||||
@@ -483,13 +619,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
projection: "EPSG:3857",
|
projection: "EPSG:3857",
|
||||||
}),
|
}),
|
||||||
// 图层依面、线、点、标注次序添加
|
// 图层依面、线、点、标注次序添加
|
||||||
layers: [
|
layers: [...availableLayers],
|
||||||
pipeLayer,
|
|
||||||
junctionLayer,
|
|
||||||
valvesLayer,
|
|
||||||
scadaLayer,
|
|
||||||
reservoirsLayer,
|
|
||||||
],
|
|
||||||
controls: [],
|
controls: [],
|
||||||
});
|
});
|
||||||
setMap(map);
|
setMap(map);
|
||||||
@@ -522,8 +652,8 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
|
|
||||||
// 清理函数
|
// 清理函数
|
||||||
return () => {
|
return () => {
|
||||||
junctionLayer.un("change:visible", handleJunctionVisibilityChange);
|
junctionsLayer.un("change:visible", handleJunctionVisibilityChange);
|
||||||
pipeLayer.un("change:visible", handlePipeVisibilityChange);
|
pipesLayer.un("change:visible", handlePipeVisibilityChange);
|
||||||
map.setTarget(undefined);
|
map.setTarget(undefined);
|
||||||
map.dispose();
|
map.dispose();
|
||||||
deck.finalize();
|
deck.finalize();
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ export const config = {
|
|||||||
12, // 在缩放级别 24 时,圆形半径为 12px
|
12, // 在缩放级别 24 时,圆形半径为 12px
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// 添加其他配置项...
|
MAP_AVAILABLE_LAYERS: process.env.NEXT_PUBLIC_MAP_AVAILABLE_LAYERS
|
||||||
|
? process.env.NEXT_PUBLIC_MAP_AVAILABLE_LAYERS.split(",").map((item) =>
|
||||||
|
item.trim().toLowerCase()
|
||||||
|
)
|
||||||
|
: ["junctions", "pipes", "valves", "reservoirs", "pumps", "tanks", "scada"],
|
||||||
};
|
};
|
||||||
export const NETWORK_NAME = process.env.NEXT_PUBLIC_NETWORK_NAME || "tjwater";
|
export const NETWORK_NAME = process.env.NEXT_PUBLIC_NETWORK_NAME || "tjwater";
|
||||||
export const MAPBOX_TOKEN =
|
export const MAPBOX_TOKEN =
|
||||||
|
|||||||
Reference in New Issue
Block a user