feat(map): refine SCADA feature experience
This commit is contained in:
@@ -3,10 +3,7 @@ import {
|
||||
INTERACTIVE_HIT_LAYER_IDS,
|
||||
waterNetworkLayers
|
||||
} from "./layers";
|
||||
import {
|
||||
DRAINAGE_SELECTED_OUTLINE_COLORS,
|
||||
DRAINAGE_SOURCE_COLORS
|
||||
} from "./map-colors";
|
||||
import { MAP_STYLE_TOKENS } from "./map-colors";
|
||||
import { DRAINAGE_LAYER_VISUALS, MAP_MAX_ZOOM } from "./map-layer-visuals";
|
||||
|
||||
describe("drainage network interaction layers", () => {
|
||||
@@ -56,61 +53,49 @@ describe("drainage network interaction layers", () => {
|
||||
|
||||
it("provides persistent selected layers for every source", () => {
|
||||
const selectedLayerIds = [
|
||||
"pipes-selected-halo",
|
||||
"pipes-selected-outline",
|
||||
"pipes-selected",
|
||||
"junctions-selected-halo",
|
||||
"junctions-selected",
|
||||
"orifices-selected-halo",
|
||||
"orifices-selected-outline",
|
||||
"orifices-selected",
|
||||
"pumps-selected-halo",
|
||||
"pumps-selected-outline",
|
||||
"pumps-selected",
|
||||
"outfalls-selected-halo",
|
||||
"outfalls-selected"
|
||||
];
|
||||
|
||||
selectedLayerIds.forEach((layerId) => {
|
||||
const layer = waterNetworkLayers.find((candidate) => candidate.id === layerId);
|
||||
expect(layer && "filter" in layer ? layer.filter : undefined).toEqual(["==", ["get", "id"], ""]);
|
||||
expect(layer && "minzoom" in layer ? layer.minzoom : undefined).toBeUndefined();
|
||||
expect(layer && "filter" in layer ? layer.filter : undefined).toBeUndefined();
|
||||
const paint = layer?.paint as Record<string, unknown> | undefined;
|
||||
expect(JSON.stringify(paint)).toContain("feature-state");
|
||||
expect(JSON.stringify(paint)).toContain("selected");
|
||||
});
|
||||
});
|
||||
|
||||
it("renders selected features as a halo, complementary outline, and source-color core", () => {
|
||||
const expectedSelectedColors = [
|
||||
["pipes-selected-outline", "line-color", DRAINAGE_SELECTED_OUTLINE_COLORS.conduits],
|
||||
["pipes-selected", "line-color", DRAINAGE_SOURCE_COLORS.conduits],
|
||||
["junctions-selected", "circle-stroke-color", DRAINAGE_SELECTED_OUTLINE_COLORS.junctions],
|
||||
["junctions-selected", "circle-color", DRAINAGE_SOURCE_COLORS.junctions],
|
||||
["orifices-selected-outline", "line-color", DRAINAGE_SELECTED_OUTLINE_COLORS.orifices],
|
||||
["orifices-selected", "line-color", DRAINAGE_SOURCE_COLORS.orifices],
|
||||
["pumps-selected-outline", "line-color", DRAINAGE_SELECTED_OUTLINE_COLORS.pumps],
|
||||
["pumps-selected", "line-color", DRAINAGE_SOURCE_COLORS.pumps],
|
||||
["outfalls-selected", "circle-stroke-color", DRAINAGE_SELECTED_OUTLINE_COLORS.outfalls],
|
||||
["outfalls-selected", "circle-color", DRAINAGE_SOURCE_COLORS.outfalls]
|
||||
it("renders selected features as opaque hollow outlines", () => {
|
||||
const expectedLineOutlines = [
|
||||
["pipes-selected-outline", DRAINAGE_LAYER_VISUALS.conduits],
|
||||
["orifices-selected-outline", DRAINAGE_LAYER_VISUALS.orifices],
|
||||
["pumps-selected-outline", DRAINAGE_LAYER_VISUALS.pumps]
|
||||
] as const;
|
||||
|
||||
expectedSelectedColors.forEach(([layerId, paintProperty, color]) => {
|
||||
expectedLineOutlines.forEach(([layerId, visuals]) => {
|
||||
const layer = waterNetworkLayers.find((candidate) => candidate.id === layerId);
|
||||
const paint = layer?.paint as Record<string, unknown> | undefined;
|
||||
expect(paint?.[paintProperty]).toBe(color);
|
||||
expect(paint?.["line-color"]).toBe(MAP_STYLE_TOKENS.state.selected);
|
||||
expect(paint?.["line-gap-width"]).toBe(visuals.selectedWidth);
|
||||
expect(paint?.["line-width"]).toBe(visuals.selectedBorderWidth);
|
||||
expect(paint?.["line-opacity"]).toEqual(["case", ["boolean", ["feature-state", "selected"], false], 1, 0]);
|
||||
});
|
||||
|
||||
const layerIds = waterNetworkLayers.map((layer) => layer.id);
|
||||
["pipes", "orifices", "pumps"].forEach((prefix) => {
|
||||
expect(layerIds.indexOf(`${prefix}-selected-halo`)).toBeLessThan(
|
||||
layerIds.indexOf(`${prefix}-selected-outline`)
|
||||
);
|
||||
expect(layerIds.indexOf(`${prefix}-selected-outline`)).toBeLessThan(
|
||||
layerIds.indexOf(`${prefix}-selected`)
|
||||
);
|
||||
});
|
||||
["junctions", "outfalls"].forEach((prefix) => {
|
||||
expect(layerIds.indexOf(`${prefix}-selected-halo`)).toBeLessThan(
|
||||
layerIds.indexOf(`${prefix}-selected`)
|
||||
);
|
||||
const expectedPointOutlines = [
|
||||
"junctions-selected",
|
||||
"outfalls-selected"
|
||||
] as const;
|
||||
expectedPointOutlines.forEach((layerId) => {
|
||||
const layer = waterNetworkLayers.find((candidate) => candidate.id === layerId);
|
||||
const paint = layer?.paint as Record<string, unknown> | undefined;
|
||||
expect(paint?.["circle-color"]).toBe(MAP_STYLE_TOKENS.canvas.transparent);
|
||||
expect(JSON.stringify(paint?.["circle-opacity"])).toContain("feature-state");
|
||||
expect(paint?.["circle-stroke-color"]).toBe(MAP_STYLE_TOKENS.state.selected);
|
||||
expect(JSON.stringify(paint?.["circle-stroke-opacity"])).toContain("selected");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -118,7 +103,7 @@ describe("drainage network interaction layers", () => {
|
||||
expect(MAP_MAX_ZOOM).toBe(24);
|
||||
expect(DRAINAGE_LAYER_VISUALS.junctions.minzoom).toBe(12);
|
||||
expect(DRAINAGE_LAYER_VISUALS.junctions.radius).toEqual([
|
||||
"interpolate", ["linear"], ["zoom"], 12, 1, 16, 3, 20, 5.5, 24, 8
|
||||
"interpolate", ["linear"], ["zoom"], 12, 0.6, 14, 1, 15, 1.5, 16, 3, 20, 5.5, 24, 8
|
||||
]);
|
||||
expect(DRAINAGE_LAYER_VISUALS.outfalls.radius).toEqual([
|
||||
"interpolate", ["linear"], ["zoom"], 11, 3, 16, 5, 20, 7, 24, 9
|
||||
@@ -134,18 +119,39 @@ describe("drainage network interaction layers", () => {
|
||||
expect((DRAINAGE_LAYER_VISUALS.junctions.hitRadius as unknown[]).at(-1)).toBe(14);
|
||||
});
|
||||
|
||||
it("prioritizes continuous conduits before full junction detail at low zoom", () => {
|
||||
expect(DRAINAGE_LAYER_VISUALS.conduits.width).toEqual([
|
||||
"interpolate", ["linear"], ["zoom"],
|
||||
9, 1.1,
|
||||
13, 2,
|
||||
17, ["+", 2.5, ["/", ["coalesce", ["get", "diameter"], 100], 360]],
|
||||
22, ["+", 3.5, ["/", ["coalesce", ["get", "diameter"], 100], 300]],
|
||||
24, ["+", 4, ["/", ["coalesce", ["get", "diameter"], 100], 280]]
|
||||
]);
|
||||
expect(DRAINAGE_LAYER_VISUALS.junctions.haloOpacity).toEqual([
|
||||
"interpolate", ["linear"], ["zoom"], 12, 0, 14, 0, 15, 1
|
||||
]);
|
||||
|
||||
const junctionHalo = waterNetworkLayers.find((layer) => layer.id === "junctions-halo");
|
||||
const orifices = waterNetworkLayers.find((layer) => layer.id === "orifices");
|
||||
const pumps = waterNetworkLayers.find((layer) => layer.id === "pumps");
|
||||
expect((junctionHalo?.paint as Record<string, unknown>)?.["circle-opacity"]).toBe(DRAINAGE_LAYER_VISUALS.junctions.haloOpacity);
|
||||
expect((orifices?.paint as Record<string, unknown>)?.["line-dasharray"]).toEqual([4, 2]);
|
||||
expect((pumps?.paint as Record<string, unknown>)?.["line-dasharray"]).toEqual([6, 2, 1.5, 2]);
|
||||
});
|
||||
|
||||
it("uses the centralized geometry tokens in rendered layers", () => {
|
||||
const expectedGeometry = [
|
||||
["pipes-flow", "line-width", DRAINAGE_LAYER_VISUALS.conduits.width],
|
||||
["pipes-selected-halo", "line-width", DRAINAGE_LAYER_VISUALS.conduits.selectedHaloWidth],
|
||||
["pipes-selected-outline", "line-width", DRAINAGE_LAYER_VISUALS.conduits.selectedBorderWidth],
|
||||
["junctions", "circle-radius", DRAINAGE_LAYER_VISUALS.junctions.radius],
|
||||
["junctions-selected-halo", "circle-radius", DRAINAGE_LAYER_VISUALS.junctions.selectedHaloRadius],
|
||||
["junctions-selected", "circle-radius", DRAINAGE_LAYER_VISUALS.junctions.selectedRadius],
|
||||
["orifices", "line-width", DRAINAGE_LAYER_VISUALS.orifices.width],
|
||||
["orifices-selected", "line-width", DRAINAGE_LAYER_VISUALS.orifices.selectedWidth],
|
||||
["orifices-selected-outline", "line-width", DRAINAGE_LAYER_VISUALS.orifices.selectedBorderWidth],
|
||||
["pumps", "line-width", DRAINAGE_LAYER_VISUALS.pumps.width],
|
||||
["pumps-selected", "line-width", DRAINAGE_LAYER_VISUALS.pumps.selectedWidth],
|
||||
["pumps-selected-outline", "line-width", DRAINAGE_LAYER_VISUALS.pumps.selectedBorderWidth],
|
||||
["outfalls", "circle-radius", DRAINAGE_LAYER_VISUALS.outfalls.radius],
|
||||
["outfalls-selected-halo", "circle-radius", DRAINAGE_LAYER_VISUALS.outfalls.selectedHaloRadius]
|
||||
["outfalls-selected", "circle-radius", DRAINAGE_LAYER_VISUALS.outfalls.selectedRadius]
|
||||
] as const;
|
||||
|
||||
expectedGeometry.forEach(([layerId, paintProperty, visualToken]) => {
|
||||
|
||||
Reference in New Issue
Block a user