Reputation: 31
I'm working on a floor plan viewer, where one should be able to select certain rooms of said plan. I'm trying to solve this with the help of a svg file. Up to this point I always generated and added the svg to the DOM, directly in javascript and added all d3.js functionality along with it (zoom, pan). Now I'm trying to achieve the same result with an external svg file (which has the same structure). What still works is to simple add this now external svg file to the DOM but I'm unable to add the d3.zoom functionality.
my svg file structure:
<svg><g><image></image>{<polygon><title><title></polygon><text></text>, ...}</g></svg>
image tag adds a floorplan png, tags inside the {} brackets are values for each single room (making selecting one possible)
loading external file (while trying to add zoom function):
var svg, g;
d3.xml('test.svg').then(function (data) {
var svgNode = data.getElementsByTagName("svg")[0];
document.getElementById("svg-viewer-foreground-3").appendChild(svgNode);
svg = d3.select("svg").call(zoom);
g = svg.select("g");
});
let zoom = d3.zoom().on('zoom', zoomed);
function zoomed() {
g.attr("transform", d3.event.transform);
}
So how do I do this correctly?
I'm happy to add additional information if needed. (This is my first time asking a question, so a possible explanation for mistakes on my end)
Upvotes: 1
Views: 790
Reputation: 31
Ok, I didn't formulate my question very specificly but I found a workaround myself. Maybe it is helpful to someone.
So in short the problem I encountered was that I could not load an external SVG file to the DOM, while being able to use the d3.js zoom functionality. Or more in detail I wasn't able to call zoom on the <svg> node I got through using d3.xml.
So my solution was to simply create a new svg node, add the attributes of the svg node loaded from the file and then append all children nodes:
d3.xml(path).then(function (data) {
// attributes have to be set manually
var svgNode = data.getElementsByTagName("svg")[0];
svg = d3.select('#div-id').append("svg")
.attr("width", svgNode.getAttribute("width"))
.attr("height", svgNode.getAttribute("height"))
.attr("id", svgNode.getAttribute("id"))
.attr("class", svgNode.getAttribute("class"))
.attr('viewBox', svgNode.getAttribute("viewBox"))
.call(zoom);
document.getElementById("svg-id").appendChild(data.getElementsByTagName("g")[0]);
});
var zoom = d3.zoom().on('zoom', handleZoom);
function handleZoom() {
d3.select('g')
.attr('transform', d3.event.transform);
}
This worked for me, but there may well be a much more elegant solution. (Oh and I used d3v5)
Upvotes: 2