forked from enviPath/enviPy
[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:
@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user