feat(map): refine sector inspector styling
This commit is contained in:
@@ -316,6 +316,11 @@ export type GridLodProfile = {
|
||||
volumeMinimumHeightMeters: number;
|
||||
volumeMaximumHeightMeters: number;
|
||||
volumeBandHeightMeters: number;
|
||||
selectionFillColor: string;
|
||||
selectionFillOpacityPercent: number;
|
||||
selectionOutlineColor: string;
|
||||
selectionOutlineWidthPx: number;
|
||||
selectionOutlineOpacityPercent: number;
|
||||
};
|
||||
|
||||
export type GridVolumeSelection = {
|
||||
@@ -1006,6 +1011,11 @@ type LocalGridAddressing = {
|
||||
volumeMinimumHeightMeters: number;
|
||||
volumeMaximumHeightMeters: number;
|
||||
volumeBandHeightMeters: number;
|
||||
selectionFillColor: string;
|
||||
selectionFillOpacityPercent: number;
|
||||
selectionOutlineColor: string;
|
||||
selectionOutlineWidthPx: number;
|
||||
selectionOutlineOpacityPercent: number;
|
||||
};
|
||||
type GraticuleGridAddressing = {
|
||||
mode: "graticule";
|
||||
@@ -1017,6 +1027,11 @@ type GraticuleGridAddressing = {
|
||||
lineColor: string;
|
||||
lineOpacity: number;
|
||||
majorLineWidthMultiplier: number;
|
||||
selectionFillColor: string;
|
||||
selectionFillOpacityPercent: number;
|
||||
selectionOutlineColor: string;
|
||||
selectionOutlineWidthPx: number;
|
||||
selectionOutlineOpacityPercent: number;
|
||||
};
|
||||
type GridAddressing = LocalGridAddressing | GraticuleGridAddressing;
|
||||
type GridResources = {
|
||||
@@ -1525,7 +1540,56 @@ function materializeGridLayer(plan: Exclude<GridLayerPlan, HiddenGridPlan>, seri
|
||||
return plan.mode === "3d" ? materializeLocalGrid(plan, serial) : materializeGraticule(plan, serial);
|
||||
}
|
||||
|
||||
const GRID_SELECTION_COLOR = Color.fromCssColorString("#35CFFF");
|
||||
const DEFAULT_GRID_SELECTION_COLOR = "#35cfff";
|
||||
|
||||
type GridSelectionStyle = {
|
||||
fillColor: Color;
|
||||
outlineColor: Color;
|
||||
outlineWidthPixels: number;
|
||||
};
|
||||
|
||||
function safeGridSelectionColor(value: unknown) {
|
||||
if (typeof value === "string" && value.trim()) {
|
||||
try {
|
||||
const parsed = Color.fromCssColorString(value.trim());
|
||||
if (parsed) return parsed;
|
||||
} catch {
|
||||
// Persisted profiles may predate strict colour validation. Rendering a
|
||||
// stable selection is preferable to failing the whole Cesium layer.
|
||||
}
|
||||
}
|
||||
return Color.fromCssColorString(DEFAULT_GRID_SELECTION_COLOR);
|
||||
}
|
||||
|
||||
function safeGridSelectionPercent(value: unknown, fallback: number) {
|
||||
const candidate = typeof value === "number" ? value : Number.NaN;
|
||||
return clamp(Number.isFinite(candidate) ? candidate : fallback, 0, 100) / 100;
|
||||
}
|
||||
|
||||
function resolveGridSelectionStyle(addressing: GridAddressing): GridSelectionStyle {
|
||||
const fallbackOutlineWidth = addressing.mode === "3d"
|
||||
? clamp(2.5 * addressing.majorLineWidthMultiplier, 3, 12)
|
||||
: clamp(addressing.lineWidthPixels * addressing.majorLineWidthMultiplier * 1.5, 3, 12);
|
||||
const requestedOutlineWidth = typeof addressing.selectionOutlineWidthPx === "number"
|
||||
? addressing.selectionOutlineWidthPx
|
||||
: Number.NaN;
|
||||
const fallbackFillOpacityPercent = addressing.mode === "graticule"
|
||||
? 12
|
||||
: addressing.volumeEnabled ? 10 : 16;
|
||||
return {
|
||||
fillColor: safeGridSelectionColor(addressing.selectionFillColor).withAlpha(
|
||||
safeGridSelectionPercent(addressing.selectionFillOpacityPercent, fallbackFillOpacityPercent),
|
||||
),
|
||||
outlineColor: safeGridSelectionColor(addressing.selectionOutlineColor).withAlpha(
|
||||
safeGridSelectionPercent(addressing.selectionOutlineOpacityPercent, 95),
|
||||
),
|
||||
outlineWidthPixels: clamp(
|
||||
Number.isFinite(requestedOutlineWidth) ? requestedOutlineWidth : fallbackOutlineWidth,
|
||||
1,
|
||||
12,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function sampledRange(start: number, end: number, maximumStep: number) {
|
||||
const span = end - start;
|
||||
@@ -1562,6 +1626,7 @@ function materializeLocalSelection(
|
||||
|
||||
const dataSource = new CustomDataSource(`nodedc-map-grid-selection-local:${serial}`);
|
||||
const crosses = new PolylineCollection();
|
||||
const selectionStyle = resolveGridSelectionStyle(addressing);
|
||||
const volumeAvailable = addressing.volumeEnabled
|
||||
&& Number.isFinite(addressing.volumeBandHeightMeters)
|
||||
&& addressing.volumeBandHeightMeters > 0
|
||||
@@ -1582,9 +1647,9 @@ function materializeLocalSelection(
|
||||
const polyline = crosses.add({
|
||||
id: { kind: "nodedc-grid-selection", sectorId: selection.id, edgeId: id },
|
||||
positions,
|
||||
width: clamp(2.5 * addressing.majorLineWidthMultiplier, 3, 12),
|
||||
width: selectionStyle.outlineWidthPixels,
|
||||
});
|
||||
if (polyline.material?.uniforms) polyline.material.uniforms.color = GRID_SELECTION_COLOR.withAlpha(0.95);
|
||||
if (polyline.material?.uniforms) polyline.material.uniforms.color = selectionStyle.outlineColor;
|
||||
};
|
||||
addLine("floor", floorPerimeter);
|
||||
if (ceiling > floor + 1e-6) addLine("ceiling", ceilingPerimeter);
|
||||
@@ -1608,7 +1673,7 @@ function materializeLocalSelection(
|
||||
polygon: {
|
||||
hierarchy: new PolygonHierarchy(ceilingSurface),
|
||||
perPositionHeight: true,
|
||||
material: GRID_SELECTION_COLOR.withAlpha(volumeAvailable ? 0.1 : 0.16),
|
||||
material: selectionStyle.fillColor,
|
||||
outline: false,
|
||||
},
|
||||
});
|
||||
@@ -1621,6 +1686,7 @@ function materializeGraticuleSelection(
|
||||
serial: number,
|
||||
): GridResources {
|
||||
const dataSource = new CustomDataSource(`nodedc-map-grid-selection-graticule:${serial}`);
|
||||
const selectionStyle = resolveGridSelectionStyle(addressing);
|
||||
const height = Math.max(0, addressing.heightMeters);
|
||||
const horizontalStep = Math.min(10, Math.max(0.5, addressing.stepDegrees));
|
||||
const verticalStep = Math.min(10, Math.max(0.5, addressing.stepDegrees));
|
||||
@@ -1643,8 +1709,8 @@ function materializeGraticuleSelection(
|
||||
id: `${selection.id}/selection-surface`,
|
||||
polyline: {
|
||||
positions: perimeter,
|
||||
width: clamp(addressing.lineWidthPixels * addressing.majorLineWidthMultiplier * 1.5, 3, 12),
|
||||
material: GRID_SELECTION_COLOR.withAlpha(0.95),
|
||||
width: selectionStyle.outlineWidthPixels,
|
||||
material: selectionStyle.outlineColor,
|
||||
clampToGround,
|
||||
arcType: ArcType.RHUMB,
|
||||
granularity: graticuleGranularity(horizontalStep, clampToGround),
|
||||
@@ -1654,7 +1720,7 @@ function materializeGraticuleSelection(
|
||||
height: clampToGround ? undefined : height,
|
||||
heightReference: clampToGround ? HeightReference.CLAMP_TO_GROUND : HeightReference.NONE,
|
||||
arcType: ArcType.RHUMB,
|
||||
material: GRID_SELECTION_COLOR.withAlpha(0.12),
|
||||
material: selectionStyle.fillColor,
|
||||
outline: false,
|
||||
},
|
||||
});
|
||||
@@ -1712,12 +1778,38 @@ class GridLayerController {
|
||||
: JSON.stringify([addressing.mode, addressing.lod, addressing.stepDegrees, addressing.majorStepDegrees]);
|
||||
}
|
||||
|
||||
private syncSelectionStyle(plan: Exclude<GridLayerPlan, HiddenGridPlan>) {
|
||||
let changed = false;
|
||||
const targetLod = plan.lod.index + 1;
|
||||
for (const layer of [this.current, this.pending]) {
|
||||
const addressing = layer?.addressing;
|
||||
if (!addressing || addressing.mode !== plan.mode || addressing.lod !== targetLod) continue;
|
||||
if (
|
||||
addressing.selectionFillColor === plan.lod.selectionFillColor
|
||||
&& addressing.selectionFillOpacityPercent === plan.lod.selectionFillOpacityPercent
|
||||
&& addressing.selectionOutlineColor === plan.lod.selectionOutlineColor
|
||||
&& addressing.selectionOutlineWidthPx === plan.lod.selectionOutlineWidthPx
|
||||
&& addressing.selectionOutlineOpacityPercent === plan.lod.selectionOutlineOpacityPercent
|
||||
) continue;
|
||||
addressing.selectionFillColor = plan.lod.selectionFillColor;
|
||||
addressing.selectionFillOpacityPercent = plan.lod.selectionFillOpacityPercent;
|
||||
addressing.selectionOutlineColor = plan.lod.selectionOutlineColor;
|
||||
addressing.selectionOutlineWidthPx = plan.lod.selectionOutlineWidthPx;
|
||||
addressing.selectionOutlineOpacityPercent = plan.lod.selectionOutlineOpacityPercent;
|
||||
changed = true;
|
||||
}
|
||||
if (changed) this.refreshSelection(this.pending?.addressing ?? this.current?.addressing);
|
||||
}
|
||||
|
||||
rebuild(presentation: MapPresentation) {
|
||||
// Planning is intentionally cheap. Geometry is materialized only after
|
||||
// key comparison; repeated camera/settings notifications cannot create
|
||||
// and discard thousands of Cesium objects for an unchanged layer.
|
||||
const plan = planGridLayer(this.viewer, presentation, this.lodIndex);
|
||||
if (plan.key === this.key) return;
|
||||
if (plan.key === this.key) {
|
||||
if (plan.mode !== "hidden") this.syncSelectionStyle(plan);
|
||||
return;
|
||||
}
|
||||
this.key = plan.key;
|
||||
this.lodIndex = plan.lodIndex;
|
||||
const epoch = ++this.epoch;
|
||||
@@ -1751,6 +1843,11 @@ class GridLayerController {
|
||||
volumeMinimumHeightMeters: plan.lod.volumeMinimumHeightMeters,
|
||||
volumeMaximumHeightMeters: plan.lod.volumeMaximumHeightMeters,
|
||||
volumeBandHeightMeters: plan.lod.volumeBandHeightMeters,
|
||||
selectionFillColor: plan.lod.selectionFillColor,
|
||||
selectionFillOpacityPercent: plan.lod.selectionFillOpacityPercent,
|
||||
selectionOutlineColor: plan.lod.selectionOutlineColor,
|
||||
selectionOutlineWidthPx: plan.lod.selectionOutlineWidthPx,
|
||||
selectionOutlineOpacityPercent: plan.lod.selectionOutlineOpacityPercent,
|
||||
} : {
|
||||
mode: "graticule",
|
||||
lod: plan.lod.index + 1,
|
||||
@@ -1761,6 +1858,11 @@ class GridLayerController {
|
||||
lineColor: plan.lod.graticuleColor,
|
||||
lineOpacity: plan.lod.graticuleOpacity,
|
||||
majorLineWidthMultiplier: plan.lod.majorLineWidthMultiplier,
|
||||
selectionFillColor: plan.lod.selectionFillColor,
|
||||
selectionFillOpacityPercent: plan.lod.selectionFillOpacityPercent,
|
||||
selectionOutlineColor: plan.lod.selectionOutlineColor,
|
||||
selectionOutlineWidthPx: plan.lod.selectionOutlineWidthPx,
|
||||
selectionOutlineOpacityPercent: plan.lod.selectionOutlineOpacityPercent,
|
||||
};
|
||||
const activeAddressing = this.pending?.addressing ?? this.current?.addressing;
|
||||
if (activeAddressing && this.addressingKey(activeAddressing) !== this.addressingKey(addressing)) {
|
||||
@@ -1943,6 +2045,11 @@ class GridLayerController {
|
||||
addressing.lineColor,
|
||||
addressing.lineOpacity,
|
||||
addressing.majorLineWidthMultiplier,
|
||||
addressing.selectionFillColor,
|
||||
addressing.selectionFillOpacityPercent,
|
||||
addressing.selectionOutlineColor,
|
||||
addressing.selectionOutlineWidthPx,
|
||||
addressing.selectionOutlineOpacityPercent,
|
||||
addressing.mode === "3d" ? [
|
||||
addressing.volumeEnabled,
|
||||
addressing.volumeMinimumHeightMeters,
|
||||
|
||||
@@ -75,6 +75,11 @@ type SectorGridLodProfile = GridLodProfile & {
|
||||
majorLinesEnabled: boolean;
|
||||
majorLabelsEnabled: boolean;
|
||||
majorLineWidthMultiplier: number;
|
||||
selectionFillColor: string;
|
||||
selectionFillOpacityPercent: number;
|
||||
selectionOutlineColor: string;
|
||||
selectionOutlineWidthPx: number;
|
||||
selectionOutlineOpacityPercent: number;
|
||||
volumeEnabled: boolean;
|
||||
volumeMinimumHeightMeters: number;
|
||||
volumeMaximumHeightMeters: number;
|
||||
@@ -981,12 +986,22 @@ export const MapFixturePreview = forwardRef<MapFixturePreviewHandle, {
|
||||
const updateGridVolumeRange = (patch: Partial<Pick<SectorGridLodProfile,
|
||||
"volumeMinimumHeightMeters" | "volumeMaximumHeightMeters" | "volumeBandHeightMeters">>) => {
|
||||
const minimum = patch.volumeMinimumHeightMeters ?? activeGridLod.volumeMinimumHeightMeters;
|
||||
const maximum = Math.max(minimum + 1, patch.volumeMaximumHeightMeters ?? activeGridLod.volumeMaximumHeightMeters);
|
||||
const requestedBandHeight = Math.min(
|
||||
1_000,
|
||||
Math.max(1, patch.volumeBandHeightMeters ?? activeGridLod.volumeBandHeightMeters),
|
||||
);
|
||||
let maximum = Math.min(
|
||||
10_000,
|
||||
Math.max(minimum + 1, patch.volumeMaximumHeightMeters ?? activeGridLod.volumeMaximumHeightMeters),
|
||||
);
|
||||
if (patch.volumeBandHeightMeters !== undefined) {
|
||||
maximum = Math.min(10_000, Math.max(maximum, minimum + requestedBandHeight));
|
||||
}
|
||||
const span = maximum - minimum;
|
||||
updateGridLod({
|
||||
volumeMinimumHeightMeters: minimum,
|
||||
volumeMaximumHeightMeters: maximum,
|
||||
volumeBandHeightMeters: Math.min(span, Math.max(1, patch.volumeBandHeightMeters ?? activeGridLod.volumeBandHeightMeters)),
|
||||
volumeBandHeightMeters: Math.min(span, requestedBandHeight),
|
||||
});
|
||||
};
|
||||
const setCacheEnabled = (cacheEnabled: boolean) => {
|
||||
@@ -1632,7 +1647,7 @@ export const MapFixturePreview = forwardRef<MapFixturePreviewHandle, {
|
||||
label: "Сетка и LOD",
|
||||
description: "first adapter control",
|
||||
group: "Слои",
|
||||
content: <>
|
||||
content: <div className="catalog-map-grid-inspector">
|
||||
<small className="catalog-map-inspector__note">Фиксированная московская ENU-адресация задаёт неизменные сектора на LOD 1–3. LOD 4–5 используют глобальную WGS84-гратику́лу; камера выбирает только LOD и видимую область.</small>
|
||||
<Checker checked={mapSettings.gridVisible} label="Сетка" onChange={(gridVisible) => updateMapSettings({ gridVisible })} />
|
||||
<Checker checked={mapSettings.grid3dEnabled} label="3D-сетка" onChange={(grid3dEnabled) => updateMapSettings({ grid3dEnabled })} />
|
||||
@@ -1743,13 +1758,55 @@ export const MapFixturePreview = forwardRef<MapFixturePreviewHandle, {
|
||||
label="Высота адресного диапазона"
|
||||
value={activeGridLod.volumeBandHeightMeters}
|
||||
min={1}
|
||||
max={Math.max(1, activeGridLod.volumeMaximumHeightMeters - activeGridLod.volumeMinimumHeightMeters)}
|
||||
max={1_000}
|
||||
step={10}
|
||||
formatValue={(value) => `${value} м`}
|
||||
onChange={(volumeBandHeightMeters) => updateGridVolumeRange({ volumeBandHeightMeters })}
|
||||
/>
|
||||
<small className="catalog-map-inspector__note">Горизонтальный ID сектора остаётся стабильным. Высотный band добавляется как отдельный адрес внутри выбранной ENU-ячейки.</small>
|
||||
</> : null}
|
||||
<ControlRow label="Цвет заливки сектора">
|
||||
<ColorField
|
||||
label="Цвет заливки выбранного сектора"
|
||||
value={activeGridLod.selectionFillColor}
|
||||
onChange={(selectionFillColor) => updateGridLod({ selectionFillColor })}
|
||||
/>
|
||||
</ControlRow>
|
||||
<RangeControl
|
||||
label="Прозрачность заливки"
|
||||
value={activeGridLod.selectionFillOpacityPercent}
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
formatValue={(value) => `${value}%`}
|
||||
onChange={(selectionFillOpacityPercent) => updateGridLod({ selectionFillOpacityPercent })}
|
||||
/>
|
||||
<ControlRow label="Цвет линии сектора">
|
||||
<ColorField
|
||||
label="Цвет линии выбранного сектора"
|
||||
value={activeGridLod.selectionOutlineColor}
|
||||
onChange={(selectionOutlineColor) => updateGridLod({ selectionOutlineColor })}
|
||||
/>
|
||||
</ControlRow>
|
||||
<RangeControl
|
||||
label="Толщина линии"
|
||||
value={activeGridLod.selectionOutlineWidthPx}
|
||||
min={1}
|
||||
max={12}
|
||||
step={0.25}
|
||||
formatValue={(value) => `${value} px`}
|
||||
onChange={(selectionOutlineWidthPx) => updateGridLod({ selectionOutlineWidthPx })}
|
||||
/>
|
||||
<RangeControl
|
||||
label="Прозрачность линии"
|
||||
value={activeGridLod.selectionOutlineOpacityPercent}
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
formatValue={(value) => `${value}%`}
|
||||
onChange={(selectionOutlineOpacityPercent) => updateGridLod({ selectionOutlineOpacityPercent })}
|
||||
/>
|
||||
<small className="catalog-map-inspector__note">Оформление применяется к выбранному сектору текущего LOD.</small>
|
||||
<section className="catalog-map-grid-sector" aria-label="Выбранный сектор">
|
||||
<ControlRow label="Выбранный сектор"><strong className="catalog-map-grid-sector-id">{selectedGridSector?.id ?? "Нажмите сектор на карте"}</strong></ControlRow>
|
||||
{selectedGridSector ? <>
|
||||
@@ -1841,7 +1898,7 @@ export const MapFixturePreview = forwardRef<MapFixturePreviewHandle, {
|
||||
</div> : null}
|
||||
</> : <small className="catalog-map-inspector__note">Кликните ячейку, чтобы получить устойчивый адрес, геометрию и навигацию по соседям.</small>}
|
||||
</section>
|
||||
</>,
|
||||
</div>,
|
||||
},
|
||||
{
|
||||
id: "map-camera-animation",
|
||||
|
||||
@@ -32,6 +32,11 @@ export type GridLodProfile = {
|
||||
volumeMinimumHeightMeters: number;
|
||||
volumeMaximumHeightMeters: number;
|
||||
volumeBandHeightMeters: number;
|
||||
selectionFillColor: string;
|
||||
selectionFillOpacityPercent: number;
|
||||
selectionOutlineColor: string;
|
||||
selectionOutlineWidthPx: number;
|
||||
selectionOutlineOpacityPercent: number;
|
||||
};
|
||||
export type GridLodBand = GridLodProfile & {
|
||||
index: number;
|
||||
|
||||
@@ -18,6 +18,8 @@ export const DEFAULT_GRID_LOD_PROFILES = Object.freeze([
|
||||
graticuleStepDegrees: 0.25, graticuleLineWidthPx: 1, graticuleColor: "#f5f5f5", graticuleOpacity: 12,
|
||||
majorLinesEnabled: true, majorLabelsEnabled: true, majorLineWidthMultiplier: 2.5,
|
||||
volumeEnabled: true, volumeMinimumHeightMeters: 0, volumeMaximumHeightMeters: 300, volumeBandHeightMeters: 300,
|
||||
selectionFillColor: "#35cfff", selectionFillOpacityPercent: 10,
|
||||
selectionOutlineColor: "#35cfff", selectionOutlineWidthPx: 6.25, selectionOutlineOpacityPercent: 95,
|
||||
}),
|
||||
Object.freeze({
|
||||
maxHeightKm: 50, stepKm: 5, mode: "3d", heightMeters: 500, max3dViewAngleDegrees: 30,
|
||||
@@ -27,6 +29,8 @@ export const DEFAULT_GRID_LOD_PROFILES = Object.freeze([
|
||||
graticuleStepDegrees: 0.5, graticuleLineWidthPx: 1, graticuleColor: "#f8fbfc", graticuleOpacity: 12,
|
||||
majorLinesEnabled: true, majorLabelsEnabled: true, majorLineWidthMultiplier: 2.5,
|
||||
volumeEnabled: true, volumeMinimumHeightMeters: 0, volumeMaximumHeightMeters: 500, volumeBandHeightMeters: 500,
|
||||
selectionFillColor: "#35cfff", selectionFillOpacityPercent: 10,
|
||||
selectionOutlineColor: "#35cfff", selectionOutlineWidthPx: 6.25, selectionOutlineOpacityPercent: 95,
|
||||
}),
|
||||
Object.freeze({
|
||||
maxHeightKm: 200, stepKm: 25, mode: "3d", heightMeters: 500, max3dViewAngleDegrees: 30,
|
||||
@@ -36,6 +40,8 @@ export const DEFAULT_GRID_LOD_PROFILES = Object.freeze([
|
||||
graticuleStepDegrees: 1, graticuleLineWidthPx: 1, graticuleColor: "#fafafa", graticuleOpacity: 12,
|
||||
majorLinesEnabled: true, majorLabelsEnabled: false, majorLineWidthMultiplier: 2,
|
||||
volumeEnabled: false, volumeMinimumHeightMeters: 0, volumeMaximumHeightMeters: 500, volumeBandHeightMeters: 500,
|
||||
selectionFillColor: "#35cfff", selectionFillOpacityPercent: 16,
|
||||
selectionOutlineColor: "#35cfff", selectionOutlineWidthPx: 5, selectionOutlineOpacityPercent: 95,
|
||||
}),
|
||||
Object.freeze({
|
||||
maxHeightKm: 800, stepKm: 50, mode: "graticule", heightMeters: 500, max3dViewAngleDegrees: 30,
|
||||
@@ -45,6 +51,8 @@ export const DEFAULT_GRID_LOD_PROFILES = Object.freeze([
|
||||
graticuleStepDegrees: 2, graticuleLineWidthPx: 1, graticuleColor: "#fcfdfd", graticuleOpacity: 12,
|
||||
majorLinesEnabled: true, majorLabelsEnabled: false, majorLineWidthMultiplier: 2,
|
||||
volumeEnabled: false, volumeMinimumHeightMeters: 0, volumeMaximumHeightMeters: 500, volumeBandHeightMeters: 500,
|
||||
selectionFillColor: "#35cfff", selectionFillOpacityPercent: 12,
|
||||
selectionOutlineColor: "#35cfff", selectionOutlineWidthPx: 3, selectionOutlineOpacityPercent: 95,
|
||||
}),
|
||||
Object.freeze({
|
||||
// Engine keeps the last LOD selected above this threshold; the independent
|
||||
@@ -56,6 +64,8 @@ export const DEFAULT_GRID_LOD_PROFILES = Object.freeze([
|
||||
graticuleStepDegrees: 2, graticuleLineWidthPx: 1, graticuleColor: "#9c9c9c", graticuleOpacity: 8,
|
||||
majorLinesEnabled: true, majorLabelsEnabled: false, majorLineWidthMultiplier: 2,
|
||||
volumeEnabled: false, volumeMinimumHeightMeters: 0, volumeMaximumHeightMeters: 500, volumeBandHeightMeters: 500,
|
||||
selectionFillColor: "#35cfff", selectionFillOpacityPercent: 12,
|
||||
selectionOutlineColor: "#35cfff", selectionOutlineWidthPx: 3, selectionOutlineOpacityPercent: 95,
|
||||
}),
|
||||
]);
|
||||
|
||||
@@ -98,6 +108,11 @@ export function gridLodProfile(settings, index) {
|
||||
volumeMinimumHeightMeters: clamp(finite(source.volumeMinimumHeightMeters, fallback.volumeMinimumHeightMeters), -1_000, 10_000),
|
||||
volumeMaximumHeightMeters: clamp(finite(source.volumeMaximumHeightMeters, fallback.volumeMaximumHeightMeters), -1_000, 10_000),
|
||||
volumeBandHeightMeters: clamp(finite(source.volumeBandHeightMeters, fallback.volumeBandHeightMeters), 1, 10_000),
|
||||
selectionFillColor: color(source.selectionFillColor, fallback.selectionFillColor),
|
||||
selectionFillOpacityPercent: clamp(finite(source.selectionFillOpacityPercent, fallback.selectionFillOpacityPercent), 0, 100),
|
||||
selectionOutlineColor: color(source.selectionOutlineColor, fallback.selectionOutlineColor),
|
||||
selectionOutlineWidthPx: clamp(finite(source.selectionOutlineWidthPx, fallback.selectionOutlineWidthPx), 1, 12),
|
||||
selectionOutlineOpacityPercent: clamp(finite(source.selectionOutlineOpacityPercent, fallback.selectionOutlineOpacityPercent), 0, 100),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+109
-2
@@ -958,6 +958,63 @@ textarea {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.catalog-map-grid-inspector {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
gap: var(--nodedc-space-3);
|
||||
font-family: var(--nodedc-font-family);
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
}
|
||||
|
||||
.catalog-map-grid-inspector :where(*) {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
font-family: var(--nodedc-font-family);
|
||||
}
|
||||
|
||||
.catalog-map-grid-inspector :where(
|
||||
.nodedc-checker__label,
|
||||
.nodedc-range__label,
|
||||
.nodedc-range__value,
|
||||
.nodedc-range__editor,
|
||||
.nodedc-select__value,
|
||||
.nodedc-select-trigger__label,
|
||||
.nodedc-control-row__label,
|
||||
.nodedc-control-row__control,
|
||||
.catalog-map-inspector__note,
|
||||
.nodedc-segmented__item,
|
||||
.nodedc-color-field__text,
|
||||
small,
|
||||
span,
|
||||
strong,
|
||||
code
|
||||
),
|
||||
.catalog-map-grid-inspector .nodedc-button {
|
||||
font-family: var(--nodedc-font-family);
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
}
|
||||
|
||||
.catalog-map-grid-inspector .nodedc-checker__label {
|
||||
overflow-wrap: anywhere;
|
||||
text-overflow: clip;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.catalog-map-grid-inspector :where(
|
||||
.nodedc-control-row__label,
|
||||
.nodedc-control-row__control,
|
||||
.catalog-map-inspector__note,
|
||||
small,
|
||||
span,
|
||||
strong,
|
||||
code,
|
||||
.nodedc-button
|
||||
) {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.catalog-map-grid-lod-tabs {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
@@ -973,22 +1030,70 @@ textarea {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
padding-inline: 0.45rem;
|
||||
font-size: var(--nodedc-font-size-xs);
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.catalog-map-grid-sector-id {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
text-align: right;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.catalog-map-grid-sector {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
gap: 0.55rem;
|
||||
border-top: 1px solid color-mix(in srgb, var(--nodedc-glass-outline) 44%, transparent);
|
||||
padding-top: 0.7rem;
|
||||
font-family: var(--nodedc-font-family);
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.catalog-map-grid-sector :where(*) {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
font-family: var(--nodedc-font-family);
|
||||
}
|
||||
|
||||
.catalog-map-grid-sector :where(
|
||||
.nodedc-control-row__label,
|
||||
.nodedc-control-row__control,
|
||||
small,
|
||||
span,
|
||||
strong,
|
||||
code
|
||||
),
|
||||
.catalog-map-grid-sector .nodedc-button {
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.catalog-map-grid-sector .nodedc-control-row {
|
||||
width: 100%;
|
||||
grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
|
||||
align-items: start;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.catalog-map-grid-sector :where(
|
||||
.nodedc-control-row__label,
|
||||
.nodedc-control-row__control,
|
||||
small,
|
||||
span,
|
||||
strong,
|
||||
code,
|
||||
.nodedc-button
|
||||
) {
|
||||
overflow-wrap: anywhere;
|
||||
word-break: normal;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.catalog-map-grid-sector__facts,
|
||||
@@ -1009,7 +1114,10 @@ textarea {
|
||||
.catalog-map-grid-sector__neighbor,
|
||||
.catalog-map-grid-sector__volume {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
gap: 0.4rem;
|
||||
border-radius: var(--nodedc-radius-control);
|
||||
background: var(--nodedc-glass-control-bg);
|
||||
@@ -1020,7 +1128,6 @@ textarea {
|
||||
.catalog-map-grid-sector__neighbor > code,
|
||||
.catalog-map-grid-sector__volume > code {
|
||||
color: var(--nodedc-text-muted);
|
||||
font-size: var(--nodedc-font-size-xs);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user