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.
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).
Related
Hi I am trying to add in a color scale for my heat map. I Specifically want to use d3.schemeRdYlBu this color scheme but I am having a hard time implementing it. At the moment it just does black. I also have a hover feature with this so I would like that to still work but i am more concerned with just getting the color to work. Obviously having the lower numbers be blue and the higher numbers be red to indicate temp
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<!-- Load color palettes -->
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
// set the dimensions and margins of the graph
var margin = {top: 80, right: 25, bottom: 30, left: 40},
width = 1000 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/Nataliemcg18/Data/master/NASA_Surface_Temperature.csv", function(data) {
// Labels of row and columns -> unique identifier of the column called 'group' and 'variable'
var myGroups = d3.map(data, function(d){return d.group;}).keys()
var myVars = d3.map(data, function(d){return d.variable;}).keys()
// Build X scales and axis:
var x = d3.scaleBand()
.range([ 0, width ])
.domain(myGroups)
.padding(0.05);
svg.append("g")
.style("font-size", 15)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickSize(0))
.select(".domain").remove()
// Build Y scales and axis:
var y = d3.scaleBand()
.range([ height, 0 ])
.domain(myVars)
.padding(0.05);
svg.append("g")
.style("font-size", 15)
.call(d3.axisLeft(y).tickSize(0))
.select(".domain").remove()
// Build color scale
var myColor = (d3.schemeRdYlBu[2])
// create a tooltip
var tooltip = d3.select("#my_dataviz")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
// Three function that change the tooltip when user hover / move / leave a cell
var mouseover = function(d) {
tooltip
.style("opacity", 1)
d3.select(this)
.style("stroke", "green")
.style("opacity", 1)
}
var mousemove = function(d) {
tooltip
.html("The exact value of this cell is: " + d.value, )
.style("left", (d3.mouse(this)[0]+70) + "px")
.style("top", (d3.mouse(this)[1]) + "px")
}
var mouseleave = function(d) {
tooltip
.style("opacity", 0)
d3.select(this)
.style("stroke", "none")
.style("opacity", 0.8)
}
// add the squares
svg.selectAll()
.data(data, function(d) {return d.group+':'+d.variable;})
.enter()
.append("rect")
.attr("x", function(d) { return x(d.group) })
.attr("y", function(d) { return y(d.variable) })
.attr("rx", 4)
.attr("ry", 4)
.attr("width", x.bandwidth() )
.attr("height", y.bandwidth() )
.style("fill", function(d) { return myColor(d.value)} )
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave)
})
// Add title to graph
svg.append("text")
.attr("x", 0)
.attr("y", -50)
.attr("text-anchor", "left")
.style("font-size", "22px")
.text("A d3.js heatmap");
// Add subtitle to graph
svg.append("text")
.attr("x", 0)
.attr("y", -20)
.attr("text-anchor", "left")
.style("font-size", "14px")
.style("fill", "grey")
.style("max-width", 400)
.text("A short description of the take-away message of this chart.");
</script>
You can use arrow function instead of the regular function to use your own binding of this for accessing myColor variable.
<!DOCTYPE html>
<meta charset="utf-8" />
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<!-- Load color palettes -->
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
// set the dimensions and margins of the graph
var margin = { top: 80, right: 25, bottom: 30, left: 40 },
width = 1000 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3
.select("#my_dataviz")
.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 + ")");
//Read the data
d3.csv(
"https://raw.githubusercontent.com/Nataliemcg18/Data/master/NASA_Surface_Temperature.csv",
function (data) {
// Labels of row and columns -> unique identifier of the column called 'group' and 'variable'
var myGroups = d3
.map(data, function (d) {
return d.group;
})
.keys();
var myVars = d3
.map(data, function (d) {
return d.variable;
})
.keys();
// Build X scales and axis:
var x = d3.scaleBand().range([0, width]).domain(myGroups).padding(0.05);
svg
.append("g")
.style("font-size", 15)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickSize(0))
.select(".domain")
.remove();
// Build Y scales and axis:
var y = d3.scaleBand().range([height, 0]).domain(myVars).padding(0.05);
svg
.append("g")
.style("font-size", 15)
.call(d3.axisLeft(y).tickSize(0))
.select(".domain")
.remove();
// Build color scale
var myColor = d3.schemeRdYlBu[3][2];
// create a tooltip
var tooltip = d3
.select("#my_dataviz")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
// Three function that change the tooltip when user hover / move / leave a cell
var mouseover = function (d) {
tooltip.style("opacity", 1);
d3.select(this).style("stroke", "green").style("opacity", 1);
};
var mousemove = function (d) {
tooltip
.html("The exact value of this cell is: " + d.value)
.style("left", d3.mouse(this)[0] + 70 + "px")
.style("top", d3.mouse(this)[1] + "px");
};
var mouseleave = function (d) {
tooltip.style("opacity", 0);
d3.select(this).style("stroke", "none").style("opacity", 0.8);
};
// add the squares
svg
.selectAll()
.data(data, function (d) {
return d.group + ":" + d.variable;
})
.enter()
.append("rect")
.attr("x", function (d) {
return x(d.group);
})
.attr("y", function (d) {
return y(d.variable);
})
.attr("rx", 4)
.attr("ry", 4)
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", (d) => {
return myColor;
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
}
);
// Add title to graph
svg
.append("text")
.attr("x", 0)
.attr("y", -50)
.attr("text-anchor", "left")
.style("font-size", "22px")
.text("A d3.js heatmap");
// Add subtitle to graph
svg
.append("text")
.attr("x", 0)
.attr("y", -20)
.attr("text-anchor", "left")
.style("font-size", "14px")
.style("fill", "grey")
.style("max-width", 400)
.text("A short description of the take-away message of this chart.");
</script>
This is another way to get the desired results
var myColor = d3.scaleSequential()
.interpolator( d3.interpolateRdYlBu)
.domain([1.37, -.81])
This question already has answers here:
Why does click event handler fire immediately upon page load?
(4 answers)
Closed 4 years ago.
I'm getting introduced to javascript and I'm trying to use .on("mouseovert", ...) in order to get the x-value of my graph when the cursor is upon the graph.
My code look like this:
// do something as mouseover the graph
svg.select("svg")
.on("mouseover", alert("mouse on graph"));
The result is: an alert appears when I open the html file (and loading my js script), but nothing happen as is hover the graph.
Everything else in the script works fine.
Do you know why?
Thank you very much for the time you take!
Here is the full script:
function draw_co2(url) {
d3.select("svg").remove() //remove the old graph
// set the dimensions and margins of the graph
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the date / time
var parseTime = d3.timeParse("%Y-%m-%d");
// Get the data
d3.json(url, function (error, data) {
if (error)
throw ('There was an error while getting geoData: ' + error);
data.forEach(function (d) {
d.Date = parseTime(d.Date);
d.Trend = +d.Trend;
});
// set the ranges // Scale the range of the data
var x = d3.scaleTime().domain([new Date("1960"), new Date("2015")]).range([0, width]);
var y = d3.scaleLinear()
.domain([d3.min(data, function (d) {
return d.Trend;
}) - 1 / 100 * d3.min(data, function (d) {
return d.Trend;
}), d3.max(data, function (d) {
return d.Trend;
}) + 1 / 100 * d3.min(data, function (d) {
return d.Trend;
})])
.range([height, 0]);
// define the line
var valueline = d3.line()
.x(function (d) {
return x(d.Date);
})
.y(function (d) {
return y(d.Trend);
});
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select("#graph_draw").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 + ")");
//Y Axis label
svg.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Carbon dioxide (ppm)");
// Add the valueline path.
svg.append("path")
.data([data])
.style("opacity", 0)
.transition()
.duration(1000)
.style("opacity", 1)
.attr("class", "line")
.attr("d", valueline);
// Add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add the Y Axis
svg.append("g")
.call(d3.axisLeft(y));
// gridlines in x axis function
function make_x_gridlines() {
return d3.axisBottom(x)
.ticks(10);
};
// add the X gridlines
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_gridlines()
.tickSize(-height)
.tickFormat(""));
// do something as mouseover the graph
svg.select("svg")
.on("mouseover", alert("mouse on graph"));
})
}
Use mouser over as an inline function
svg.select("svg")
.on("mouseover", function () {
alert("mouse on graph")
});
I experience the weirdest problem:
If I draw my axis before my graph, the graph misses as much text elements as there are ticks in the axis. When I increase or decrease the number of ticks, the number of missing text elements increases or decreases alike.
If I draw my axis after my graph, everything is alright.
I want to draw the axis first, as I want the grid lines to appear below the graph. And first of all, I want to understand what is going on here.
Here the code snippet in question:
var generateVisualization = function() {
var margin = {top: 30, right: 10, bottom: 30, left: 10};
var width = 1000 - margin.left - margin.right;
var height = (dataset.length * 11) + 5;
var xScale = d3.scale.linear()
.domain([1850, 2020])
.range([0, width])
var xAxisBottom = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickSize(-height)
.tickFormat(d3.format("d")); // removes the comma as thousands separator
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 + ")")
// Axis drawn first
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxisBottom);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(d.BeginDate);
})
.attr("y", function(d, i) {
return i * 11 + 3;
})
.attr("width", function(d, i) {
return xScale(d.EndDate) - xScale(d.BeginDate);
})
.attr("height", 4)
.attr("class", "line");
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d.DisplayName;
})
.attr("x", function(d, i) {
return xScale(d.BeginDate) + (xScale(d.EndDate) - xScale(d.BeginDate)) + 4;
})
.attr("y", function(d, i) {
return i * 11 + 8;
})
.attr("font-family", "sans-serif")
.attr("font-size", 8);
// Alternative: Axis drawn last
/*
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxisBottom);
*/
};
My hunch:
Instead of this:
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d.DisplayName;
})
do this:
svg.selectAll(".myLabel")//selection via class
.data(dataset)
.enter()
.append("text")
.attr("class", "myLabel")//adding a class to the label
.text(function(d) {
return d.DisplayName;
})
Reason: when you do
svg.selectAll("text")
It will select the text on ticks, and bind the data to it. This is the reason for the anomaly... you increase the ticks the labels displayed decreases.
The above solution will add the class myLabel to only the labels but not the tick text, so the problem should resolve.
I'm trying to find a way to add grid boxes to my D3.js scatterplot. The boxes should have a certain color depending on in which value range they reside. For example the box that is between x value 0-20 and y value 0-20 should be green.
What I have now:
What I want - Illustration:
I know that I could add a background image for the svg, but that doesn't seem to be a viable solution.
My code so far:
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 1200 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// setup x
var xValue = function(d) { return d.Impact;}, // 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.Likelihood;}, // 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.Conf;},
color = d3.scale.category20();
// add the graph canvas to the body of the webpage
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right + 400)
.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("#chart").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// change string (from CSV) into number format
data.forEach(function(d) {
d,Impact = +d.Impact;
d.Likelihood = +d.Likelihood;
});
// 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]);
// scales w/o extra padding
xScale.domain([d3.min(data, xValue), d3.max(data, xValue)]);
yScale.domain([d3.min(data, yValue), d3.max(data, yValue)]);
// x-axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.attr("class", "grid")
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Likelihood");
// y-axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.attr("class", "grid")
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Impact");
// draw dots
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 5.5)
.attr("cx", xMap)
.attr("cy", yMap)
.style("fill", function(d) { return color(d.CategoryMain);})
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html(d.CategoryMain + "<br/> " + d.CategorySub1 + "<br/>(" + xValue(d)
+ ", " + yValue(d) + ")")
.style("left", (d3.event.pageX + 10) + "px")
.style("top", (d3.event.pageY - 10) + "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(160," + (i+7) * 20 + ")"; });
// draw legend colored rectangles
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
// draw legend text
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d;})
})
Any suggestions how this could be done?
I've been searching around for a while now for a possible solution to this problem. I've created a bar chart for a company dashboard based on this graph.
http://bl.ocks.org/mbostock/3887051
This is working great, however what I would like to do now is display some of the external data that I have in text underneath the graph so for example. "Total Sales Today = ......" instead of just a monthly graph.
So I guess I'm asking is there a way to do this in d3.js using a text element or anything similar? if not pointing me to something that can would be great. Ill also add that the data is coming from a csv.
This is the code:
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
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 + ")");
d3.csv("data.csv", function(error, data) {
var Names = d3.keys(data[0]).filter(function(key) { return key !== "Month"; });
data.forEach(function(d) {
d.Total = Names.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.Month; }));
x1.domain(Names).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.Total, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Sales Value £");
var text = svg.selectAll("text")
.data(data)
.enter()
.append("text");
var Month = svg.selectAll(".Month")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x0(d.Month) + ",0)"; });
Month.selectAll("rect")
.data(function(d) { return d.Total; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(Names.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
If you need any more info just say
Cheers!
In your HTML file, create a div for your chart and a div below that for your label
<div id="chart"></div>
<div id="label"></div>
In your d3 code, instead of appending an svg element to the body, select the "chart" div and append an svg element to it.
var svg = d3.select("#chart").append("svg"). ...
Use that svg element to draw your chart like in your above code.
At some point in your code calculate the total sales for the day and create a variable called totalSales. You could do this by summing up the sales value when you draw the chart, but it doesn't really matter as long as totalSales is calculated.
Create another svg element on the "label" div
var svgLabel = d3.select("#label").append("svg") ...
Use this svgLabel to write a text element with totalSales as the text attribute.
svg.append("text")
...
.text(totalSales);