score:31
you can use the following:
var svg = document.createelementns('http://www.w3.org/2000/svg', 'svg');
note the use of createelementns
. this is required because svg
elements are not in the same xhtml namespace as most html elements.
this code creates a new svg
element, as you would regardless of using d3 or not, and then creates a selection over that single element.
this can be made marginally more succinct but clearer and less error prone as:
var svg = document.createelementns(d3.ns.prefix.svg, 'svg');
score:1
i am working with version 4.4.4
var svg = document.createelementns(d3.namespaces.svg, "svg");
score:3
d3 author mike bostock suggests another (simpler) approach in his comment on an old d3 github "issue" asking about this very topic:
another strategy you could consider is to remove the element from the dom immediately after creating it:
var svg = d3.select("body").append("svg") .remove() .attr("width", w) .attr("height", w); svg.append("circle") .attr("r", 200); document.body.appendchild(svg.node());
this approach does indeed append the element on creation, but .remove
s it immediately prior to manipulation and creation of child elements, so there should be no browser repaint. while technically contrary to the original question, this is probably the most idiomatic way to meet the requirement.
score:8
here's an example function that creates an unattached group element:
function createsomething(){
return function(){
var group = d3.select(document.createelementns(d3.ns.prefix.svg, 'g'));
// add stuff...
return group.node();
}
}
you can call it like so:
node.append(createsomething());
explanation
let's say you are rendering a collapsible tree and you want to have plus/minus icons with a circle border as the toggles. your draw function is already enormous so you want the code for drawing the plus sign in it's own function. the draw/update method will take care of proper positioning.
one option is to pass the existing container into a function:
createplus(node).attr({
x: 10,
y: 10
});
function createplus(node){
var group = node.append('g');
// add stuff...
return group;
}
we can make this better by applying the technique from @drew and @paul for creating unattached elements.
node.append(createplus())
.attr({
x: 10,
y: 10
});
function createplus(){
var group = d3.select(document.createelementns(d3.ns.prefix.svg, 'g'));
// add stuff...
return group;
}
except that throws an error because append()
expects either a string or a function.
the name may be specified either as a constant string or as a function that returns the dom element to append.
so we just change it to:
node.append(function(){
return createplus();
});
but that still doesn't work. it causes the following error:
typeerror: failed to execute 'appendchild' on 'node': parameter 1 is not of type 'node'.
luckily i found selection.node()
which does work! though, admittedly, i have no idea why.
function createplus(){
var group = d3.select(document.createelementns(d3.ns.prefix.svg, 'g'));
// add stuff...
return group.node();
}
we can save us a little more time by moving the anonymous function into createplus
:
node.append(createplus())
function createplus(){
return function(){
var group = d3.select(document.createelementns(d3.ns.prefix.svg, 'g'));
// add stuff...
return group.node();
}
}
score:15
finally, with the release of d3 v5 (march 22nd, 2018) this can now be done in d3 itself. this does not affect the other answers, whatsoever, which are still valid and in the end, d3 is going to use document.createelementns()
like described in previous posts.
as of v5 you can now use:
given the specified element name, returns a single-element selection containing a detached element of the given name in the current document.
this new feature can be used as follows:
// create detached <svg> element.
const detachedsvg = d3.create("svg");
// manipulate detached element.
detachedsvg
.attr("width", 400)
.attr("height", 200);
// bind data. append sub-elements (also not attached to dom).
detachedsvg.selectall(null)
.data([50, 100])
.enter()
//...
// attach element to dom.
d3.select("body")
.append(() => detachedsvg.node());
have a look at the following snippet for a working demo creating a detached sub-tree, which is attached on a click event:
// create detached <svg> element.
const detachedsvg = d3.create("svg");
// manipulate detached element.
detachedsvg
.attr("width", 400)
.attr("height", 200);
// bind data. attach sub-elements.
detachedsvg.selectall(null)
.data([50, 100])
.enter().append("circle")
.attr("r", 20)
.attr("cx", d => d)
.attr("cy", 50);
// still detached. attach on click.
d3.select(document)
.on("click", () => {
// attach element to dom.
d3.select("body")
.append(() => detachedsvg.node());
});
<script src="https://d3js.org/d3.v5.js"></script>
the main advantages of this approach are ease of use and clarity. the creation of the element is done by d3 behind the scenes and it is made available as a full-fledged selection with all its methods at hand. apart from manipulating the newly created detached element, the returned selection can easily be used for data-binding.
it is also worth noting, that the function is not restriced to create elements from the svg namespace but can be used to create an element from any namespace registered with d3.
score:24
to save a little bit of time you can use d3.ns.prefix.svg
var svg = document.createelementns(d3.ns.prefix.svg, 'svg');
Source: stackoverflow.com
Related Query
- How to create "svg" object without appending it?
- d3 create object without appending
- How do I create a tree layout using JSON data in d3.v4 - without stratify()
- How can I animate infinite marker movement down an SVG path without very high CPU usage?
- How to create SVG elements of different types based on data?
- How do I create a minimap of an SVG using D3 v5 and show the current viewport dimensions?
- How do you move an SVG around a webpage without triggering slow redraws?
- How to transform (rotate) svg text element without changing coordinates?
- How to create a flow layout in SVG using D3.js?
- How to create SVG shapes based on data?
- How do I import SVG to Illustrator with CSS without errors?
- How to create responsive svg using d3.js
- How to get SVG path data of TopoJSON feature without adding it to the DOM?
- On a Google maps overlay, how do I create lines between svg elements in D3
- How to make d3.js generate an svg without drawing it?
- How so create complex SVG shapes using D3JS?
- How to create SVG with grid lines using D3JS
- How to set background color for svg text tspan without foreign object?
- d3.js create same svg object with different data
- How to use "g" with svg in coffee script to rotate object in d3 ?
- How to reshaping Data in Javascript from array to object without losing some of the data
- How to Create a path in svg for d3 brush
- How to wrap the text inside the SVG polygon without cutting the text
- How to dynamically create append svg line using d3js?
- How to modify tags of an already existing svg object with data from json file
- How do I create an API or link to my SVG so other websites can show it?
- How can I create an SVG where elements' position are relative to others?
- How to select an existing SVG container in D3 without creating that container using D3?
- How to create variable number of image or circle elements in an SVG element using a loop in D3 js(v3)
- How to make an svg object move in a circular trajectory with a constant speed, D3.js
More Query from same tag
- D3, Angular component passing in variable
- d3.js : dynamically passing data to pie chart
- Date parsing troubles with javascript and regex
- D3.js network graph using force-directed layout and rectangles for nodes
- How to align legend dynamically on top-center of the chart in c3.js?
- Receive Uncaught SecurityError when accessing SVG objects from Javascript
- How to assign colors according to a index in d3.js?
- Setting up D3 force directed graph
- d3.zoomIdentity.translate().scale() doesn't respect d3.zoom().translateExtent()
- using qtip2 tooltip with d3.js
- C3 bar chart width is not working properly
- How can I find the frequency of each member in my data set
- d3 text label format based on value
- How to get Average from DOW of Date column using crossfilter to populate in bar chart
- drawing the graph of a function f(x) = x^3 - 6x^2 + 9x - 4 in d3.js
- How to make into d3.js v3.4 the same behavior drag as into v3.1?
- Display area on D3 graph
- How to read(get) Y-Axis Scale Values from D3.js Chart?
- Checking group of boxes in an indented tree
- How to create a line chart with vertical line and different backgrounds?
- Move element to front without breaking events
- D3.js sending path/link behing nodes/images
- D3.js Scales with custom easing-like interpolation
- I want to add "..." or ">>" icon after 100 characters in my html table column using javaScript (No jquery)
- What is a good way to convert %H:%M:%S strings to timespan?
- Updating the coordinates in d3js for a tree layout
- How to align text vertically on a node within a Sankey diagram (D3.JS)?
- Calling externally-located csv data in javascript
- d3.rebind in D3 v4
- D3: How can I find the largest length of my text labels?