D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
davidgutierrez
Full window
Github gist
Data Breaches zoom
Built with
blockbuilder.org
<!DOCTYPE html> <!-- 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