Xiphias
Xiphias

Reputation: 4716

How can I draw overlapping graphics in d3.js?

I can easily draw single elements in an svg and let them overlay using d3, but I somehow cannot combine joint data with drawn graphics.

svg = d3.select("#widget").append("svg")
    .attr("width","360")
    .attr("height","240")
svg.append("rect")
    .attr("width","360")
    .attr("height","40")
    .attr("fill","#EDA939")
dataset = [40,50,60,90,30]
svg.selectAll("rect")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("height",5)
    .attr("width",5)
    .attr("x",function(d){return d;})

enter image description here enter image description here Unfortunately, one element of my array is missing! It seems that the placeholder in the svg has been consumed by my background svg.

Now I can switch svg.selectAll("rect") with d3.select("#widget").append("svg").selectAll("rect") so that there is a second svg element, but then I get this:

enter image description here enter image description here

So either one element is missing and they overlay correctly or they do not overlay and all elements are drawn.

What can I do?

Upvotes: 0

Views: 1567

Answers (1)

ckersch
ckersch

Reputation: 7687

The background rect is being 'consumed' by the d3 selection because you map your data to all of the rects in the element with svg.selectAll('rect').data(data). When you then use the .enter() method, it selects all of the bits of data you have that don't already have a matching DOM element. Since one of your data has a matching DOM element, that one is not in the selection provided by .enter().

To fix this, all you need to do is change the selection from rect to something that describes only your data, such as a class. Try this instead:

svg.selectAll(".rectClass")
  .data(dataset)
  .enter()
  .append("rect")
  .classed('rectClass', true)
  .attr("height",5)
  .attr("width",5)
  .attr("x",function(d){return d;})

Upvotes: 1

Related Questions