diff --git a/static/js/pw.js b/static/js/pw.js index 5ccff67e..a335f951 100644 --- a/static/js/pw.js +++ b/static/js/pw.js @@ -384,30 +384,47 @@ function draw(pathway, elem) { .style("fill", "#e8e8e8"); // Add image only for non pseudo nodes - node.filter(d => !d.pseudo).each(function (d) { - const g = d3.select(this).append("g"); + node.filter(d => !d.pseudo).each(function (d, i) { + const g = d3.select(this); // Parse the SVG string const parser = new DOMParser(); const svgDoc = parser.parseFromString(d.image_svg, "image/svg+xml"); - const svgContent = svgDoc.documentElement; + const svgElem = svgDoc.documentElement; - // Remove width/height so scaling works - svgContent.removeAttribute("width"); - svgContent.removeAttribute("height"); + // Create a unique prefix per node + const prefix = `node-${i}-`; - // Move all children of the parsed SVG into our - while (svgContent.firstChild) { - g.node().appendChild(svgContent.firstChild); - } + // Rename all IDs and fix references + svgElem.querySelectorAll('[id]').forEach(el => { + const oldId = el.id; + const newId = prefix + oldId; + el.id = newId; - // Get viewBox dimensions for scaling - const vb = svgContent.viewBox.baseVal; + const XLINK_NS = "http://www.w3.org/1999/xlink"; + // Update elements that reference this old ID + const uses = Array.from(svgElem.querySelectorAll('use')).filter( + u => u.getAttributeNS(XLINK_NS, 'href') === `#${oldId}` + ); + + uses.forEach(u => { + u.setAttributeNS(XLINK_NS, 'href', `#${newId}`); + }); + }); + + g.node().appendChild(svgElem); + + const vb = svgElem.viewBox.baseVal; const svgWidth = vb.width || 40; const svgHeight = vb.height || 40; - // Center and scale - g.attr("transform", `translate(${-svgWidth/2},${-svgHeight/2}) scale(${(nodeRadius*2)/svgWidth})`); + const scale = (nodeRadius * 2) / Math.max(svgWidth, svgHeight); + + g.select("svg") + .attr("width", svgWidth * scale) + .attr("height", svgHeight * scale) + .attr("x", -svgWidth * scale / 2) + .attr("y", -svgHeight * scale / 2); }); // add element to nodes array