feat: add dynamic entity color generation and support for reassigning geometry IDs
This commit is contained in:
@@ -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;
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user