assembled with blockbuilder.org
slightly improved in Version 2
A very unfinished little example combining d3.js
and d3.layout.timeline
by Elijah Meeks to render what you might use in a resume or something similar. It is partially reusable, but still needs lots of love and attention. Please do not use this as an model for how to implement a reusable component.
If you are wondering about my potential motivation for this, see post.
library(pipeR) #install.packages("pipeR")
library(timelineR) #devtools::install_github("timelyportfolio/timelineR")
library(htmltools) #install.packages("htmltools")
library(d3r) #devtools::install_github("timelyportfolio/d3r")
library(googlefontR) #devtools::install_github("timelyportfolio/googlefontR")
library(whisker) #install.packages("whisker")
dat <- data.frame(
id = 1:4,
company = c(
"Company A",
"Company A",
"Company B",
"Company C"
),
start = c(
"1998-08-31",
"1999-12-31",
"2001-05-31",
"2011-08-31"
),
end = c(
"1999-12-31",
"2001-05-31",
"2011-08-31",
"2016-12-31"
),
description = c(
"Title and all the stuff I did",
"New Title with other sophisticated sounding items",
"Really Important Sounding Title with all the buzzwords",
"Even More Important Title with persuasive text"
)
)
# based off of
# /emeeks/3184af35f4937d878ac0
template <- '
(function(){
var svg = d3.select("svg#{{svgid}}");
var width = svg.node().getBoundingClientRect().width,
height = svg.node().getBoundingClientRect().height;
var data = {{{data}}};
var groups = d3.set(data.map(function(d){ return d.{{group}} })).values();
var bandHeight = {{bandHeight}};
var timeline = d3.layout.timeline()
.size([width - 150 - 20, bandHeight - 10])
.extent(["1998-01-01", "2016-12-31"])
.padding(3)
.maxBandHeight(bandHeight - 20);
var colorScale = {{colorFun}};
groups.forEach(function (type, i) {
onlyThisType = data.filter(function(d) {return d.{{group}} === type});
theseBands = timeline(onlyThisType);
svg.append("g")
.attr("transform", "translate(150," + (35 + (i * 50)) + ")")
.selectAll("rect")
.data(theseBands)
.enter()
.append("rect")
.classed("rect-position",true)
.attr("rx", 2)
.attr("x", function (d) {return d.start})
.attr("y", function (d) {return d.y})
.attr("height", function (d) {return d.dy})
.attr("width", function (d) {return d.end - d.start})
.style("fill", function (d) {return colorScale(d.{{group}})})
.style("stroke", "black")
.style("stroke-width", 1);
d3.select("svg").append("text")
.text(type)
.attr("y", bandHeight + (i * bandHeight))
.attr("x", 20);
});
var axisScale = d3.time.scale();
axisScale
.domain(timeline.extent())
.range([0, width - 150 - 20]);
var axis = d3.svg.axis();
axis.scale(axisScale);
axis.tickSize(bandHeight * groups.length + 20);
var axis_g = svg.append("g")
.attr("class","timeline-axis")
.attr("transform","translate(170,0)")
.call(axis);
// some default styles for our axis
axis_g.selectAll("path, .tick > line")
.style("fill","none")
.style("stroke","black");
svg.selectAll(".timeline-axis > path")
.style("fill","none")
.style("stroke","none");
svg.selectAll(".timeline-axis .tick line")
.style("stroke","gray")
.attr("stroke-dasharray","5 5");
svg.selectAll("rect")
.style("stroke","white")
.attr("rx",4);
svg.attr("height", (bandHeight * groups.length + 20 + 20) + "px")
// now render the text descriptions of each position
var textdiv = d3.select("div#{{divid}}");
var posdiv = textdiv.selectAll("p")
.data(data)
.enter()
.append("div");
posdiv.append("h3")
.text(function(d){
return d.company + " | " + d.start + " - " + d.end
});
posdiv.append("p")
.text(function(d){ return d.description; });
// add some mouseover on the rects
svg.selectAll("rect.rect-position")
.on("mouseover", highlightPos)
.on("mouseout", unhighlightPos);
function highlightPos(pos){
posdiv.each(function(d) {
if(d.id !== pos.id) {
d3.select(this).style("color", "lightgray");
}
});
}
function unhighlightPos() {
posdiv.style("color", "black")
}
})();
'
tagList(
h1("Work History"),
tag("svg",list(id="work-timeline", width="80%", height="400px")),
hr(),
div(id = "work-history"),
tags$script(
HTML(
whisker.render(
template,
list(
svgid = "work-timeline",
divid = "work-history",
group = "company",
data = jsonlite::toJSON(dat, dataframe="rows"),
bandHeight = 50, # total height of band not the timeline rect
colorFun = "d3.scale.category10()"
)
)
)
)
) %>>%
gf_add_font("Titillium+Web") %>>%
attachDependencies(
list(
d3r::d3_dep_v3(offline=FALSE),
htmlwidgets:::getDependency("timeline","timelineR")[[3]]
),
append = TRUE
) %>>%
browsable()
Updated missing url https://cdn.rawgit.com/emeeks/d3.layout.timeline/master/d3.layout.timeline.js to https://cdn.jsdelivr.net/npm/d3-layout-timeline@1.0.3/d3.layout.timeline.js
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js
https://cdn.rawgit.com/emeeks/d3.layout.timeline/master/d3.layout.timeline.js