Built with blockbuilder.org
forked from davidgutierrez's block: Vertical Zoom
forked from Saminu's block: Vertical Zoom
xxxxxxxxxx
<!-- adapted from mbostock v4 area brush https://bl.ocks.org/rajvansia/ce6903fad978d20773c41ee34bf6735c-->
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Merriweather" rel="stylesheet">
<style>
body {
font-family: 'Merriweather', serif;
}
a {
color: white;
}
div.tooltip {
position: absolute;
text-align: center;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
}
</style>
<body>
<h1>Data Breaches</h1>
<svg width="1000" height="800"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 60, right: 350, bottom: 110, left: 100},
margin2 = {top: 60, right: 590, bottom: 100, left: 330},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
width2 = +svg.attr("width") - margin2.left - margin2.right;
var parseTime = d3.timeParse("%Y");
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([7, width2]),
y = d3.scaleLinear().range([1,height-10]),
y2 = y.copy();
var xAxis = d3.axisTop(x),
yAxis = d3.axisLeft(y);
var force = d3.forceManyBody()
.strength(10);
var simulation = d3.forceSimulation()
.force("charge", force)
var brush = d3.brushY()
.extent([[0, 0], [width2, height]])
.on("brush", brushed);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + 20 + "," + 58 + ")");
d3.csv("Data_Breaches.csv", type, function(error, data) {
if (error) throw error;
x.domain(d3.extent(data, function(d) { return d.Year; }));
y.domain([d3.min(data, function(d) { return d.RecordsStolen; }), d3.max(data, function(d) { return d.RecordsStolen; })]);
x2.domain(x.domain());
y2.domain(y.domain());
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// set the colour scale
var color = d3.scaleOrdinal(d3.schemeCategory20);
// append scatter plot to main chart area
var dots = focus.append("g");
dots.attr("clip-path", "url(#clip)");
dots.selectAll("dot")
.data(data)
.enter()
.append("circle")
.attr('class', 'dot')
.attr("r",3)
.style("opacity", .7)
.attr("cx", function(d) { return x(d.Year); })
.attr("cy", function(d) { return y(d.RecordsStolen); })
.style("fill", function(d) { return color(d.MethodOfLeak); })
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("background-color", color(d.MethodOfLeak) )
.style("opacity", .9);
div .html(
'<a href= "'+d.Source+'" target="_blank">' + //with a link
d.Entity +
"</a>" +
"<br/>" + numberWithCommas(d.RecordsStolen)+
"<br/>" + d.MethodOfLeak)
.style("left", (d3.event.pageX+10) + "px")
.style("top", (d3.event.pageY - 28) + "px");
});
focus.append("g")
.attr("class", "axis axis--x")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
focus.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Records Stolen");
svg.append("text")
.attr("transform",
"translate(" + ((width + margin.right + margin.left)/2) + " ," + 30 + ")")
.style("text-anchor", "middle")
.text("Year");
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, y2.range());
// draw legend
var legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(120,"+height/2+")");
var legendItem = legend.selectAll(".legendItem")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(220," + i * 20 + ")"; });
// draw legend colored rectangles
legendItem.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
// draw legendItem text
legendItem.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d;})
});
//create brush function redraw scatterplot with selection
function brushed() {
var selection = d3.event.selection;
y.domain(selection.map(y2.invert, y));
focus.selectAll(".dot")
.attr("cx", function(d) { return x(d.Year); })
.attr("cy", function(d) { return y(d.RecordsStolen); });
focus.select(".axis--y").call(yAxis);
}
function type(d) {
d.Year = parseTime(d.Year);
d.RecordsStolen = +d.RecordsStolen;
return d;
}
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
</script>
https://d3js.org/d3.v4.min.js