Reputation: 101
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
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