+39
-28
@@ -211,6 +211,7 @@ async function loadNetworkData() {
|
||||
renderNodeList();
|
||||
renderShapeList();
|
||||
if (shapes.length) nextShapeZ = Math.max(...shapes.map(x => x.z_index)) + 1;
|
||||
buildCanvasGraph();
|
||||
renderNetwork();
|
||||
}
|
||||
|
||||
@@ -376,14 +377,14 @@ function getNodeColorVal(type) {
|
||||
|
||||
// ==================== CANVAS RENDERING ====================
|
||||
const NODE_FA_ICONS = {
|
||||
host: { path: 'M7,4 L17,4 L20,9 L20,18 L4,18 L4,9 Z', color: '#3b82f6' },
|
||||
server: { path: 'M6,3 L18,3 L20,6 L20,20 L4,20 L4,6 Z M8,10 L16,10 M8,14 L16,14 M8,17 L12,17', color: '#8b5cf6' },
|
||||
router: { path: 'M12,3 L21,10 L18,20 L6,20 L3,10 Z M12,6 L12,17 M8,10 L16,10', color: '#f59e0b' },
|
||||
firewall: { path: 'M6,3 L18,3 L21,8 L21,16 L18,21 L6,21 L3,16 L3,8 Z M9,10 L15,10 L15,14 L9,14 Z', color: '#ef4444' },
|
||||
switch: { path: 'M4,8 L20,8 L20,16 L4,16 Z M7,11 L7,13 M10,11 L10,13 M13,11 L13,13 M16,11 L16,13', color: '#06b6d4' },
|
||||
cloud: { path: 'M10,4 C6,4 4,7 5,10 C3,11 2,14 4,16 L8,16 C10,18 14,18 16,16 L20,16 C22,14 21,10 19,9 C20,6 17,4 15,5 C14,4 12,4 10,4 Z', color: '#22c55e' },
|
||||
endpoint: { path: 'M8,4 L16,4 L18,10 L18,16 L16,20 L8,20 L6,16 L6,10 Z M10,12 L14,12 M12,10 L12,14', color: '#ec4899' },
|
||||
other: { path: 'M8,6 L16,6 L18,12 L16,18 L8,18 L6,12 Z', color: '#6b7280' }
|
||||
host: { path: 'M-7,-7h14v10h-14z M-5,3h3v4h-3z M2,3h3v4h-3z M0,-10v-3', color: '#3b82f6' },
|
||||
server: { path: 'M-8,-8h16v4h-16z M-8,-2h16v4h-16z M-8,4h16v4h-16z M-8,10h16v4h-16z', color: '#8b5cf6' },
|
||||
router: { path: 'M-10,0l10,-8v5h6v6h-6v5z', color: '#f59e0b' },
|
||||
firewall: { path: 'M-9,-4l3,-4h12l3,4v8l-3,4h-12l-3,-4z M-4,-2h8v4h-8z', color: '#ef4444' },
|
||||
switch: { path: 'M-10,-4h20v2h-20z M-10,0h20v2h-20z M-10,4h20v2h-20z', color: '#06b6d4' },
|
||||
cloud: { path: 'M-2,-9c-5,0-8,3-7,7c-2,2-3,5-1,8h5c2,3,7,3,10,2h5c3-2,3-7,1-9c1-4-2-8-5-8c-1,0-3,1-4,2c-1-1-2-2-4-2z', color: '#22c55e' },
|
||||
endpoint: { path: 'M-9,-7c0-2,2-4,4-4h10c2,0,4,2,4,4v14c0,2-2,4-4,4h-10c-2,0-4-2-4-4z M-5,7h10v2h-10z M-5,3h10v2h-10z M0,-2c2,0,3,1,3,3c0,2-1,3-3,3c-2,0-3-1-3-3c0-2,1-3,3-3z', color: '#ec4899' },
|
||||
other: { path: 'M-6,-6h12v12h-12z', color: '#6b7280' }
|
||||
};
|
||||
|
||||
function buildCanvasGraph() {
|
||||
@@ -413,11 +414,11 @@ function buildCanvasGraph() {
|
||||
}
|
||||
|
||||
function renderNetwork() {
|
||||
buildCanvasGraph();
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.save();
|
||||
ctx.translate(panX, panY);
|
||||
|
||||
// Use canvasShapes / canvasNodes / canvasLinks arrays directly (no rebuild)
|
||||
canvasShapes.sort((a, b) => a.z - b.z).forEach(drawShape);
|
||||
|
||||
canvasLinks.forEach(l => {
|
||||
@@ -498,11 +499,18 @@ function drawCanvasNode(n) {
|
||||
ctx.stroke();
|
||||
ctx.shadowBlur = 0;
|
||||
|
||||
// Icon path scaled
|
||||
const scaled = n.iconPath.replace(/([\d.]+)/g, m => ((parseFloat(m) - 12) * 0.85 + 0).toFixed(1));
|
||||
const path = new Path2D(scaled);
|
||||
// Draw icon
|
||||
ctx.save();
|
||||
ctx.translate(n.x, n.y);
|
||||
const s = 1.2;
|
||||
ctx.scale(s, s);
|
||||
const path = new Path2D(n.iconPath);
|
||||
ctx.fillStyle = n.color;
|
||||
ctx.lineWidth = 1.8;
|
||||
ctx.strokeStyle = n.color;
|
||||
ctx.fill(path);
|
||||
ctx.stroke(path);
|
||||
ctx.restore();
|
||||
|
||||
// Status dot
|
||||
ctx.beginPath();
|
||||
@@ -528,10 +536,10 @@ function drawCanvasNode(n) {
|
||||
|
||||
function getShapeHandles(s) {
|
||||
return [
|
||||
{ x: s.x, y: s.y },
|
||||
{ x: s.x + s.w, y: s.y },
|
||||
{ x: s.x + s.w, y: s.y + s.h },
|
||||
{ x: s.x, y: s.y + s.h }
|
||||
{ x: s.x, y: s.y, cx: 0, cy: 0 },
|
||||
{ x: s.x + s.w, y: s.y, cx: 1, cy: 0 },
|
||||
{ x: s.x + s.w, y: s.y + s.h, cx: 1, cy: 1 },
|
||||
{ x: s.x, y: s.y + s.h, cx: 0, cy: 1 }
|
||||
];
|
||||
}
|
||||
|
||||
@@ -552,7 +560,7 @@ function getShapeResizeHandleAt(mx, my) {
|
||||
for (const s of canvasShapes) {
|
||||
if (selectedShapeId != s.id) continue;
|
||||
for (const h of getShapeHandles(s)) {
|
||||
if (Math.hypot(mx - h.x, my - h.y) < 8) return { shape: s, hx: h.x, hy: h.y };
|
||||
if (Math.hypot(mx - h.x, my - h.y) < 8) return { shape: s, cx: h.cx, cy: h.cy, sx: h.x, sy: h.y };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -563,12 +571,14 @@ function onMouseDown(e) {
|
||||
const mx = e.clientX - rect.left - panX;
|
||||
const my = e.clientY - rect.top - panY;
|
||||
|
||||
// Always build graph fresh before interacting
|
||||
buildCanvasGraph();
|
||||
|
||||
const resize = getShapeResizeHandleAt(mx, my);
|
||||
if (resize) {
|
||||
const s = resize.shape;
|
||||
dragType = 'resize'; dragTarget = s;
|
||||
dragType = 'resize'; dragTarget = resize.shape;
|
||||
dragOffX = mx; dragOffY = my;
|
||||
dragOrig = { x: s.x, y: s.y, w: s.w, h: s.h };
|
||||
dragOrig = { x: resize.shape.x, y: resize.shape.y, w: resize.shape.w, h: resize.shape.h, cx: resize.cx, cy: resize.cy };
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -585,7 +595,7 @@ function onMouseDown(e) {
|
||||
selectedNodeId = null; selectedShapeId = shape.id;
|
||||
dragType = 'shape'; dragTarget = shape;
|
||||
dragOffX = mx - shape.x; dragOffY = my - shape.y;
|
||||
renderNodeList(); renderShapeList(); renderNetwork();
|
||||
renderNodeList(); renderShapeList();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -611,13 +621,14 @@ function onMouseMove(e) {
|
||||
const dx = e.clientX - rect.left - panX - dragOffX;
|
||||
const dy = e.clientY - rect.top - panY - dragOffY;
|
||||
const s = dragTarget;
|
||||
let nx = dragOrig.x, ny = dragOrig.y, nw = dragOrig.w, nh = dragOrig.h;
|
||||
if (dragOffX < dragOrig.x + dragOrig.w / 2) { nx = dragOrig.x + dx; nw = dragOrig.w - dx; }
|
||||
else { nw = dragOrig.w + dx; }
|
||||
if (dragOffY < dragOrig.y + dragOrig.h / 2) { ny = dragOrig.y + dy; nh = dragOrig.h - dy; }
|
||||
else { nh = dragOrig.h + dy; }
|
||||
if (nw < 50) nw = 50;
|
||||
if (nh < 50) nh = 50;
|
||||
const o = dragOrig;
|
||||
let nx = o.x, ny = o.y, nw = o.w, nh = o.h;
|
||||
if (o.cx === 0) { nx = o.x + dx; nw = o.w - dx; }
|
||||
else { nw = o.w + dx; }
|
||||
if (o.cy === 0) { ny = o.y + dy; nh = o.h - dy; }
|
||||
else { nh = o.h + dy; }
|
||||
if (nw < 50) { if (o.cx === 0) nx = o.x + o.w - 50; nw = 50; }
|
||||
if (nh < 50) { if (o.cy === 0) ny = o.y + o.h - 50; nh = 50; }
|
||||
s.x = nx; s.y = ny; s.w = nw; s.h = nh;
|
||||
renderNetwork();
|
||||
} else if (isPanning) {
|
||||
|
||||
Reference in New Issue
Block a user