Skip to content

Instantly share code, notes, and snippets.

@rlugojr
Forked from diethardsteiner/index.html
Created June 26, 2016 06:11
Show Gist options
  • Save rlugojr/73633a7675299f802401c6841bc3926d to your computer and use it in GitHub Desktop.
Save rlugojr/73633a7675299f802401c6841bc3926d to your computer and use it in GitHub Desktop.
Simple D3JS Dashboard
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Testing Pie Chart</title>
<!--<script type="text/javascript" src="d3/d3.v2.js"></script>-->
<script src="http://d3js.org/d3.v2.js"></script>
<!-- Note: I made good use of the sample code provided by the D3JS community and extended it to fit my needs to create this simple dashboard -->
<style type="text/css">
#pieChart {
position:absolute;
top:10px;
left:10px;
width:400px;
height: 400px;
}
#lineChart {
position:absolute;
top:10px;
left:410px;
height: 150px;
}
#barChart {
position:absolute;
top:160px;
left:410px;
height: 250px;
}
.slice {
font-size: 12pt;
font-family: Verdana;
fill: white; //svg specific - instead of color
font-weight: bold;
}
/*for line chart*/
.axis path, .axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges; //The shape-rendering property is an SVG attribute, used here to make sure our axis and its tick mark lines are pixel-perfect.
}
.line {
fill: none;
/*stroke: steelblue;*/
stroke-width: 3px;
}
.dot {
/*fill: white;*/
/*stroke: steelblue;*/
stroke-width: 1.5px;
}
.axis text {
font-family: Verdana;
font-size: 11px;
}
.title {
font-family: Verdana;
font-size: 15px;
}
.xAxis {
font-family: verdana;
font-size: 11px;
fill: black;
}
.yAxis {
font-family: verdana;
font-size: 11px;
fill: white;
}
table {
border-collapse:collapse;
border: 0px;
font-family: Verdana;
color: #5C5558;
font-size: 12px;
text-align: right;
}
td {
padding-left: 10px;
}
#lineChartTitle1 {
font-family: Verdana;
font-size : 14px;
fill : lightgrey;
font-weight: bold;
text-anchor: middle;
}
#lineChartTitle2 {
font-family: Verdana;
font-size : 72px;
fill : grey;
text-anchor: middle;
font-weight: bold;
/*font-style: italic;*/
}
</style>
</head>
<body>
<div id="pieChart"></div>
<div id="barChart"></div>
<div id="lineChart"></div>
<script type="text/javascript">
/*
################ FORMATS ##################
-------------------------------------------
*/
var formatAsPercentage = d3.format("%"),
formatAsPercentage1Dec = d3.format(".1%"),
formatAsInteger = d3.format(","),
fsec = d3.time.format("%S s"),
fmin = d3.time.format("%M m"),
fhou = d3.time.format("%H h"),
fwee = d3.time.format("%a"),
fdat = d3.time.format("%d d"),
fmon = d3.time.format("%b")
;
/*
############# PIE CHART ###################
-------------------------------------------
*/
function dsPieChart(){
var dataset = [
{category: "Sam", measure: 0.30},
{category: "Peter", measure: 0.25},
{category: "John", measure: 0.15},
{category: "Rick", measure: 0.05},
{category: "Lenny", measure: 0.18},
{category: "Paul", measure:0.04},
{category: "Steve", measure: 0.03}
]
;
var width = 400,
height = 400,
outerRadius = Math.min(width, height) / 2,
innerRadius = outerRadius * .999,
// for animation
innerRadiusFinal = outerRadius * .5,
innerRadiusFinal3 = outerRadius* .45,
color = d3.scale.category20() //builtin range of colors
;
var vis = d3.select("#pieChart")
.append("svg:svg") //create the SVG element inside the <body>
.data([dataset]) //associate our data with the document
.attr("width", width) //set the width and height of our visualization (these will be attributes of the <svg> tag
.attr("height", height)
.append("svg:g") //make a group to hold our pie chart
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")") //move the center of the pie chart from 0, 0 to radius, radius
;
var arc = d3.svg.arc() //this will create <path> elements for us using arc data
.outerRadius(outerRadius).innerRadius(innerRadius);
// for animation
var arcFinal = d3.svg.arc().innerRadius(innerRadiusFinal).outerRadius(outerRadius);
var arcFinal3 = d3.svg.arc().innerRadius(innerRadiusFinal3).outerRadius(outerRadius);
var pie = d3.layout.pie() //this will create arc data for us given a list of values
.value(function(d) { return d.measure; }); //we must tell it out to access the value of each element in our data array
var arcs = vis.selectAll("g.slice") //this selects all <g> elements with class slice (there aren't any yet)
.data(pie) //associate the generated pie data (an array of arcs, each having startAngle, endAngle and value properties)
.enter() //this will create <g> elements for every "extra" data element that should be associated with a selection. The result is creating a <g> for every object in the data array
.append("svg:g") //create a group to hold each slice (we will have a <path> and a <text> element associated with each slice)
.attr("class", "slice") //allow us to style things in the slices (like text)
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("click", up)
;
arcs.append("svg:path")
.attr("fill", function(d, i) { return color(i); } ) //set the color for each slice to be chosen from the color function defined above
.attr("d", arc) //this creates the actual SVG path using the associated data (pie) with the arc drawing function
.append("svg:title") //mouseover title showing the figures
.text(function(d) { return d.data.category + ": " + formatAsPercentage(d.data.measure); });
d3.selectAll("g.slice").selectAll("path").transition()
.duration(750)
.delay(10)
.attr("d", arcFinal )
;
// Add a label to the larger arcs, translated to the arc centroid and rotated.
// source: http://bl.ocks.org/1305337#index.html
arcs.filter(function(d) { return d.endAngle - d.startAngle > .2; })
.append("svg:text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.attr("transform", function(d) { return "translate(" + arcFinal.centroid(d) + ")rotate(" + angle(d) + ")"; })
//.text(function(d) { return formatAsPercentage(d.value); })
.text(function(d) { return d.data.category; })
;
// Computes the label angle of an arc, converting from radians to degrees.
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
// Pie chart title
vis.append("svg:text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text("Revenue Share 2012")
.attr("class","title")
;
function mouseover() {
d3.select(this).select("path").transition()
.duration(750)
//.attr("stroke","red")
//.attr("stroke-width", 1.5)
.attr("d", arcFinal3)
;
}
function mouseout() {
d3.select(this).select("path").transition()
.duration(750)
//.attr("stroke","blue")
//.attr("stroke-width", 1.5)
.attr("d", arcFinal)
;
}
function up(d, i) {
/* update bar chart when user selects piece of the pie chart */
//updateBarChart(dataset[i].category);
updateBarChart(d.data.category, color(i));
updateLineChart(d.data.category, color(i));
}
}
dsPieChart();
/*
############# BAR CHART ###################
-------------------------------------------
*/
var datasetBarChart = [
{ group: "All", category: "Oranges", measure: 63850.4963 },
{ group: "All", category: "Apples", measure: 78258.0845 },
{ group: "All", category: "Grapes", measure: 60610.2355 },
{ group: "All", category: "Figs", measure: 30493.1686 },
{ group: "All", category: "Mangos", measure: 56097.0151 },
{ group: "Sam", category: "Oranges", measure: 19441.5648 },
{ group: "Sam", category: "Apples", measure: 25922.0864 },
{ group: "Sam", category: "Grapes", measure: 9720.7824 },
{ group: "Sam", category: "Figs", measure: 6480.5216 },
{ group: "Sam", category: "Mangos", measure: 19441.5648 },
{ group: "Peter", category: "Oranges", measure: 22913.2728 },
{ group: "Peter", category: "Apples", measure: 7637.7576 },
{ group: "Peter", category: "Grapes", measure: 23549.7526 },
{ group: "Peter", category: "Figs", measure: 1909.4394 },
{ group: "Peter", category: "Mangos", measure: 7637.7576 },
{ group: "John", category: "Oranges", measure: 1041.5124 },
{ group: "John", category: "Apples", measure: 2430.1956 },
{ group: "John", category: "Grapes", measure: 15275.5152 },
{ group: "John", category: "Figs", measure: 4166.0496 },
{ group: "John", category: "Mangos", measure: 11803.8072 },
{ group: "Rick", category: "Oranges", measure: 7406.3104 },
{ group: "Rick", category: "Apples", measure: 2545.9192 },
{ group: "Rick", category: "Grapes", measure: 1620.1304 },
{ group: "Rick", category: "Figs", measure: 8563.5464 },
{ group: "Rick", category: "Mangos", measure: 3008.8136 },
{ group: "Lenny", category: "Oranges", measure: 7637.7576 },
{ group: "Lenny", category: "Apples", measure: 35411.4216 },
{ group: "Lenny", category: "Grapes", measure: 8332.0992 },
{ group: "Lenny", category: "Figs", measure: 6249.0744 },
{ group: "Lenny", category: "Mangos", measure: 11803.8072 },
{ group: "Paul", category: "Oranges", measure: 3182.399 },
{ group: "Paul", category: "Apples", measure: 867.927 },
{ group: "Paul", category: "Grapes", measure: 1808.18125 },
{ group: "Paul", category: "Figs", measure: 795.59975 },
{ group: "Paul", category: "Mangos", measure: 578.618 },
{ group: "Steve", category: "Oranges", measure: 2227.6793 },
{ group: "Steve", category: "Apples", measure: 3442.7771 },
{ group: "Steve", category: "Grapes", measure: 303.77445 },
{ group: "Steve", category: "Figs", measure: 2328.93745 },
{ group: "Steve", category: "Mangos", measure: 1822.6467 },
]
;
// set initial group value
var group = "All";
function datasetBarChosen(group) {
var ds = [];
for (x in datasetBarChart) {
if(datasetBarChart[x].group==group){
ds.push(datasetBarChart[x]);
}
}
return ds;
}
function dsBarChartBasics() {
var margin = {top: 30, right: 5, bottom: 20, left: 50},
width = 500 - margin.left - margin.right,
height = 250 - margin.top - margin.bottom,
colorBar = d3.scale.category20(),
barPadding = 1
;
return {
margin : margin,
width : width,
height : height,
colorBar : colorBar,
barPadding : barPadding
}
;
}
function dsBarChart() {
var firstDatasetBarChart = datasetBarChosen(group);
var basics = dsBarChartBasics();
var margin = basics.margin,
width = basics.width,
height = basics.height,
colorBar = basics.colorBar,
barPadding = basics.barPadding
;
var xScale = d3.scale.linear()
.domain([0, firstDatasetBarChart.length])
.range([0, width])
;
// Create linear y scale
// Purpose: No matter what the data is, the bar should fit into the svg area; bars should not
// get higher than the svg height. Hence incoming data needs to be scaled to fit into the svg area.
var yScale = d3.scale.linear()
// use the max funtion to derive end point of the domain (max value of the dataset)
// do not use the min value of the dataset as min of the domain as otherwise you will not see the first bar
.domain([0, d3.max(firstDatasetBarChart, function(d) { return d.measure; })])
// As coordinates are always defined from the top left corner, the y position of the bar
// is the svg height minus the data value. So you basically draw the bar starting from the top.
// To have the y position calculated by the range function
.range([height, 0])
;
//Create SVG element
var svg = d3.select("#barChart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("id","barChartPlot")
;
var plot = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
;
plot.selectAll("rect")
.data(firstDatasetBarChart)
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(i);
})
.attr("width", width / firstDatasetBarChart.length - barPadding)
.attr("y", function(d) {
return yScale(d.measure);
})
.attr("height", function(d) {
return height-yScale(d.measure);
})
.attr("fill", "lightgrey")
;
// Add y labels to plot
plot.selectAll("text")
.data(firstDatasetBarChart)
.enter()
.append("text")
.text(function(d) {
return formatAsInteger(d3.round(d.measure));
})
.attr("text-anchor", "middle")
// Set x position to the left edge of each bar plus half the bar width
.attr("x", function(d, i) {
return (i * (width / firstDatasetBarChart.length)) + ((width / firstDatasetBarChart.length - barPadding) / 2);
})
.attr("y", function(d) {
return yScale(d.measure) + 14;
})
.attr("class", "yAxis")
/* moved to CSS
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white")
*/
;
// Add x labels to chart
var xLabels = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + (margin.top + height) + ")")
;
xLabels.selectAll("text.xAxis")
.data(firstDatasetBarChart)
.enter()
.append("text")
.text(function(d) { return d.category;})
.attr("text-anchor", "middle")
// Set x position to the left edge of each bar plus half the bar width
.attr("x", function(d, i) {
return (i * (width / firstDatasetBarChart.length)) + ((width / firstDatasetBarChart.length - barPadding) / 2);
})
.attr("y", 15)
.attr("class", "xAxis")
//.attr("style", "font-size: 12; font-family: Helvetica, sans-serif")
;
// Title
svg.append("text")
.attr("x", (width + margin.left + margin.right)/2)
.attr("y", 15)
.attr("class","title")
.attr("text-anchor", "middle")
.text("Overall Sales Breakdown 2012")
;
}
dsBarChart();
/* ** UPDATE CHART ** */
/* updates bar chart on request */
function updateBarChart(group, colorChosen) {
var currentDatasetBarChart = datasetBarChosen(group);
var basics = dsBarChartBasics();
var margin = basics.margin,
width = basics.width,
height = basics.height,
colorBar = basics.colorBar,
barPadding = basics.barPadding
;
var xScale = d3.scale.linear()
.domain([0, currentDatasetBarChart.length])
.range([0, width])
;
var yScale = d3.scale.linear()
.domain([0, d3.max(currentDatasetBarChart, function(d) { return d.measure; })])
.range([height,0])
;
var svg = d3.select("#barChart svg");
var plot = d3.select("#barChartPlot")
.datum(currentDatasetBarChart)
;
/* Note that here we only have to select the elements - no more appending! */
plot.selectAll("rect")
.data(currentDatasetBarChart)
.transition()
.duration(750)
.attr("x", function(d, i) {
return xScale(i);
})
.attr("width", width / currentDatasetBarChart.length - barPadding)
.attr("y", function(d) {
return yScale(d.measure);
})
.attr("height", function(d) {
return height-yScale(d.measure);
})
.attr("fill", colorChosen)
;
plot.selectAll("text.yAxis") // target the text element(s) which has a yAxis class defined
.data(currentDatasetBarChart)
.transition()
.duration(750)
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return (i * (width / currentDatasetBarChart.length)) + ((width / currentDatasetBarChart.length - barPadding) / 2);
})
.attr("y", function(d) {
return yScale(d.measure) + 14;
})
.text(function(d) {
return formatAsInteger(d3.round(d.measure));
})
.attr("class", "yAxis")
;
svg.selectAll("text.title") // target the text element(s) which has a title class defined
.attr("x", (width + margin.left + margin.right)/2)
.attr("y", 15)
.attr("class","title")
.attr("text-anchor", "middle")
.text(group + "'s Sales Breakdown 2012")
;
}
/*
############# LINE CHART ##################
-------------------------------------------
*/
var datasetLineChart = [
{ group: "All", category: 2008, measure: 289309 },
{ group: "All", category: 2009, measure: 234998 },
{ group: "All", category: 2010, measure: 310900 },
{ group: "All", category: 2011, measure: 223900 },
{ group: "All", category: 2012, measure: 234500 },
{ group: "Sam", category: 2008, measure: 81006.52 },
{ group: "Sam", category: 2009, measure: 70499.4 },
{ group: "Sam", category: 2010, measure: 96379 },
{ group: "Sam", category: 2011, measure: 64931 },
{ group: "Sam", category: 2012, measure: 70350 },
{ group: "Peter", category: 2008, measure: 63647.98 },
{ group: "Peter", category: 2009, measure: 61099.48 },
{ group: "Peter", category: 2010, measure: 87052 },
{ group: "Peter", category: 2011, measure: 58214 },
{ group: "Peter", category: 2012, measure: 58625 },
{ group: "Rick", category: 2008, measure: 23144.72 },
{ group: "Rick", category: 2009, measure: 14099.88 },
{ group: "Rick", category: 2010, measure: 15545 },
{ group: "Rick", category: 2011, measure: 11195 },
{ group: "Rick", category: 2012, measure: 11725 },
{ group: "John", category: 2008, measure: 34717.08 },
{ group: "John", category: 2009, measure: 30549.74 },
{ group: "John", category: 2010, measure: 34199 },
{ group: "John", category: 2011, measure: 33585 },
{ group: "John", category: 2012, measure: 35175 },
{ group: "Lenny", category: 2008, measure: 69434.16 },
{ group: "Lenny", category: 2009, measure: 46999.6 },
{ group: "Lenny", category: 2010, measure: 62180 },
{ group: "Lenny", category: 2011, measure: 40302 },
{ group: "Lenny", category: 2012, measure: 42210 },
{ group: "Paul", category: 2008, measure: 7232.725 },
{ group: "Paul", category: 2009, measure: 4699.96 },
{ group: "Paul", category: 2010, measure: 6218 },
{ group: "Paul", category: 2011, measure: 8956 },
{ group: "Paul", category: 2012, measure: 9380 },
{ group: "Steve", category: 2008, measure: 10125.815 },
{ group: "Steve", category: 2009, measure: 7049.94 },
{ group: "Steve", category: 2010, measure: 9327 },
{ group: "Steve", category: 2011, measure: 6717 },
{ group: "Steve", category: 2012, measure: 7035 }
]
;
// set initial category value
var group = "All";
function datasetLineChartChosen(group) {
var ds = [];
for (x in datasetLineChart) {
if(datasetLineChart[x].group==group){
ds.push(datasetLineChart[x]);
}
}
return ds;
}
function dsLineChartBasics() {
var margin = {top: 20, right: 10, bottom: 0, left: 50},
width = 500 - margin.left - margin.right,
height = 150 - margin.top - margin.bottom
;
return {
margin : margin,
width : width,
height : height
}
;
}
function dsLineChart() {
var firstDatasetLineChart = datasetLineChartChosen(group);
var basics = dsLineChartBasics();
var margin = basics.margin,
width = basics.width,
height = basics.height
;
var xScale = d3.scale.linear()
.domain([0, firstDatasetLineChart.length-1])
.range([0, width])
;
var yScale = d3.scale.linear()
.domain([0, d3.max(firstDatasetLineChart, function(d) { return d.measure; })])
.range([height, 0])
;
var line = d3.svg.line()
//.x(function(d) { return xScale(d.category); })
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d.measure); })
;
var svg = d3.select("#lineChart").append("svg")
.datum(firstDatasetLineChart)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
// create group and move it so that margins are respected (space for axis and title)
var plot = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("id", "lineChartPlot")
;
/* descriptive titles as part of plot -- start */
var dsLength=firstDatasetLineChart.length;
plot.append("text")
.text(firstDatasetLineChart[dsLength-1].measure)
.attr("id","lineChartTitle2")
.attr("x",width/2)
.attr("y",height/2)
;
/* descriptive titles -- end */
plot.append("path")
.attr("class", "line")
.attr("d", line)
// add color
.attr("stroke", "lightgrey")
;
plot.selectAll(".dot")
.data(firstDatasetLineChart)
.enter().append("circle")
.attr("class", "dot")
//.attr("stroke", function (d) { return d.measure==datasetMeasureMin ? "red" : (d.measure==datasetMeasureMax ? "green" : "steelblue") } )
.attr("fill", function (d) { return d.measure==d3.min(firstDatasetLineChart, function(d) { return d.measure; }) ? "red" : (d.measure==d3.max(firstDatasetLineChart, function(d) { return d.measure; }) ? "green" : "white") } )
//.attr("stroke-width", function (d) { return d.measure==datasetMeasureMin || d.measure==datasetMeasureMax ? "3px" : "1.5px"} )
.attr("cx", line.x())
.attr("cy", line.y())
.attr("r", 3.5)
.attr("stroke", "lightgrey")
.append("title")
.text(function(d) { return d.category + ": " + formatAsInteger(d.measure); })
;
svg.append("text")
.text("Performance 2012")
.attr("id","lineChartTitle1")
.attr("x",margin.left + ((width + margin.right)/2))
.attr("y", 10)
;
}
dsLineChart();
/* ** UPDATE CHART ** */
/* updates bar chart on request */
function updateLineChart(group, colorChosen) {
var currentDatasetLineChart = datasetLineChartChosen(group);
var basics = dsLineChartBasics();
var margin = basics.margin,
width = basics.width,
height = basics.height
;
var xScale = d3.scale.linear()
.domain([0, currentDatasetLineChart.length-1])
.range([0, width])
;
var yScale = d3.scale.linear()
.domain([0, d3.max(currentDatasetLineChart, function(d) { return d.measure; })])
.range([height, 0])
;
var line = d3.svg.line()
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d.measure); })
;
var plot = d3.select("#lineChartPlot")
.datum(currentDatasetLineChart)
;
/* descriptive titles as part of plot -- start */
var dsLength=currentDatasetLineChart.length;
plot.select("text")
.text(currentDatasetLineChart[dsLength-1].measure)
;
/* descriptive titles -- end */
plot
.select("path")
.transition()
.duration(750)
.attr("class", "line")
.attr("d", line)
// add color
.attr("stroke", colorChosen)
;
var path = plot
.selectAll(".dot")
.data(currentDatasetLineChart)
.transition()
.duration(750)
.attr("class", "dot")
.attr("fill", function (d) { return d.measure==d3.min(currentDatasetLineChart, function(d) { return d.measure; }) ? "red" : (d.measure==d3.max(currentDatasetLineChart, function(d) { return d.measure; }) ? "green" : "white") } )
.attr("cx", line.x())
.attr("cy", line.y())
.attr("r", 3.5)
// add color
.attr("stroke", colorChosen)
;
path
.selectAll("title")
.text(function(d) { return d.category + ": " + formatAsInteger(d.measure); })
;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment