Beeswarm visualization of approximate dates at which each emoji was seen in the main chat for the first time. d3.js, v4. Press Open
button to see full rendering.
This visualization was prepared for this article in Medium freeCodeCamp.
Beeswarm visualization of approximate dates at which each emoji was seen in the main chat for the first time. d3.js, v4. Press Open
button to see full rendering.
This visualization was prepared for this article in Medium freeCodeCamp.
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
svg { | |
background-color: grey; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.axis text { | |
font: 14px sans-serif; | |
fill: white; | |
} | |
.cells path { | |
fill: none; | |
pointer-events: all; | |
} | |
.cells :hover circle { | |
fill: white; | |
} | |
</style> | |
<svg width="1120" height="600"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script> | |
var svg = d3.select("svg"), | |
margin = {top: 40, right: 40, bottom: 40, left: 40}, | |
width = svg.attr("width") - margin.left - margin.right, | |
height = svg.attr("height") - margin.top - margin.bottom; | |
// parse the date / time | |
var parseTime = d3.timeParse("%d-%b-%y"); | |
// set the ranges | |
var xDom = d3.scaleTime().range([0, width]); | |
var g = svg.append("g") | |
.attr("transform", "translate(" + (margin.left + 25) + "," + margin.top + ")"); | |
d3.json('https://raw.githubusercontent.com/evaristoc/fCC_emojis/master/views/emojis_viz_final_corr.json', function(err, data){ | |
if (err) console.log(err); | |
var withdate = [] | |
var withoutdate = [] | |
Object.keys(data).forEach(key => { | |
data[key]['unicode'] = key | |
console.log(data) | |
if (data[key].data.first == '2018-12-31') { | |
withoutdate.push(data[key]) | |
}else{ | |
withdate.push(data[key]) | |
} | |
}); | |
xDom.domain(d3.extent(withdate, function(d){return new Date(d.data.first)})) | |
var simulation = d3.forceSimulation(withdate) | |
.force("x", d3.forceX(function(d) { return xDom(new Date(d.data.first)); }).strength(1)) | |
.force("y", d3.forceY(height / 2)) | |
.force("collide", d3.forceCollide(10)) | |
.stop(); | |
for (var i = 0; i < 120; ++i) simulation.tick(); | |
g.append("g") | |
.attr("class", "axis axis--x") | |
.attr("transform", "translate( 0 ,"+ height + ")") | |
.call(d3.axisBottom(xDom).ticks(10)); | |
//the values of d.x and d.y are assigned to each data point at the *.forceSimulation(...) step | |
var cell = g.append("g") | |
.attr("class", "cells") | |
.selectAll("g") | |
.data(d3.voronoi() | |
.extent([[-margin.left, -margin.top], [width + margin.right, height + margin.top]]) | |
.x(function(d) { return d.x; }) | |
.y(function(d) { return d.y; }) | |
.polygons(withdate)) | |
.enter() | |
.append("g"); | |
cell | |
.append("circle") | |
.attr("r", 5) | |
.attr("cx", function(d) { if(d) return d.data.x; }) //return d.data.x | |
.attr("cy", function(d) { if(d) return d.data.y; }) | |
.attr("fill", "transparent") | |
.attr("stroke", "black") | |
cell | |
.append("image") | |
.attr('x',function(d) { if(d) return d.data.x - 5; }) | |
.attr('y',function(d) { if(d) return d.data.y - 5; }) | |
.attr('width', 10) | |
.attr('height', 10) | |
.attr("xlink:href",function(d,i){if(d) return d.data.data.Apple_img}) | |
cell | |
.on("mouseover", function(d){ | |
//console.log(d, this); | |
var _sel = d3 | |
.select(this) | |
_sel | |
.select("circle") | |
.attr("r", 15) | |
_sel | |
.select("image") | |
.attr('x',function(d) { if(d) return d.data.x - 10; }) | |
.attr('y',function(d) { if(d) return d.data.y - 10; }) | |
.attr('width', 20) | |
.attr('height', 20) | |
}) | |
.on("mouseout", function(d){ | |
var _sel = d3 | |
.select(this) | |
_sel | |
.select("circle") | |
.attr("r", 5) | |
_sel | |
.select("image") | |
.attr('x',function(d) { if(d) return d.data.x - 5; }) | |
.attr('y',function(d) { if(d) return d.data.y - 5; }) | |
.attr('width', 10) | |
.attr('height', 10) | |
}) | |
cell.append("path") | |
.attr("d", function(d) { if(d) return "M" + d.join("L") + "Z"; }) | |
cell.append("title") | |
.text(function(d) { | |
if(d) return d.data.data.alias + "\nin chat: " + d.data.data.first }); | |
cell | |
.append("rect") | |
.attr("width",1) | |
.attr("height",function(d, i){return 20}) | |
.attr("x",function(d, i){if(d) return d.data.x}) | |
.attr("y",function(d, i){if(d) return d.data.y}) | |
.attr("transform",function(d,i){if(d) return "translate(0," + (height - d.data.y - 20) + ")"}) | |
}) | |
</script> |