|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>Household monthly electricity consumption</title> |
|
<style> |
|
body { |
|
font: 12px sans-serif; |
|
} |
|
|
|
svg { |
|
margin: 0px auto; |
|
display: block; |
|
} |
|
|
|
path.arc { |
|
opacity: 0.9; |
|
transition: opacity 0.5s; |
|
} |
|
|
|
path.arc:hover { |
|
opacity: 0.7; |
|
} |
|
|
|
.axis line, .axis circle { |
|
stroke: #cccccc; |
|
stroke-width: 1px |
|
} |
|
|
|
.axis circle { |
|
fill: none; |
|
} |
|
|
|
.r.axis text { |
|
text-anchor: end |
|
} |
|
|
|
.tooltip { |
|
position: absolute; |
|
display: none; |
|
background: rgba(0, 0, 0, 0.6); |
|
border-radius: 3px; |
|
box-shadow: -3px 3px 15px #888; |
|
color: white; |
|
padding: 6px; |
|
} |
|
#radia button { |
|
background-color:#f2f2f2; |
|
text-align:center; |
|
border-radius: 5px; |
|
font-size: 20px; |
|
font-weight: bold; |
|
} |
|
#radial button:hover { |
|
background-color: #b3b3b3; |
|
} |
|
</style> |
|
<script src="https://d3js.org/d3.v4.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-scale-chromatic.v1.min.js"></script> |
|
</head> |
|
<body> |
|
<p> |
|
<div align = "right"> |
|
|
|
</div> |
|
</p> |
|
<div id="radial"> |
|
<p> |
|
Click to toggle between <b>Revenue</b> and <b>Landings</b> data by decade: <button>Change Data</button> <br> Dollars Adjusted to 2016 inflation |
|
</p> |
|
<div id="radialSvg"> |
|
</div> |
|
</div> |
|
<script type="text/javascript" src="js/d3-tip.js"></script> |
|
<script type="text/javascript"> |
|
//JS Object used to switch between data using a simple button |
|
function dataSwitcherConstructor(datatype) { |
|
this.currentData = datatype; |
|
dataswitch(this.currentData); |
|
} |
|
//load data |
|
var datatype = "revenue"; |
|
var dataSwitcher = new dataSwitcherConstructor(datatype); |
|
//console.log(dataSwitcher); |
|
|
|
/* const width = 960, |
|
height = 500, |
|
chartRadius = height / 2 - 40; |
|
*/ |
|
const color1 = d3.interpolate("#003718","#00662c"); |
|
const color2 = d3.interpolate("#002d38","#005666"); |
|
|
|
|
|
/*let svg = d3.select('body').append('svg') |
|
.attr('width', width) |
|
.attr('height', height) |
|
.append('g') |
|
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); |
|
*/ |
|
let tooltip = d3.select('body').append('div') |
|
.attr('class', 'tooltip'); |
|
|
|
const PI = Math.PI, |
|
arcMinRadius = 10, |
|
arcPadding = 10, |
|
labelPadding = -5, |
|
numTicks = 10; |
|
|
|
d3.select("#radial button").on("click", function(){ |
|
if (datatype=="revenue") |
|
datatype = "landings"; |
|
else |
|
datatype = "revenue"; |
|
dataSwitcher = new dataSwitcherConstructor(datatype); |
|
//console.log(datatype) |
|
}); |
|
function dataswitch(datatype){ |
|
const width = 960, |
|
height = 500, |
|
chartRadius = height / 2 - 40; |
|
d3.select("svg").remove(); |
|
let svg = d3.select('body').append('svg') |
|
.attr('width', width) |
|
.attr('height', height) |
|
.append('g') |
|
.attr('transform', 'translate(' + width / 2 + ',' + height / 2.18 + ')'); |
|
|
|
d3.csv('Oyster.csv', (error, data) => { |
|
if(datatype == "revenue"){ |
|
let scale = d3.scaleLinear() |
|
.domain([0, d3.max(data, d => +d.AdjustedRevenue) * 1.1]) |
|
.range([0, 2 * PI]); |
|
|
|
let ticks = scale.ticks(numTicks).slice(0, -1); |
|
let keys = data.map((d, i) => d.Decade); |
|
//console.log(keys) |
|
//number of arcs |
|
const numArcs = keys.length; |
|
const arcWidth = (chartRadius - arcMinRadius - numArcs * arcPadding) / numArcs; |
|
let arc = d3.arc() |
|
.innerRadius((d, i) => getInnerRadius(i)) |
|
.outerRadius((d, i) => getOuterRadius(i)) |
|
.startAngle(0) |
|
.endAngle((d, i) => scale(d)) |
|
|
|
let radialAxis = svg.append('g') |
|
.attr('class', 'r axis') |
|
.selectAll('g') |
|
.data(data) |
|
.enter().append('g'); |
|
|
|
radialAxis.append('circle') |
|
.attr('r', (d, i) => getOuterRadius(i) + arcPadding); |
|
|
|
radialAxis.append('text') |
|
.attr('x', labelPadding) |
|
.attr('y', (d, i) => -getOuterRadius(i) + arcPadding) |
|
.text(d => d.Decade); |
|
|
|
let axialAxis = svg.append('g') |
|
.attr('class', 'a axis') |
|
.selectAll('g') |
|
.data(ticks) |
|
.enter().append('g') |
|
.attr('transform', d => 'rotate(' + (rad2deg(scale(d)) - 90) + ')'); |
|
|
|
axialAxis.append('line') |
|
.attr('x2', chartRadius); |
|
|
|
axialAxis.append('text') |
|
.attr('x', chartRadius + 10) |
|
.style('text-anchor', d => (scale(d) >= PI && scale(d) < 2 * PI ? 'end' : null)) |
|
.attr('transform', d => 'rotate(' + (90 - rad2deg(scale(d))) + ',' + (chartRadius + 10) + ',0)') |
|
.text(d => d); |
|
|
|
//data arcs |
|
let arcs = svg.append('g') |
|
.attr('class', 'data') |
|
.selectAll('path') |
|
.data(data) |
|
.enter().append('path') |
|
.attr('class', 'arc') |
|
.style('fill', (d, i) => color1(i)) |
|
console.log(data) |
|
arcs.transition() |
|
.delay((d, i) => i * 200) |
|
.duration(1000) |
|
.attrTween('d', arcTween); |
|
|
|
arcs.on('mousemove', showTooltip) |
|
arcs.on('mouseout', hideTooltip) |
|
|
|
svg.append("text") |
|
.text("Data Shown:") |
|
.attr("y",-200) |
|
.attr("x",250) |
|
.attr("font-size", 20) |
|
.attr("font-family", "monospace") |
|
|
|
svg.append("text") |
|
.text("Revenue") |
|
.attr("y",-200) |
|
.attr("x",375) |
|
.attr("font-size", 20) |
|
.attr("font-family", "monospace") |
|
|
|
function arcTween(d, i) { |
|
let interpolate = d3.interpolate(0, +d.AdjustedRevenue); |
|
return t => arc(interpolate(t), i); |
|
|
|
} |
|
|
|
function showTooltip(d) { |
|
tooltip.style('left', (d3.event.pageX + 10) + 'px') |
|
.style('top', (d3.event.pageY - 25) + 'px') |
|
.style('display', 'inline-block') |
|
.html("$"+d.AdjustedRevenue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "<br>" + " Decline since 1950: " +(100-((d.AdjustedRevenue/data[0].AdjustedRevenue)*100)) |
|
) |
|
|
|
} |
|
|
|
function hideTooltip() { |
|
tooltip.style('display', 'none'); |
|
} |
|
|
|
function rad2deg(angle) { |
|
return angle * 180 / PI; |
|
} |
|
|
|
function getInnerRadius(index) { |
|
return arcMinRadius + (numArcs - (index + 1)) * (arcWidth + arcPadding); |
|
} |
|
|
|
function getOuterRadius(index) { |
|
return getInnerRadius(index) + arcWidth; |
|
} |
|
} |
|
//Landings data |
|
else if(datatype == "landings"){ |
|
let scale = d3.scaleLinear() |
|
.domain([0, d3.max(data, d => +d.MetricTonnage) * 1.1]) |
|
.range([0, 2 * PI]); |
|
|
|
svg.append("text") |
|
.text("Data Shown:") |
|
.attr("y",-200) |
|
.attr("x",250) |
|
.attr("font-size", 20) |
|
.attr("font-family", "monospace") |
|
|
|
svg.append("text") |
|
.text("Landings") |
|
.attr("y",-200) |
|
.attr("x",375) |
|
.attr("font-size", 20) |
|
.attr("font-family", "monospace") |
|
|
|
let ticks = scale.ticks(numTicks).slice(0, -1); |
|
let keys = data.map((d, i) => d.Decade); |
|
//console.log(keys) |
|
//number of arcs |
|
const numArcs = keys.length; |
|
const arcWidth = (chartRadius - arcMinRadius - numArcs * arcPadding) / numArcs; |
|
let arc = d3.arc() |
|
.innerRadius((d, i) => getInnerRadius(i)) |
|
.outerRadius((d, i) => getOuterRadius(i)) |
|
.startAngle(0) |
|
.endAngle((d, i) => scale(d)) |
|
|
|
let radialAxis = svg.append('g') |
|
.attr('class', 'r axis') |
|
.selectAll('g') |
|
.data(data) |
|
.enter().append('g'); |
|
|
|
radialAxis.append('circle') |
|
.attr('r', (d, i) => getOuterRadius(i) + arcPadding); |
|
|
|
radialAxis.append('text') |
|
.attr('x', labelPadding) |
|
.attr('y', (d, i) => -getOuterRadius(i) + arcPadding) |
|
.text(d => d.Decade); |
|
|
|
let axialAxis = svg.append('g') |
|
.attr('class', 'a axis') |
|
.selectAll('g') |
|
.data(ticks) |
|
.enter().append('g') |
|
.attr('transform', d => 'rotate(' + (rad2deg(scale(d)) - 90) + ')'); |
|
|
|
axialAxis.append('line') |
|
.attr('x2', chartRadius); |
|
|
|
axialAxis.append('text') |
|
.attr('x', chartRadius + 10) |
|
.style('text-anchor', d => (scale(d) >= PI && scale(d) < 2 * PI ? 'end' : null)) |
|
.attr('transform', d => 'rotate(' + (90 - rad2deg(scale(d))) + ',' + (chartRadius + 10) + ',0)') |
|
.text(d => d); |
|
|
|
//data arcs |
|
let arcs = svg.append('g') |
|
.attr('class', 'data') |
|
.selectAll('path') |
|
.data(data) |
|
.enter().append('path') |
|
.attr('class', 'arc') |
|
.style('fill', (d, i) => color2(i)) |
|
|
|
arcs.transition() |
|
.delay((d, i) => i * 200) |
|
.duration(1000) |
|
.attrTween('d', arcTween); |
|
|
|
arcs.on('mousemove', showTooltip) |
|
arcs.on('mouseout', hideTooltip) |
|
|
|
|
|
function arcTween(d, i) { |
|
let interpolate = d3.interpolate(0, +d.MetricTonnage); |
|
return t => arc(interpolate(t), i); |
|
|
|
} |
|
|
|
function showTooltip(d) { |
|
tooltip.style('left', (d3.event.pageX + 10) + 'px') |
|
.style('top', (d3.event.pageY - 25) + 'px') |
|
.style('display', 'inline-block') |
|
.html(d.MetricTonnage.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " Metric Tons"+ "<br> Decline since 1950: " ) |
|
|
|
} |
|
|
|
function hideTooltip() { |
|
tooltip.style('display', 'none'); |
|
} |
|
|
|
function rad2deg(angle) { |
|
return angle * 180 / PI; |
|
} |
|
|
|
function getInnerRadius(index) { |
|
return arcMinRadius + (numArcs - (index + 1)) * (arcWidth + arcPadding); |
|
} |
|
|
|
function getOuterRadius(index) { |
|
return getInnerRadius(index) + arcWidth; |
|
} |
|
} |
|
}) |
|
} |
|
|
|
|
|
|
|
</script> |
|
</body> |
|
</html> |