Created
June 20, 2017 15:59
-
-
Save royshil/32bcc10606c40fb648f0407bc12ab34a to your computer and use it in GitHub Desktop.
A d3v4 visualization of yearly submission deadlines (conference, grant, etc). Tool for the hungry assistant professor.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<meta charset="utf-8"> | |
<head> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.23.1/babel.min.js"></script> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.min.js"></script> | |
<script src="http://unpkg.com/d3-radial-axis@1.5/dist/d3-radial-axis.min.js"></script> | |
<script src="https://npmcdn.com/d3fc-rebind@4.0.1/build/d3fc-rebind.js"></script> | |
<script src="https://npmcdn.com/d3fc-data-join@2.0.0/build/d3fc-data-join.js"></script> | |
<script src="https://npmcdn.com/d3fc-label-layout@4.0.0/build/d3fc-label-layout.js"></script> | |
</head> | |
<style> | |
body { | |
text-align: center; | |
font-family: Sans-serif; | |
margin: 0; | |
} | |
.background { | |
stroke-width: 0; | |
fill: Lavender; | |
fill-opacity: 0.3; | |
} | |
.axis .domain, .axis .tick line { | |
stroke-width: 2px; | |
stroke: lightgrey; | |
} | |
.axis .tick:first-of-type { | |
display: none; // hide 0 tick | |
} | |
.axis .tick text { | |
font-size: 14px; | |
fill: blue; | |
} | |
.chart rect { | |
fill: transparent; | |
} | |
.label { | |
font-size: 18pt; | |
} | |
</style> | |
<body> | |
<svg id="canvas"></svg> | |
<script> | |
// Add your deadlines here. | |
// type: "[grant, conf, conf_venue][1, 2]" | |
var data = [ | |
{name: "NSF M3X", date: new Date("Jan 10 2017"), type: "grant1"}, | |
{name: "NSF M3X", date: new Date("Sep 1 2017"), type: "grant1"}, | |
{name: "NSF BIO-ABI", date: new Date("Sep 8 2017"), type: "grant1"}, | |
{name: "NSF Core Medium", date: new Date("Oct 12 2017"), type: "grant1"}, | |
{name: "NSF BIO-MCB", date: new Date("Nov 15 2017"), type: "grant1"}, | |
{name: "NSF S&AS", date: new Date("Dec 11 2017"), type: "grant1"}, | |
{name: "NSF Core Small", date: new Date("Nov 2 2017"), type: "grant2"}, | |
{name: "NSF CRII", date: new Date("Aug 9 2017"), type: "grant2"}, | |
{name: "SIGGRAPH", date: new Date("Jan 16 2017"), type: "conf1"}, | |
{name: "ICCV", date: new Date("Mar 15 2017"), type: "conf1"}, | |
{name: "UIST", date: new Date("Apr 10 2017"), type: "conf1"}, | |
{name: "CSCW", date: new Date("Apr 20 2017"), type: "conf1"}, | |
{name: "SIGGRAPH Asia", date: new Date("May 20 2017"), type: "conf1"}, | |
{name: "NIPS", date: new Date("May 25 2017"), type: "conf1"}, | |
{name: "BMVC", date: new Date("May 15 2017"), type: "conf1"}, | |
{name: "CHI", date: new Date("Sep 10 2017"), type: "conf1"}, | |
{name: "AAAI", date: new Date("Sep 20 2017"), type: "conf1"}, | |
{name: "Eurographics", date: new Date("Oct 10 2017"), type: "conf1"}, | |
{name: "CVPR", date: new Date("Nov 15 2017"), type: "conf1"}, | |
{name: "ISMAR", date: new Date("Mar 15 2017"), type: "conf1"}, | |
{name: "UbiComp", date: new Date("Nov 15 2017"), type: "conf1"}, | |
{name: "UbiComp", date: new Date("Feb 15 2017"), type: "conf1"}, | |
{name: "UbiComp", date: new Date("May 15 2017"), type: "conf1"}, | |
{name: "UbiComp", date: new Date("Aug 15 2017"), type: "conf1"}, | |
{name: "DIS", date: new Date("Jan 9 2017"), type: "conf2"}, | |
{name: "C&C", date: new Date("Jan 13 2017"), type: "conf2"}, | |
{name: "Compu. Fab.", date: new Date("Jan 31 2017"), type: "conf2"}, | |
{name: "Compu. Fab.", date: new Date("Apr 10 2017"), type: "conf2"}, | |
{name: "Mobile HCI", date: new Date("Feb 15 2017"), type: "conf2"}, | |
{name: "ICDAR", date: new Date("Mar 5 2017"), type: "conf2"}, | |
{name: "DocEng", date: new Date("Mar 25 2017"), type: "conf2"}, | |
{name: "Expressive", date: new Date("Apr 1 2017"), type: "conf2"}, | |
{name: "CHI Play", date: new Date("Apr 15 2017"), type: "conf2"}, | |
{name: "SUI", date: new Date("Jun 30 2017"), type: "conf2"}, | |
{name: "VRST", date: new Date("Jun 30 2017"), type: "conf2"}, | |
{name: "ISS", date: new Date("Jun 28 2017"), type: "conf2"}, | |
{name: "ASSETS", date: new Date("Jul 25 2017"), type: "conf2"}, | |
{name: "TEI", date: new Date("Aug 1 2017"), type: "conf2"}, | |
{name: "Graph. Intrf.", date: new Date("Dec 23 2017"), type: "conf2"}, | |
{name: "IUI", date: new Date("Oct 1 2017"), type: "conf2"}, | |
{name: "Augm. Human", date: new Date("Nov 1 2017"), type: "conf2"}, | |
{name: "CHI", date: new Date("Apr 21 2017"), type: "conf_venue1"}, | |
{name: "SIGGRAPH", date: new Date("Jul 30 2017"), type: "conf_venue1"}, | |
{name: "UIST", date: new Date("Oct 22 2017"), type: "conf_venue1"}, | |
{name: "CVPR", date: new Date("Jul 21 2017"), type: "conf_venue1"}, | |
{name: "UbiComp", date: new Date("Sep 11 2017"), type: "conf_venue1"}, | |
{name: "MobileHCI", date: new Date("Sep 4 2017"), type: "conf_venue2"}, | |
{name: "TEI", date: new Date("Mar 20 2017"), type: "conf_venue2"}, | |
{name: "SIGGRAPH Asia", date: new Date("Nov 27 2017"), type: "conf_venue2"}, | |
{name: "AH", date: new Date("Feb 7 2017"), type: "conf_venue2"}, | |
{name: "ASSETS", date: new Date("Oct 29 2017"), type: "conf_venue2"}, | |
]; | |
// determine how far apart the labels will be (also from their dots) | |
const labelPadding = 8; | |
// the radii for label types: [grant, conf, conf_venue] | |
const typeRadiiOffset = [75, 0, 150]; | |
// the radius of the circle (from the window size) | |
const r = Math.min(window.innerWidth, window.innerHeight) / 2 - 100; | |
// the scale is linear chronological, mapped to [0, 2pi] | |
const yearScale = d3.scaleTime() | |
.domain([new Date(2017, 0, 0), new Date(2017, 11, 30)]) | |
.range([0, 2 * Math.PI]); | |
// Size canvas | |
const svg = d3.select('#canvas') | |
.attr('width', r * 2 + 300) // extra width space | |
.attr('height', r * 2 + 100) | |
.attr('viewBox', `${-r - 150} ${-r - 150} ${r*2 + 300} ${r*2 + 300}`) | |
// add chart group | |
var chart = svg.append('g') | |
.classed("chart", true) | |
.attr("transform","translate(0, 50)"); | |
// Add background | |
chart.append('circle').classed('background', true) | |
.attr('cx', 0) | |
.attr('cy', 0) | |
.attr('r', r) | |
// Set axis at (r - 100) | |
var radialAxis = d3.axisRadialInner(yearScale.copy(), r - 100) | |
.ticks(12) | |
.tickSize(-170) //push the ticks way out | |
.tickPadding(-190); | |
// draw radial axis | |
chart.append('g') | |
.classed('axis', true) | |
.call(radialAxis); | |
/********** Dont worry about this stuff ************/ | |
/* It's to make sure labels won't overlap. */ | |
var textLabel = fc.layoutTextLabel() | |
.padding(labelPadding) | |
.value(function(d) { return d.name; }); | |
var strategy = fc.layoutAnnealing(); | |
var labels = fc.layoutLabel(strategy) | |
.size(function(_, i, g) { | |
// measure the label and add the required padding | |
var textSize = d3.select(g[i]) | |
.select('text') | |
.node() | |
.getBBox(); | |
return [textSize.width + labelPadding * 2, | |
textSize.height + labelPadding * 2]; | |
}) | |
.position(function(d) { | |
var a = yearScale(d.date); | |
// this puts the papers, grants and venues on different radii | |
const rad = d.type.startsWith("conf_venue") ? r - typeRadiiOffset[2] : | |
d.type.startsWith("grant") ? r - typeRadiiOffset[0] : | |
r - typeRadiiOffset[1] ; | |
return [ Math.sin(a) * rad, -Math.cos(a) * rad]; | |
}) | |
.component(textLabel); | |
/**************** Resume worrying ****************/ | |
// render non-overlapping labels! | |
chart.datum(data) | |
.call(labels); | |
// style the labels according to their type | |
chart.selectAll(".label") | |
.style("fill-opacity", (d)=>d.type.endsWith("1") ? 1 : 0.65 ) | |
.style("font-weight", (d)=>d.type.endsWith("1") ? "bold" : "normal") | |
.style("font-size", (d)=>d.type.endsWith("1") ? "18pt" : "16pt" ) | |
.style("fill", (d)=>d.type.startsWith("conf_venue") ? "green" : | |
d.type.startsWith("grant") ? "black" : | |
"red" ); | |
// Add title | |
svg.append("text") | |
.text("Circle of Deadlines") | |
.attr("x", 0) | |
.attr("y", -r - 50) | |
.attr("text-anchor", "middle") | |
.style("font-size", "36pt"); | |
// Add reader | |
svg.append("foreignObject") | |
.attr("width", 150) | |
.attr("height", 300) | |
.attr("x", r + 100) | |
.attr("y", -r) | |
.append("xhtml:body") | |
.style("font", "14px 'Helvetica Neue'") | |
.style("text-align", "left") | |
.html("<p><b>1st Tier</b><br/>2nd Tier</p>" + | |
"<p>Grant<br/><span style='color: red'>Conference Paper</span>" + | |
"<br/><span style='color: green'>Conference Venue</span></p>"); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment