const d_connector_top = 5; const d_connector_mask = 0; function connect(mask, tbox, index) { const tbox_rect = tbox.getBoundingClientRect(); const img = document.querySelector(".image-wrapper img"); const img_rect = img.getBoundingClientRect(); let coords; if (tbox.classList.contains("right")) { coords = connectToRight(mask, img_rect, tbox_rect); } else { coords = connectToLeft(mask, img_rect, tbox_rect); } // get the border color of this mask const maskColor = mask.dataset.color; // --- build a fresh SVG connector --- const connector = document.createElementNS("http://www.w3.org/2000/svg", "svg"); connector.setAttribute("width", "1px"); connector.setAttribute("height", "1px"); connector.setAttribute("class", "connector"); connector.setAttribute("id", `connector${index}`); connector.style.position = "absolute"; connector.style.top = coords.top + "px"; connector.style.left = coords.left + "px"; // straight line const straight = document.createElementNS("http://www.w3.org/2000/svg", "line"); straight.setAttribute("class", "straight"); straight.setAttribute("x1", coords.x0); straight.setAttribute("y1", coords.y0); straight.setAttribute("x2", coords.x1); straight.setAttribute("y2", coords.y1); straight.setAttribute("stroke", maskColor); // diagonal line const diagonal = document.createElementNS("http://www.w3.org/2000/svg", "line"); diagonal.setAttribute("class", "diagonal"); diagonal.setAttribute("x1", coords.x1); diagonal.setAttribute("y1", coords.y1); diagonal.setAttribute("x2", coords.x2); diagonal.setAttribute("y2", coords.y2); diagonal.setAttribute("stroke", maskColor); connector.appendChild(straight); connector.appendChild(diagonal); const wrapper = document.querySelector(".image-wrapper"); wrapper.appendChild(connector); } function connectToRight(mask, img_rect, tbox_rect) { const width = img_rect.width; const height = img_rect.height; const top = parseFloat(mask.dataset.top) * height; const left = parseFloat(mask.dataset.left) * width; const w1 = img_rect.right - (img_rect.left + left) + 15; const w2 = tbox_rect.left - (img_rect.left + left) - w1 - d_connector_mask; const h2 = (tbox_rect.top + tbox_rect.bottom) / 2 - (img_rect.top + top) - d_connector_top; const [x0, y0] = [0, 0]; const [x1, y1] = [x0 + w1, 0]; const [x2, y2] = [x0 + w1 + w2, h2]; return { top, left, x0, y0, x1, y1, x2, y2 }; } function connectToLeft(mask, img_rect, tbox_rect) { const width = img_rect.width; const height = img_rect.height; const top = parseFloat(mask.dataset.top) * height; const left = parseFloat(mask.dataset.left) * width; const w1 = left + 15; const w2 = (img_rect.left + left) - tbox_rect.right - w1 - d_connector_mask; const h2 = (tbox_rect.top + tbox_rect.bottom) / 2 - (img_rect.top + top) - d_connector_top; const [x0, y0] = [0, 0]; const [x1, y1] = [x0 - w1, 0]; const [x2, y2] = [x0 - w1 - w2, h2]; return { top, left, x0, y0, x1, y1, x2, y2 }; } function redrawAll() { const wrapper = document.querySelector(".image-wrapper"); // clear old connectors first wrapper.querySelectorAll("svg.connector").forEach(el => el.remove()); const masks = document.querySelectorAll(".svg"); masks.forEach((mask, index) => { const tbox = document.querySelector(`#tbox${index}`); if (tbox) { connect(mask, tbox, index); } }); } redrawAll(); window.addEventListener("resize", redrawAll); window.addEventListener("scroll", redrawAll);