init: replay mode
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
import maplibregl, { LayerSpecification } from "maplibre-gl";
|
||||
|
||||
const TYPE_MATCH_EXPR: maplibregl.ExpressionSpecification = ["coalesce", ["get", "type"], ["get", "entity_type_id"], ""];
|
||||
const DRAFT_ENTITY_EXPR: maplibregl.ExpressionSpecification = ["==", ["coalesce", ["get", "entity_id"], ""], ""];
|
||||
const SELECTED_EXPR: maplibregl.ExpressionSpecification = ["boolean", ["feature-state", "selected"], false];
|
||||
|
||||
const SELECTED_COLOR = "#22c55e";
|
||||
const SELECTED_STROKE = "#14532d";
|
||||
const DRAFT_COLOR = "#ef4444";
|
||||
const DRAFT_STROKE = "#7f1d1d";
|
||||
|
||||
type ZoomStops = {
|
||||
z1: number;
|
||||
z4: number;
|
||||
z6: number;
|
||||
};
|
||||
|
||||
type LineGeotypeStyle = {
|
||||
typeId: string;
|
||||
color: string;
|
||||
strokeColor?: string;
|
||||
opacity?: number;
|
||||
width?: ZoomStops;
|
||||
dasharray?: number[];
|
||||
arrow?: boolean;
|
||||
arrowOpacity?: number;
|
||||
arrowOutlineColor?: string;
|
||||
arrowOutlineWidth?: ZoomStops;
|
||||
};
|
||||
|
||||
type PolygonGeotypeStyle = {
|
||||
typeId: string;
|
||||
fillColor: string;
|
||||
strokeColor: string;
|
||||
fillOpacity: number;
|
||||
strokeWidth?: ZoomStops;
|
||||
dasharray?: number[];
|
||||
};
|
||||
|
||||
const DEFAULT_LINE_WIDTH: ZoomStops = { z1: 2.2, z4: 3.2, z6: 4.2 };
|
||||
const DEFAULT_ARROW_OUTLINE_WIDTH: ZoomStops = { z1: 0.45, z4: 0.8, z6: 1.2 };
|
||||
const DEFAULT_POLYGON_STROKE_WIDTH: ZoomStops = { z1: 1.4, z4: 2, z6: 2.8 };
|
||||
const LINE_GEOMETRY_FILTER: maplibregl.ExpressionSpecification = [
|
||||
"any",
|
||||
["==", ["geometry-type"], "LineString"],
|
||||
["==", ["geometry-type"], "MultiLineString"],
|
||||
];
|
||||
const POLYGON_GEOMETRY_FILTER: maplibregl.ExpressionSpecification = [
|
||||
"any",
|
||||
["==", ["geometry-type"], "Polygon"],
|
||||
["==", ["geometry-type"], "MultiPolygon"],
|
||||
];
|
||||
|
||||
export function buildLineGeotypeLayers(
|
||||
sourceId: string,
|
||||
pathArrowSourceId: string | undefined,
|
||||
style: LineGeotypeStyle
|
||||
): LayerSpecification[] {
|
||||
const lineLayer: LayerSpecification = {
|
||||
id: `${style.typeId}-line`,
|
||||
type: "line",
|
||||
source: sourceId,
|
||||
filter: lineFilter(style.typeId),
|
||||
layout: {
|
||||
"line-cap": "round",
|
||||
"line-join": "round",
|
||||
},
|
||||
paint: {
|
||||
"line-color": statusColor(style.color),
|
||||
"line-width": widthStops(style.width ?? DEFAULT_LINE_WIDTH),
|
||||
"line-opacity": style.opacity ?? 0.9,
|
||||
...(style.dasharray ? { "line-dasharray": style.dasharray } : {}),
|
||||
},
|
||||
};
|
||||
|
||||
const hitLayer: LayerSpecification = {
|
||||
id: `${style.typeId}-hit`,
|
||||
type: "line",
|
||||
source: sourceId,
|
||||
filter: lineFilter(style.typeId),
|
||||
layout: {
|
||||
"line-cap": "round",
|
||||
"line-join": "round",
|
||||
},
|
||||
paint: {
|
||||
"line-color": "#ffffff",
|
||||
"line-width": widthStops({ z1: 12, z4: 18, z6: 24 }),
|
||||
"line-opacity": 0,
|
||||
},
|
||||
};
|
||||
|
||||
if (style.arrow === false || !pathArrowSourceId) {
|
||||
return [lineLayer, hitLayer];
|
||||
}
|
||||
|
||||
return [
|
||||
lineLayer,
|
||||
hitLayer,
|
||||
{
|
||||
id: `${style.typeId}-path-arrow-fill`,
|
||||
type: "fill",
|
||||
source: pathArrowSourceId,
|
||||
filter: ["==", TYPE_MATCH_EXPR, style.typeId],
|
||||
paint: {
|
||||
"fill-color": statusColor(style.color),
|
||||
"fill-opacity": [
|
||||
"case",
|
||||
SELECTED_EXPR,
|
||||
0.92,
|
||||
style.arrowOpacity ?? 0.82,
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: `${style.typeId}-path-arrow-line`,
|
||||
type: "line",
|
||||
source: pathArrowSourceId,
|
||||
filter: ["==", TYPE_MATCH_EXPR, style.typeId],
|
||||
layout: {
|
||||
"line-cap": "round",
|
||||
"line-join": "round",
|
||||
},
|
||||
paint: {
|
||||
"line-color": statusStroke(style.arrowOutlineColor ?? style.strokeColor ?? "#0f172a"),
|
||||
"line-width": widthStops(style.arrowOutlineWidth ?? DEFAULT_ARROW_OUTLINE_WIDTH),
|
||||
"line-opacity": 0.9,
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function buildPolygonGeotypeLayers(
|
||||
sourceId: string,
|
||||
style: PolygonGeotypeStyle
|
||||
): LayerSpecification[] {
|
||||
return [
|
||||
{
|
||||
id: `${style.typeId}-fill`,
|
||||
type: "fill",
|
||||
source: sourceId,
|
||||
filter: polygonFilter(style.typeId),
|
||||
paint: {
|
||||
"fill-color": statusColor(style.fillColor),
|
||||
"fill-opacity": [
|
||||
"case",
|
||||
SELECTED_EXPR,
|
||||
0.58,
|
||||
style.fillOpacity,
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: `${style.typeId}-line`,
|
||||
type: "line",
|
||||
source: sourceId,
|
||||
filter: polygonFilter(style.typeId),
|
||||
layout: {
|
||||
"line-cap": "round",
|
||||
"line-join": "round",
|
||||
},
|
||||
paint: {
|
||||
"line-color": statusStroke(style.strokeColor),
|
||||
"line-width": widthStops(style.strokeWidth ?? DEFAULT_POLYGON_STROKE_WIDTH),
|
||||
"line-opacity": 0.95,
|
||||
...(style.dasharray ? { "line-dasharray": style.dasharray } : {}),
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function statusColor(normalColor: string): maplibregl.ExpressionSpecification {
|
||||
return [
|
||||
"case",
|
||||
SELECTED_EXPR,
|
||||
SELECTED_COLOR,
|
||||
DRAFT_ENTITY_EXPR,
|
||||
DRAFT_COLOR,
|
||||
normalColor,
|
||||
];
|
||||
}
|
||||
|
||||
function statusStroke(normalColor: string): maplibregl.ExpressionSpecification {
|
||||
return [
|
||||
"case",
|
||||
SELECTED_EXPR,
|
||||
SELECTED_STROKE,
|
||||
DRAFT_ENTITY_EXPR,
|
||||
DRAFT_STROKE,
|
||||
normalColor,
|
||||
];
|
||||
}
|
||||
|
||||
function lineFilter(typeId: string): maplibregl.ExpressionSpecification {
|
||||
return ["all", LINE_GEOMETRY_FILTER, ["==", TYPE_MATCH_EXPR, typeId]];
|
||||
}
|
||||
|
||||
function polygonFilter(typeId: string): maplibregl.ExpressionSpecification {
|
||||
return ["all", POLYGON_GEOMETRY_FILTER, ["==", TYPE_MATCH_EXPR, typeId]];
|
||||
}
|
||||
|
||||
function widthStops(stops: ZoomStops): maplibregl.ExpressionSpecification {
|
||||
return ["interpolate", ["linear"], ["zoom"], 1, stops.z1, 4, stops.z4, 6, stops.z6];
|
||||
}
|
||||
Reference in New Issue
Block a user