feat: Enhance GraphView with improved zoom functionality and label styling, including shadows for better visibility and aesthetics
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 5m48s

This commit is contained in:
2025-08-08 16:03:30 +07:00
parent 896f2e668c
commit 16c75a40a8
+59 -31
View File
@@ -79,8 +79,11 @@ function GraphView({ servers, connections }) {
// Контролы масштабирования // Контролы масштабирования
const zoomBy = (factor) => { const zoomBy = (factor) => {
if (!zoomRef.current || !svgRef.current) return;
const svg = d3.select(svgRef.current); const svg = d3.select(svgRef.current);
svg.transition().duration(200).call(zoomRef.current.scaleBy, factor); const node = svgRef.current;
const center = [node.clientWidth / 2, node.clientHeight / 2];
svg.transition().duration(220).call(zoomRef.current.scaleBy, factor, center);
}; };
const fitToView = () => { const fitToView = () => {
@@ -263,6 +266,10 @@ function GraphView({ servers, connections }) {
<filter id="cardShadow" x="-50%" y="-50%" width="200%" height="200%"> <filter id="cardShadow" x="-50%" y="-50%" width="200%" height="200%">
<feDropShadow dx="0" dy="2" stdDeviation="3" floodOpacity="0.2" /> <feDropShadow dx="0" dy="2" stdDeviation="3" floodOpacity="0.2" />
</filter> </filter>
{/* Тень для ярлыков ссылок */}
<filter id="labelShadow" x="-50%" y="-50%" width="200%" height="200%">
<feDropShadow dx="0" dy="1" stdDeviation="2" floodOpacity="0.25" />
</filter>
</defs> </defs>
{/* Подложка сетки */} {/* Подложка сетки */}
<rect width="100%" height="100%" fill="url(#grid)" /> <rect width="100%" height="100%" fill="url(#grid)" />
@@ -309,36 +316,57 @@ function GraphView({ servers, connections }) {
style={{ vectorEffect: 'non-scaling-stroke' }} style={{ vectorEffect: 'non-scaling-stroke' }}
/> />
{/* Подпись связи */} {/* Подпись связи: ярлык с подложкой и halo */}
<rect {(() => {
x={mx - 50} const labelW = 140;
y={my - 35} const labelH = 38;
width="80" const lx = cx - labelW / 2;
height="30" const ly = cy - labelH / 2 - 4; // слегка выше вершины
rx="15" return (
fill="#ffffff" <g style={{ pointerEvents: 'none' }}>
stroke={style.color} <rect
strokeWidth="1" x={lx}
/> y={ly}
<text width={labelW}
x={mx - 10} height={labelH}
y={my - 18} rx="16"
textAnchor="middle" fill="#ffffff"
fontSize="11" stroke={style.color}
fill="#374151" strokeWidth="1"
fontWeight="bold" filter="url(#labelShadow)"
> />
{connection.tunnelType} {/* Halo для заголовка */}
</text> <text
<text x={cx}
x={mx} y={ly + 16}
y={my - 3} textAnchor="middle"
textAnchor="middle" fontSize="12"
fontSize="9" fontWeight="700"
fill="#6b7280" stroke="#ffffff"
> strokeWidth="3"
{connection.ipA} ⇄ {connection.ipB} strokeLinejoin="round"
</text> fill="#374151"
style={{ paintOrder: 'stroke fill' }}
>
{connection.tunnelType}
</text>
{/* Линия IP с более мелким шрифтом */}
<text
x={cx}
y={ly + 30}
textAnchor="middle"
fontSize="10"
fill="#6b7280"
stroke="#ffffff"
strokeWidth="2"
strokeLinejoin="round"
style={{ paintOrder: 'stroke fill' }}
>
{connection.ipA} ⇄ {connection.ipB}
</text>
</g>
);
})()}
</g> </g>
); );
})} })}