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) => {
if (!zoomRef.current || !svgRef.current) return;
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 = () => {
@@ -263,6 +266,10 @@ function GraphView({ servers, connections }) {
<filter id="cardShadow" x="-50%" y="-50%" width="200%" height="200%">
<feDropShadow dx="0" dy="2" stdDeviation="3" floodOpacity="0.2" />
</filter>
{/* Тень для ярлыков ссылок */}
<filter id="labelShadow" x="-50%" y="-50%" width="200%" height="200%">
<feDropShadow dx="0" dy="1" stdDeviation="2" floodOpacity="0.25" />
</filter>
</defs>
{/* Подложка сетки */}
<rect width="100%" height="100%" fill="url(#grid)" />
@@ -309,36 +316,57 @@ function GraphView({ servers, connections }) {
style={{ vectorEffect: 'non-scaling-stroke' }}
/>
{/* Подпись связи */}
<rect
x={mx - 50}
y={my - 35}
width="80"
height="30"
rx="15"
fill="#ffffff"
stroke={style.color}
strokeWidth="1"
/>
<text
x={mx - 10}
y={my - 18}
textAnchor="middle"
fontSize="11"
fill="#374151"
fontWeight="bold"
>
{connection.tunnelType}
</text>
<text
x={mx}
y={my - 3}
textAnchor="middle"
fontSize="9"
fill="#6b7280"
>
{connection.ipA} {connection.ipB}
</text>
{/* Подпись связи: ярлык с подложкой и halo */}
{(() => {
const labelW = 140;
const labelH = 38;
const lx = cx - labelW / 2;
const ly = cy - labelH / 2 - 4; // слегка выше вершины
return (
<g style={{ pointerEvents: 'none' }}>
<rect
x={lx}
y={ly}
width={labelW}
height={labelH}
rx="16"
fill="#ffffff"
stroke={style.color}
strokeWidth="1"
filter="url(#labelShadow)"
/>
{/* Halo для заголовка */}
<text
x={cx}
y={ly + 16}
textAnchor="middle"
fontSize="12"
fontWeight="700"
stroke="#ffffff"
strokeWidth="3"
strokeLinejoin="round"
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>
);
})}