feat: add dynamic entity color generation and support for reassigning geometry IDs

This commit is contained in:
taDuc
2026-05-24 11:57:40 +07:00
parent 23b2c6f534
commit 0ebf8e1c65
10 changed files with 437 additions and 67 deletions
+53
View File
@@ -940,3 +940,56 @@ export function clampNumber(value: number, min: number, max: number): number {
if (value > max) return max;
return value;
}
export function hashStringToColor(str: string): string {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
const hue = Math.abs(hash) % 360;
return `hsl(${hue}, 70%, 50%)`;
}
export function decorateFeaturesWithEntityColors(fc: FeatureCollection): FeatureCollection {
return {
...fc,
features: fc.features.map((feature) => {
const geomType = feature.geometry?.type;
if (geomType === "Point" || geomType === "MultiPoint") {
// Point - giữ nguyên màu của preset/icon
return feature;
}
if (geomType === "LineString" || geomType === "MultiLineString") {
const entityIds = getFeatureEntityIds(feature);
if (entityIds.length > 0) {
const sortedCombined = [...entityIds].sort().join("+");
return {
...feature,
properties: {
...feature.properties,
entity_color: hashStringToColor(sortedCombined),
},
};
}
return feature;
}
if (geomType === "Polygon" || geomType === "MultiPolygon") {
const geoId = String(feature.properties?.id || "");
if (geoId) {
return {
...feature,
properties: {
...feature.properties,
entity_color: hashStringToColor(geoId),
},
};
}
return feature;
}
return feature;
}),
};
}
+3 -1
View File
@@ -15,6 +15,7 @@ import {
fitMapToFeatureCollection,
setSelectedFeatureState,
splitDraftFeatures,
decorateFeaturesWithEntityColors,
} from "./mapUtils";
import { applyImageOverlay, type MapImageOverlay } from "./imageOverlay";
@@ -128,7 +129,8 @@ export function useMapSync({
const bindingFilteredRenderDraft = applyGeometryBindingFilterRef.current
? filterDraftByBinding(renderFc, currentSelectedIds, highlightFeaturesVal)
: renderFc;
const mapSourceDraft = filterDraftByGeometryVisibility(bindingFilteredRenderDraft, geometryVisibilityRef.current);
const visibilityFilteredDraft = filterDraftByGeometryVisibility(bindingFilteredRenderDraft, geometryVisibilityRef.current);
const mapSourceDraft = decorateFeaturesWithEntityColors(visibilityFilteredDraft);
const labelTimelineYear = labelTimelineYearRef.current;
const { polygons, points } = splitDraftFeatures(mapSourceDraft);
const labeledGeometries = decorateLineFeaturesWithLabels(polygons, labelContext, labelTimelineYear);