简体   繁体   中英

How can I get my two d3 graphs to appear next to one another?

I'm trying to get these 2 divs called bar1 and bar2 to appear next to one another. I tried messing a little bit with the svg and div ids. Not sure how to get these two graphs to be side-by-side.

Here is bar1:

var margin = {top: 20, right: 20, bottom: 30, left: 40};

  var width = 360 - margin.left - margin.right,
  height = 330 - margin.top - margin.bottom;

  var chart1 = d3.select("#bar1")
     .append("svg")
     .attr('id', 'bar1svg')
     .attr('width', width + margin.left + margin.right)
     .attr('height', height + margin.top + margin.bottom);

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

  var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
   y = d3.scaleLinear().rangeRound([height, 0]);

var g = chart1.append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top +       ")");

 d3.csv ( "data/housingdata.csv", function(d) {
  d.median_housing_prices = +d.median_housing_prices;
  return d;
 }, function(error, data) {
  if (error) throw error;

 x.domain(data.map(function(d) { return d.neighborhoods; }));
 y.domain([0, d3.max(data, function(d) { return      d.median_housing_prices; })]);

g.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x));

g.append("g")
    .attr("class", "axis axis--y")
    .call(d3.axisLeft(y).ticks(20, 's'))
  .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", "0.71em")
    .attr("text-anchor", "end")
    .text("Frequency");

   g.selectAll(".bar")
  .data(data)
  .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) { return x(d.neighborhoods); })
    .attr("y", function(d) { return y(d.median_housing_prices); })
    .attr("width", x.bandwidth())
    .attr("height", function(d) { return height - y(d.median_housing_prices); });

 });

Here is bar 2:

 var chart2 = d3.select("#bar2")
   .append("svg")
   .attr('id', 'bar2svg')
   .attr('width', width + margin.left + margin.right)
   .attr('height', height + margin.top + margin.bottom);

    var g2 = chart2.append("g2")
    .attr("transform", "translate(" + margin.left + "," + margin.top +   ")");

 d3.csv("data/housingdata2.csv", function(d) {
 d.median_housing_prices = +d.median_housing_prices;
 return d;
  }, function(error, data) {
  if (error) throw error;

x.domain(data.map(function(d) { return d.neighborhoods; }));
y.domain([0, d3.max(data, function(d) { return d.median_housing_prices; })]);

g2.append("g2")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x));

g2.append("g2")
    .attr("class", "axis axis--y")
    .call(d3.axisLeft(y).ticks(10, 's'))
  .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", "0.71em")
    .attr("text-anchor", "end")
    .text("Frequency");

g2.selectAll(".bar")
  .data(data)
  .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) { return x(d.neighborhoods); })
    .attr("y", function(d) { return y(d.median_housing_prices); })
    .attr("width", x.bandwidth())
    .attr("height", function(d) { return height - y(d.median_housing_prices); });
 });

There is a lot of d3 code there, obscuring the fact that you don't have a d3 or even an SVG problem, but a standard HTML / CSS layout issue.

Browsers try to position adajacent <svg> (and <img> ) elements side by side, but then switch to a vertical layout if they judge the elements together as "too wide" for the current width. In CSS layout lingo, they have display: inline by default. <div> are block elements, however, so lay out vertically unless that is changed by CSS. The trick is subverting this, and insisting on the side by side layout, like so:

典型的例子

Note the second <svg> is clipped by the window border, because you insisted on side by side layout, come what may.

All of the approaches to get this are HTML / CSS fixes. Eg:

  • Put the SVGs in adjacent table cells
  • Use the float property to make the SVGs float left or right.
  • Add a container <div> and absolutely position the SVGs therein.
  • Add a container <div> and use text wrapping control to keep the SVGs side by side.
  • Probably a half-dozen others.

Using a containing <div> with CSS property white-space: nowrap and then setting your SVG-continaing <div> elements to display: inline is an easy solution that nicely structures your HTML, yet is simple, reliable, and maintanable in ways the table, float, and absolute positioning approaches aren't. The quick and dirty formulation in your HTML follows. (It's neater to define the styling in your CSS file.)

<div style="white-space: nowrap;">
    <div id="bar1" style="display: inline"></div>
    <div id="bar2" style="display: inline"></div>
</div>

Here is a running demo of the idea.

The disadvantage to this "always go side by side!" command is, well, you may be successful. Then the elements are side by side always, even if there isn't enough room for them to be fully displayed. If you don't want to be so always and forever, try a float: left style on #bar1 , with very little margins on your <div> and <svg> . In the Fiddle , you can change the window width to see this dynamc layout decision in action.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM