[Bug] Fix duplicate IDs in SVG defs (#108)

Fixes #107

Co-authored-by: Tim Lorsbach <tim@lorsba.ch>
Reviewed-on: enviPath/enviPy#108
This commit is contained in:
2025-09-11 10:20:33 +12:00
parent 62e6448448
commit af3981d96e

View File

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