feat(network-map): add jitter-based label placement and clamp function for improved edge label positioning
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m20s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m20s
This commit is contained in:
@@ -119,6 +119,20 @@ function anchorPoint(pos, side, slotOffset = 0) {
|
|||||||
return { x: pos.x + slotOffset, y: pos.y - NODE_HEIGHT / 2 };
|
return { x: pos.x + slotOffset, y: pos.y - NODE_HEIGHT / 2 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clamp(val, min, max) {
|
||||||
|
return Math.max(min, Math.min(max, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
function hash01(str) {
|
||||||
|
let h = 2166136261;
|
||||||
|
const s = String(str || '');
|
||||||
|
for (let i = 0; i < s.length; i += 1) {
|
||||||
|
h ^= s.charCodeAt(i);
|
||||||
|
h = Math.imul(h, 16777619);
|
||||||
|
}
|
||||||
|
return (h >>> 0) / 4294967295;
|
||||||
|
}
|
||||||
|
|
||||||
export default function NetworkMapUnifi({
|
export default function NetworkMapUnifi({
|
||||||
servers = [],
|
servers = [],
|
||||||
connections = [],
|
connections = [],
|
||||||
@@ -442,15 +456,24 @@ export default function NetworkMapUnifi({
|
|||||||
return `M ${sx} ${sy} L ${sOutX} ${sOutY} Q ${cpx} ${cpy} ${eOutX} ${eOutY} L ${ex} ${ey}`;
|
return `M ${sx} ${sy} L ${sOutX} ${sOutY} Q ${cpx} ${cpy} ${eOutX} ${eOutY} L ${ex} ${ey}`;
|
||||||
}, [computeCurvePoints]);
|
}, [computeCurvePoints]);
|
||||||
|
|
||||||
/** Точка для подписи: середина ребра + смещение по перпендикуляру (чтобы подпись была у ребра, а не уезжала) */
|
/** Точка подписи на кривой с небольшим jitter и ограничением в пределах карты */
|
||||||
const labelPlacement = useCallback((e, level = 0) => {
|
const labelPlacement = useCallback((e, level = 0) => {
|
||||||
const { mx, my, perpX, perpY } = computeCurvePoints(e);
|
const geom = computeCurvePoints(e);
|
||||||
const baseOffset = 18;
|
const jitter = (hash01(e.edgeKey) - 0.5) * 0.24;
|
||||||
const stepOffset = 26;
|
const t = clamp(0.42 + jitter, 0.26, 0.74);
|
||||||
const x = mx + perpX * (baseOffset + level * stepOffset);
|
const omt = 1 - t;
|
||||||
const y = my + perpY * (baseOffset + level * stepOffset);
|
const xCurve = omt * omt * geom.sOutX + 2 * omt * t * geom.cpx + t * t * geom.eOutX;
|
||||||
return { x, y };
|
const yCurve = omt * omt * geom.sOutY + 2 * omt * t * geom.cpy + t * t * geom.eOutY;
|
||||||
}, [computeCurvePoints]);
|
const baseOffset = 16;
|
||||||
|
const stepOffset = 18;
|
||||||
|
const x = xCurve + geom.perpX * (baseOffset + level * stepOffset);
|
||||||
|
const y = yCurve + geom.perpY * (baseOffset + level * stepOffset);
|
||||||
|
const margin = 22;
|
||||||
|
return {
|
||||||
|
x: clamp(x, margin, Math.max(margin, size.w - margin)),
|
||||||
|
y: clamp(y, margin, Math.max(margin, size.h - margin)),
|
||||||
|
};
|
||||||
|
}, [computeCurvePoints, size.w, size.h]);
|
||||||
|
|
||||||
if (servers.length === 0) return null;
|
if (servers.length === 0) return null;
|
||||||
|
|
||||||
@@ -500,11 +523,15 @@ export default function NetworkMapUnifi({
|
|||||||
const used = [];
|
const used = [];
|
||||||
const LABEL_W = 118;
|
const LABEL_W = 118;
|
||||||
const LABEL_H = 22;
|
const LABEL_H = 22;
|
||||||
|
const denseMode = routedEdges.length > 14;
|
||||||
return routedEdges.map((e, idx) => {
|
return routedEdges.map((e, idx) => {
|
||||||
const dimFactor =
|
const dimFactor =
|
||||||
hoveredEdgeKey && hoveredEdgeKey !== e.edgeKey ? 0.25 : 1;
|
hoveredEdgeKey && hoveredEdgeKey !== e.edgeKey ? 0.16 : 1;
|
||||||
const strokeWidth = hoveredEdgeKey === e.edgeKey ? 3 : 2;
|
const strokeWidth = hoveredEdgeKey === e.edgeKey ? 3 : 1.8;
|
||||||
const edgeColor = getTunnelColor(e.tunnelType);
|
const edgeColor = getTunnelColor(e.tunnelType);
|
||||||
|
const isFocused =
|
||||||
|
hoveredEdgeKey === e.edgeKey || selectedEdge?.edgeKey === e.edgeKey;
|
||||||
|
const baseOpacity = denseMode ? 0.62 : 0.82;
|
||||||
return (
|
return (
|
||||||
<g
|
<g
|
||||||
key={e.edgeKey || `${e.from}-${e.to}-${idx}`}
|
key={e.edgeKey || `${e.from}-${e.to}-${idx}`}
|
||||||
@@ -521,12 +548,13 @@ export default function NetworkMapUnifi({
|
|||||||
stroke={edgeColor}
|
stroke={edgeColor}
|
||||||
strokeWidth={strokeWidth}
|
strokeWidth={strokeWidth}
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
opacity={dimFactor}
|
opacity={baseOpacity * dimFactor}
|
||||||
filter="url(#edgeGlow)"
|
filter="url(#edgeGlow)"
|
||||||
/>
|
/>
|
||||||
{(() => {
|
{(() => {
|
||||||
if (!e.edgeLabel) return null;
|
const showLabel = e.edgeLabel && (!denseMode || isFocused || e.stale);
|
||||||
const minDist = 70;
|
if (!showLabel) return null;
|
||||||
|
const minDist = denseMode ? 56 : 70;
|
||||||
let level = 0;
|
let level = 0;
|
||||||
let x; let y;
|
let x; let y;
|
||||||
while (level < 10) {
|
while (level < 10) {
|
||||||
@@ -557,9 +585,9 @@ export default function NetworkMapUnifi({
|
|||||||
width={w}
|
width={w}
|
||||||
height={h}
|
height={h}
|
||||||
rx={7}
|
rx={7}
|
||||||
fill="rgba(2,6,23,0.9)"
|
fill={isFocused ? 'rgba(2,6,23,0.94)' : 'rgba(2,6,23,0.85)'}
|
||||||
stroke={isStale ? staleColor : edgeColor}
|
stroke={isStale ? staleColor : edgeColor}
|
||||||
strokeWidth={1}
|
strokeWidth={isFocused ? 1.3 : 1}
|
||||||
strokeDasharray={isStale ? '2,2' : 'none'}
|
strokeDasharray={isStale ? '2,2' : 'none'}
|
||||||
/>
|
/>
|
||||||
{isStale && (
|
{isStale && (
|
||||||
|
|||||||
Reference in New Issue
Block a user