Jon
Jon

Reputation: 101

How to add a d3js graph in slideshow instead of body?

I am very new to d3js, css, html and trying to practice different examples of d3js. I am trying to add a d3js graph in a slideshow instead of adding it to a body of webpage. I am kind of stuck on how to do this. How do i place a graph in slideshow ? For your reference below is my attempted code-

<div class="mySlides fade">
        <div class="numbertext">2 / 3</div>

 Something goes here in slide 2

  </div>
    </div>


  <div class="mySlides fade">

      <div class="numbertext">3 / 4</div>

      <h1 style="font-size:400%;"><u>Data</u></h1>



          <script src="http://d3js.org/d3.v3.min.js"></script>
      <script>
            var margin = {top: 20, right: 20, bottom: 30, left: 40},
                width = 960 - margin.left - margin.right,
                height = 500 - margin.top - margin.bottom;

            /* 
             * value accessor - returns the value to encode for a given data object.
             * scale - maps value to a visual display encoding, such as a pixel position.
             * map function - maps from data value to display value
             * axis - sets up axis
             */ 

            // setup x 
            var xValue = function(d) { return d.Contributions;}, // data -> value
                xScale = d3.scale.linear().range([0, width]), // value -> display
                xMap = function(d) { return xScale(xValue(d));}, // data -> display
                xAxis = d3.svg.axis().scale(xScale).orient("bottom");

            // setup y
            var yValue = function(d) { return d.Deaths;}, // data -> value
                yScale = d3.scale.linear().range([height, 0]), // value -> display
                yMap = function(d) { return yScale(yValue(d));}, // data -> display
                yAxis = d3.svg.axis().scale(yScale).orient("left");

            // setup fill color
            var cValue = function(d) { return d.State;},
                color = d3.scale.category10();




            // add the graph canvas to the body of the webpage
            var svg = d3.select("body").append("svg")
             .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
             .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            // add the tooltip area to the webpage
            var tooltip = d3.select("body").append("div")
            .attr("class", "tooltip")
            .style("opacity", 0);

            // load data
            d3.csv("data.csv", function(error, data) {

              // change string (from CSV) into number format
              data.forEach(function(d) {
                d.Contributions = +d.Contributions;
                d.Deaths = +d.Deaths;
             //  console.log(d);
              });

            //   // don't want dots overlapping axis, so add in buffer to data domain
               xScale.domain([d3.min(data, xValue)-1, d3.max(data, xValue)+1]);
               yScale.domain([d3.min(data, yValue)-1, d3.max(data, yValue)+1]);

            //   // x-axis
              svg.append("g")
                  .attr("class", "x axis")
                  .attr("transform", "translate(0," + height + ")")
                  .call(xAxis)
                .append("text")
                  .attr("class", "label")
                  .attr("x", width)
                  .attr("y", -6)
                  .style("text-anchor", "end")
                  .text("Conntributions");

            //   // y-axis
              svg.append("g")
                  .attr("class", "y axis")
                  .call(yAxis)
                .append("text")
                  .attr("class", "label")
                  .attr("transform", "rotate(-90)")
                  .attr("y", 6)
                  .attr("dy", ".71em")
                  .style("text-anchor", "end")
                  .text("Deaths");

              // draw dots
              svg.selectAll(".dot")
                  .data(data)
                .enter().append("circle")
                  .attr("class", "dot")
                  .attr("r", 3.5)
                  .attr("cx", xMap)
                  .attr("cy", yMap)
                  .style("fill", function(d) { return color(cValue(d));}) 
                  .on("mouseover", function(d) {
                      tooltip.transition()
                           .duration(200)
                           .style("opacity", .9);
                      tooltip.html(d["State"] + "<br/> (" + xValue(d) 
                        + ", " + yValue(d) + ")")
                           .style("left", (d3.event.pageX + 5) + "px")
                           .style("top", (d3.event.pageY - 28) + "px");
                  })
                  .on("mouseout", function(d) {
                      tooltip.transition()
                           .duration(500)
                           .style("opacity", 0);
                  });

              // draw legend
              var legend = svg.selectAll(".legend")
                  .data(color.domain())
                .enter().append("g")
                  .attr("class", "legend")
                  .attr("transform", function(d, i) {
                    return "translate("+ (i * 20 + 137) + ", 6)";
                  });

              // draw legend colored rectangles
              var boxSize = 17;
              legend.append("rect")
                  .attr("x", 0)
                  .attr("width", boxSize)
                  .attr("height", boxSize)
                  .style("fill", color);

              // draw legend text
              legend.append("text")
                  .attr("x", -8.2)
                  .attr("y", 19)
                  .attr("dy", ".35em")
                  .style("text-anchor", "end")
                  .attr("transform","rotate(-43)")
                  .text(function(d) { return d;})
            });

            </script>




    </div>

This code gets me a graph in all pages of slideshow which i don't want but instead i would like to add a graph in page 3 of my slideshow.

Upvotes: 4

Views: 255

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

This is an interesting question: normally, the answer here would be just "select the div you want by ID or any other CSS selector that suits you" (or, since that this has been answered many many times, just a comment and a vote to close). The basis for that answer is that this...

var svg = d3.select("body").append("svg")

... will append the SVG at the end of the body. So far, nothing new or difficult.

But why did I said that this is an interesting question?

Because of the funny way (if you don't mind me saying so) you tried to select the div: you thought that D3 would create the chart inside that div just by putting the respective script inside it.

Of course putting the script inside the container div is not the way of doing this. But just for the sake of curiosity, there is a way of doing what you thought you were doing (again, selecting the element that contains the script): by using document.currentScript, which:

Returns the element whose script is currently being processed.

So, all we need in your situation is:

var container = document.currentScript.parentNode;
var svg = d3.select(container)
    .append("svg")
    //etc...

Which appends the SVG in the <div> (or any other containing element) that contains the <script>.

Here is a basic demo:

<script src="https://d3js.org/d3.v5.min.js"></script>
<div>
  <h3>I am div 1</h3>
</div>
<div>
  <h3>I am div 2, I have a chart</h3>
  <script>
    var container = document.currentScript.parentNode;
    var svg = d3.select(container)
      .append("svg");
    var data = d3.range(10).map(d => Math.random() * 150);
    var scale = d3.scaleBand()
      .domain(data)
      .range([0, 300])
      .padding(0.4);
    var bars = svg.selectAll(null)
      .data(data)
      .enter()
      .append("rect")
      .style("fill", "steelblue")
      .attr("x", d => scale(d))
      .attr("width", scale.bandwidth())
      .attr("height", d => 150 - d)
      .attr("y", Number)
  </script>
</div>
<div>
  <h3>I am div 3</h3>
</div>
<div>
  <h3>I am div 4</h3>
</div>

Note that document.CurrentScript doesn't work on IE (if you care for IE, just give the div an ID and select it).

Upvotes: 3

Related Questions