Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elements appended to SVG with D3 are not appearing

I am trying to display some simple bar charts with D3 where each bar is a div, but nothing is being displayed.

var chartData =  [4, 8, 15, 16, 23, 42];
var body = d3.select('body');
    	
var svg = body.append('svg')
   .attr("width",800)
   .attr("height",500);
    				
var div = svg.append('div').attr('class', '.chart');
    	
for (var i = 0; i < chartData.length; i++) {
   div.append('div')
    	.attr("height", 20)
    	.attr("width", chartData[i]*10)
    	.html(chartData[i]);
}
.chart div {
	font: 10px sans-serif;
  background-color: steelblue;
	text-align: right;
	padding: 3px;
  margin: 1px;
	color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

When using inspecting the SVG I see the newly created elements and the svg is highlighted but the inner divs are not.

like image 516
martinbshp Avatar asked Mar 10 '17 08:03

martinbshp


People also ask

How is SVG used with D3?

SVG stands for Scalable Vector Graphics. SVG is an XML-based vector graphics format. It provides options to draw different shapes such as Lines, Rectangles, Circles, Ellipses, etc. Hence, designing visualizations with SVG gives you more power and flexibility.

Which tag is used for marking points in D3 using SVG?

An SVG line element is represented by <line> tag. A line's attributes are: x1: This is the x-coordinate of the first point. y1: This is the y-coordinate of the first point.

Does D3 use SVG or Canvas?

D3 charts are most often rendered using SVG, a retained mode graphics model, which is easy to use, but performance is limited. SVG charts can typically handle around 1,000 datapoints. Since D3 v4 you've also had the option to render charts using canvas, which is an immediate mode graphics model.

Is D3 SVG based?

js (also known as D3, short for Data-Driven Documents) is a JavaScript library for producing dynamic, interactive data visualizations in web browsers. It makes use of Scalable Vector Graphics (SVG), HTML5, and Cascading Style Sheets (CSS) standards.


1 Answers

In a nutshell: you cannot append a HTML element to a SVG. The reason is simple: <div>, <p>, <h1>, <h2>, <td>, <li> and so on are not valid SVG elements.

This has been asked and answered many, many times. However, I'd like to answer this question because of a specific part of it (which is normally not asked):

When using chrome's inspect I see the newly created elements.

Yes, the elements are there. But this doesn't mean it's going to work.

Let's show this in the following snippet, in which I'm appending <div>s to the SVG. look at the console.log, it shows the SVG structure:

var svg = d3.select("svg");

var data = d3.range(5);

var divs = svg.selectAll("foo")
	.data(data)
	.enter()
	.append("div")
	.html("Where are you?")
	
var mySVG = (new XMLSerializer()).serializeToString(svg.node());
console.log(mySVG)
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

You can see that the divs are in the DOM. However, there is nothing on the screen...

The fact that you see the element in the DOM means nothing, because you can append anything!

For instance, let's append an element named CharlesDarwin:

var svg = d3.select("svg");

var data = d3.range(5);

var divs = svg.selectAll("foo")
	.data(data)
	.enter()
	.append("CharlesDarwin")
	.html("I'm a strange tag!")
	
var mySVG = (new XMLSerializer()).serializeToString(svg.node());
console.log(mySVG)
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

You can see <charlesDarwin> in the DOM. However, it's obvious that nothing will show up in the SVG.

PS: Regarding your chart:

  1. Get rid of that for loop. You don't need that when using D3;
  2. Set the class without the dot;
  3. Append the divs to the body, as discussed above.

This is the working code:

var chartData = [4, 8, 15, 16, 23, 42];

var body = d3.select('body');

var div = body.selectAll("foo")
  .data(chartData)
  .enter()
  .append('div')
  .attr('class', 'chart')
  .style("width", d => d * 10 + "px")
  .html(d => d);
.chart {
  font: 10px sans-serif;
  background-color: steelblue;
  text-align: right;
  padding: 3px;
  margin: 1px;
  color: white;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
like image 184
Gerardo Furtado Avatar answered Oct 19 '22 09:10

Gerardo Furtado