One approach that fits perfectly in this scenario is utilizing a detached element. Another option could be using a DocumentFragment, but within D3 code, a detached element is considered more idiomatic.
To create a detached whatever
SVG element, you can easily do the following:
var detached = d3.create('svg:whatever');
As per the documentation,
Upon providing the specified element name, it returns a single-element selection containing a detached element with the given name within the current document.
This procedure mirrors Andrew's response to some extent, because d3.create
internally utilizes document.createElement
. Nevertheless, make sure to note that it uses document.createElement
, not document.createElementNS
, hence the namespace is imperative here:
var detached = d3.create('svg:whatever');
//this signifies the namespace----ˆ
Subsequently, you can structure it as desired. For example:
detached.selectAll(null)
.data(d3.range(5))
.enter()
.append("circle")
//etc...
Following this, obtain the node of the detached element and insert it wherever needed using append
:
svg.append(function(){ return detached.node();});
Here's an illustration; the function makeGraphic
generates a detached element and provides its node. Afterwards, we simply append the returned value to the SVG:
var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 300);
function makeGraphic() {
var detached = d3.create('svg:g');
detached.selectAll(null)
.data(d3.range(10))
.enter()
.append("circle")
.attr("cx", function() {
return Math.random() * 500
})
.attr("cy", function() {
return Math.random() * 300
})
.attr("r", function() {
return Math.random() * 50
})
.attr("fill", function(_, i) {
return d3.schemeCategory10[i]
});
return detached.node();
};
svg.append(makeGraphic)
<script src="https://d3js.org/d3.v5.min.js"></script>