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 };
|
||||
}
|
||||
|
||||
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({
|
||||
servers = [],
|
||||
connections = [],
|
||||
@@ -442,15 +456,24 @@ export default function NetworkMapUnifi({
|
||||
return `M ${sx} ${sy} L ${sOutX} ${sOutY} Q ${cpx} ${cpy} ${eOutX} ${eOutY} L ${ex} ${ey}`;
|
||||
}, [computeCurvePoints]);
|
||||
|
||||
/** Точка для подписи: середина ребра + смещение по перпендикуляру (чтобы подпись была у ребра, а не уезжала) */
|
||||
/** Точка подписи на кривой с небольшим jitter и ограничением в пределах карты */
|
||||
const labelPlacement = useCallback((e, level = 0) => {
|
||||
const { mx, my, perpX, perpY } = computeCurvePoints(e);
|
||||
const baseOffset = 18;
|
||||
const stepOffset = 26;
|
||||
const x = mx + perpX * (baseOffset + level * stepOffset);
|
||||
const y = my + perpY * (baseOffset + level * stepOffset);
|
||||
return { x, y };
|
||||
}, [computeCurvePoints]);
|
||||
const geom = computeCurvePoints(e);
|
||||
const jitter = (hash01(e.edgeKey) - 0.5) * 0.24;
|
||||
const t = clamp(0.42 + jitter, 0.26, 0.74);
|
||||
const omt = 1 - t;
|
||||
const xCurve = omt * omt * geom.sOutX + 2 * omt * t * geom.cpx + t * t * geom.eOutX;
|
||||
const yCurve = omt * omt * geom.sOutY + 2 * omt * t * geom.cpy + t * t * geom.eOutY;
|
||||
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;
|
||||
|
||||
@@ -500,11 +523,15 @@ export default function NetworkMapUnifi({
|
||||
const used = [];
|
||||
const LABEL_W = 118;
|
||||
const LABEL_H = 22;
|
||||
const denseMode = routedEdges.length > 14;
|
||||
return routedEdges.map((e, idx) => {
|
||||
const dimFactor =
|
||||
hoveredEdgeKey && hoveredEdgeKey !== e.edgeKey ? 0.25 : 1;
|
||||
const strokeWidth = hoveredEdgeKey === e.edgeKey ? 3 : 2;
|
||||
hoveredEdgeKey && hoveredEdgeKey !== e.edgeKey ? 0.16 : 1;
|
||||
const strokeWidth = hoveredEdgeKey === e.edgeKey ? 3 : 1.8;
|
||||
const edgeColor = getTunnelColor(e.tunnelType);
|
||||
const isFocused =
|
||||
hoveredEdgeKey === e.edgeKey || selectedEdge?.edgeKey === e.edgeKey;
|
||||
const baseOpacity = denseMode ? 0.62 : 0.82;
|
||||
return (
|
||||
<g
|
||||
key={e.edgeKey || `${e.from}-${e.to}-${idx}`}
|
||||
@@ -521,12 +548,13 @@ export default function NetworkMapUnifi({
|
||||
stroke={edgeColor}
|
||||
strokeWidth={strokeWidth}
|
||||
strokeLinecap="round"
|
||||
opacity={dimFactor}
|
||||
opacity={baseOpacity * dimFactor}
|
||||
filter="url(#edgeGlow)"
|
||||
/>
|
||||
{(() => {
|
||||
if (!e.edgeLabel) return null;
|
||||
const minDist = 70;
|
||||
const showLabel = e.edgeLabel && (!denseMode || isFocused || e.stale);
|
||||
if (!showLabel) return null;
|
||||
const minDist = denseMode ? 56 : 70;
|
||||
let level = 0;
|
||||
let x; let y;
|
||||
while (level < 10) {
|
||||
@@ -557,9 +585,9 @@ export default function NetworkMapUnifi({
|
||||
width={w}
|
||||
height={h}
|
||||
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}
|
||||
strokeWidth={1}
|
||||
strokeWidth={isFocused ? 1.3 : 1}
|
||||
strokeDasharray={isStale ? '2,2' : 'none'}
|
||||
/>
|
||||
{isStale && (
|
||||
|
||||
Reference in New Issue
Block a user