forked from jadiehm's block: Line area chart with swoopy drag annotations
xxxxxxxxxx
<html lang='en-GB'>
<head>
<meta charset='utf-8'>
</head>
<style>
body {
font-family: sans-serif;;
font-size: 16px;
line-height: 1.4;
display: block;
margin: 0;
padding: 0;
color: #333;
-webkit-font-smoothing: antialiased;
}
p {
font-family: sans-serif;
font-size: 14px;
margin: 5px 0 0 0;
}
/*template styles*/
.gia-chart-wrapper {
max-width: 960px;
margin: 0 auto;
}
/*chart styles*/
.y.axis line {
fill: none;
stroke: #dcdcdc;
stroke-dasharray: 1px 1px;
shape-rendering: crispEdges;
stroke-width: 1px;
}
.x.axis line {
fill: none;
stroke: #333333;
shape-rendering: crispEdges;
stroke-width: 1px;
}
.tick.g-baseline line {
stroke: #333333;
stroke-dasharray: 0;
stroke-width: 1px;
}
.axis text {
font-family: sans-serif;
font-size: 12px;
pointer-events: none;
fill: #bdbdbd;
}
.y.axis text {
text-anchor: end !important;
font-size:12px;
fill: #bdbdbd;
}
.domain {
display: none;
}
.line {
stroke: #4bc6df;
stroke-width: 2px;
fill: none;
}
.area {
fill: #4bc6df;
opacity: 0.1;
}
.g-label-circle {
fill: #4bc6df;
}
.g-label-text, .g-label-text-bold {
font-family: sans-serif;
font-size: 14px;
text-align: left;
}
.g-label-text-bold {
font-weight: 700;
}
.annotations path{
fill: none;
stroke: black;
}
.annotations g:hover circle{
stroke: red;
}
.annotations g:hover text{
fill: red;
}
.swoopy-drag-lines path {
fill: none;
stroke: #333333;
}
.swoopy-drag-lines text {
font-family: sans-serif;
font-size: 14px;
text-align: left;
fill: #333333;
}
.swoopy-drag-lines tspan:first-child {
font-weight: 700;
}
@media (max-width: 575px) {
.label-group1, .label-group3, .label-group4, .label-group5 {
display: none;
}
}
@media (max-width: 475px) {
.label-group1, .label-group2, .label-group3, .label-group4, .label-group5 {
display: none;
}
}
@media (max-width: 375px) {
.label-group1, .label-group2, .label-group3, .label-group4, .label-group5, .label-group6, .label-group7 {
display: none;
}
}
</style>
<body>
<main>
<div class='gia-chart-wrapper'>
<div class='gia-chart'>
</div>
</div>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<script src='d3-jetpack.js'></script>
<script src='swoopy-drag.js'></script>
<script>
//Margin conventions
var margin = {top: 50, right: 5, bottom: 30, left: 25};
var widther = d3.select(".gia-chart").node().clientWidth;
var width = widther - margin.left - margin.right,
height = 430 - margin.top - margin.bottom;
//Parses date for correct time format
var parseDate = d3.time.format("%e-%b-%y").parse;
var monthArr = ['Jan.', 'Feb.', 'March', 'Apr.', 'May', 'June', 'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.'];
//Appends the svg to the chart-container div
var svg = d3.select(".gia-chart").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 + ")");
//Creates the xScale
var xScale = d3.time.scale()
.range([0, width]);
//Creates the yScale
var yScale = d3.scale.linear()
.range([height, 0]);
//Defines the y axis styles
var yAxis = d3.svg.axis()
.scale(yScale)
.tickSize(-width)
.tickPadding(8)
.orient("left");
//Defines the y axis styles
var xAxis = d3.svg.axis()
.scale(xScale)
.tickPadding(8)
.orient("bottom")
.ticks(6)
.tickFormat(d3.time.format("%Y"));
//line function convention (feeds an array)
var line = d3.svg.line()
.x(function(d) { return xScale(d.date); })
.y(function(d) { return yScale(d.close); });
//area function
var area = d3.svg.area()
.x(function(d) {return xScale(d.date); })
.y0(height)
.y1(function(d) {return yScale(d.close); });
//Loads the data
d3.csv("swhc.csv", ready);
function ready(err, data) {
if (err) throw "error loading data";
//FORMAT data
data.forEach(function(d) {
d.close = +d.close;
d.date = parseDate(d.date);
});
//Organizes the data
data.sort(function(a,b) { return a.date - b.date; });
var maxY = d3.max(data, function(d) { return d.close; });
//Defines the xScale max
xScale.domain(d3.extent(data, function(d) { return d.date; }));
//Defines the yScale max
yScale.domain([0, 30]);
//Appends the y axis
var yAxisGroup = svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.selectAll("g")
.classed("g-baseline", function(d) {return d == 0});
//Appends the x axis
var xAxisGroup = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
//Binds the data to the line
var drawarea = svg.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
//Binds the data to the line
var drawline = svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
//Adding labels
var labelElements = svg.append("g")
.attr("class", "fiddly-bits")
var label = labelElements.selectAll(".g-label-element")
.data(data.filter(function(d) { return d.event == "yes"; }))
.enter().append("g")
.attr("class", "g-label-element")
.attr("transform", function(d) { return "translate(" + xScale(d.date) + "," + yScale(d.close) + ")"; } );
label.append("circle")
.attr("r", 3)
.attr("class", "g-label-circle");
/*
label.append("text")
.attr("x", 0)
.attr("y", function(d) {
if (d.position == "down") { return 30; }
else { return -26; }
})
.text(function(d) { return monthArr[d.date.getMonth()] + " " + d.date.getDate() + ", " + d.date.getFullYear() ; })
.style("text-anchor","end")
.attr("class", "g-label-text-bold");
label.append("text")
.attr("x", 0)
.attr("y", function(d) {
if (d.position == "down") { return 46; }
else { return -10; }
})
.text(function(d) { return d.desc_info; })
.style("text-anchor","end")
.attr("class", "g-label-text");
*/
//Swoopy-drag
var annotations = [
{
"xVal": 1467864000000,
"yVal": 28.04,
"path": "M0,-36L0,-9",
"text": "July 7, 2016 Dallas police shooting",
"textOffset": [
-76,
-61
]
},
{
"xVal": 1465704000000,
"yVal": 22.5,
"path": "M-113,-81C-62,-103,-6,-89,-1,-11",
"text": "June 12, 2016 Orlando nightclub shooting",
"textOffset": [
-172,
-67
]
},
{
"xVal": 1449032400000,
"yVal": 18.18,
"path": "M0,60L0,3",
"text": "Dec. 2, 2015 San Bernardino terrorist attack",
"textOffset": [
-23,
80
]
},
{
"xVal": 1434513600000,
"yVal": 15.75,
"path": "M0,85L0,5",
"text": "June 17, 2015 Charleston church shooting",
"textOffset": [
-58,
102
]
},
{
"xVal": 1403928000000,
"yVal": 13.55,
"path": "M50,-67C14,-65,0,-34,14,-6",
"text": "July 28, 2014 S&W charged with bribing foreign officials",
"textOffset": [
53,
-93
]
},
{
"xVal": 1400817600000,
"yVal": 15.08,
"path": "M-80,-92C-27,-93,9,-58,-1,-8",
"text": "May 23, 2014 Isla Vista shooting",
"textOffset": [
-144,
-117
]
},
{
"xVal": 1379304000000,
"yVal": 10.94,
"path": "M0,41L0,4",
"text": "Sept. 16, 2013 Washington, DC Navy Yard shooting",
"textOffset": [
-25,
57
]
},
{
"xVal": 1355461200000,
"yVal": 9.05,
"path": "M-20,-79C13,-66,27,-27,3,-7",
"text": "Dec. 14, 2012 Sandy Hook school shooting",
"textOffset": [
-71,
-102
]
}
]
var swoopy = d3.swoopyDrag()
.x(function(d){ return xScale(d.xVal) })
.y(function(d){ return yScale(d.yVal) })
.draggable(false)
.annotations(annotations)
var swoopySel = svg.append('g').call(swoopy)
.attr("class", "swoopy-drag-lines");
swoopySel.selectAll('text')
.each(function(d){
d3.select(this)
.text('') //clear existing text
.tspans(d3.wordwrap(d.text, 12)) //wrap after 20 char
});
swoopySel.selectAll('g')
.attr("class", function(d, i) {
return 'label-group'+i;
});
//RESPONSIVENESS
d3.select(window).on("resize", resized);
function resized() {
//new margin
var newMargin = {top: 30, right: 5, bottom: 30, left: 25};
var newWidther = d3.select(".gia-chart").node().clientWidth;
var newWidth = newWidther - newMargin.left - newMargin.right;
//Change the width of the svg
d3.select("svg")
.attr("width", newWidth + newMargin.left + newMargin.right);
//Change the xScale
xScale
.range([0, newWidth]);
//Update the line
line = d3.svg.line()
.x(function(d) { return xScale(d.date); })
.y(function(d) { return yScale(d.close); });
d3.selectAll('.line')
.attr("d", line);
//Updates circle labels
d3.selectAll('.g-label-element')
.attr("transform", function(d) { return "translate(" + xScale(d.date) + "," + yScale(d.close) + ")"; } );
//Update the area
area = d3.svg.area()
.x(function(d) {return xScale(d.date); })
.y0(height)
.y1(function(d) {return yScale(d.close); });
d3.selectAll('.area')
.attr("d", area);
//Updates xAxis
d3.selectAll(".x.axis")
.call(xAxis);
//Updates ticks
xAxis
.scale(xScale);
//Updates yAxis
d3.selectAll(".y.axis")
.call(yAxis);
yAxis
.tickSize(-newWidth);
swoopySel.remove();
swoopySel = svg.append('g').call(swoopy)
.attr("class", "swoopy-drag-lines");
swoopySel.selectAll('g')
.attr("class", function(d, i) {
return 'label-group'+i;
});
swoopySel.selectAll('text')
.each(function(d){
d3.select(this)
.text('') //clear existing text
.tspans(d3.wordwrap(d.text, 12)) //wrap after 20 char
})
};
}
</script>
</body>
</html>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js