<section id="timeline-3">
<h1>Timeline concept</h1>
<div id="scrollbox">
<div id="svgOutput"></div>
</div>
<div class="data">
<script>
const dataset = [{
"id": 1,
"author": "Rory",
"details": [{
"month": "2021-06-02",
"work": "Snake Eyes"
}, {
"month": "2021-03-18",
"work": "How to Eat Your Watermelon in White Company (and Enjoy It)"
}, {
"month": "2021-01-25",
"work": "Black Dragons"
}, {
"month": "2021-01-03",
"work": "If You Only Knew"
}, {
"month": "2021-03-04",
"work": "Switchback"
}, {
"month": "2020-09-17",
"work": "I'm Still Here"
}, {
"month": "2021-03-07",
"work": "Shut Up and Play the Hits"
}, {
"month": "2021-04-11",
"work": "Accidental Husband, The"
}]
},
{
"id": 2,
"author": "Conny",
"details": [{
"month": "2021-06-09",
"work": "I Remember Mama"
}, {
"month": "2021-08-21",
"work": "Aladdin and the King of Thieves"
}, {
"month": "2021-01-19",
"work": "Stavisky..."
}]
},
{
"id": 3,
"author": "Sibbie",
"details": [{
"month": "2020-11-01",
"work": "Miami Blues"
}, {
"month": "2021-04-26",
"work": "Nutty Professor II: The Klumps"
}, {
"month": "2021-02-17",
"work": "Bright Young Things"
}, {
"month": "2021-08-22",
"work": "Crew, The"
}, {
"month": "2021-03-21",
"work": "Oh, Heavenly Dog!"
}]
},
{
"id": 4,
"author": "Brittni",
"details": [{
"month": "2021-01-23",
"work": "Nobody"
}, {
"month": "2020-11-13",
"work": "House of Mirth, The"
}, {
"month": "2021-07-28",
"work": "I Love You Phillip Morris"
}]
},
{
"id": 5,
"author": "Avrit",
"details": [{
"month": "2020-10-22",
"work": "Commune, La (Paris, 1871)"
}, {
"month": "2020-11-16",
"work": "Panic"
}, {
"month": "2020-10-04",
"work": "Igor"
}, {
"month": "2021-03-01",
"work": "Front, The"
}, {
"month": "2021-04-11",
"work": "Jack the Giant Killer"
}, {
"month": "2020-12-16",
"work": "How Wang-Fo Was Saved (Comment Wang-Fo fut sauvé)"
}]
},
{
"id": 6,
"author": "Kathy",
"details": [{
"month": "2021-01-23",
"work": "Ghost Adventures"
}, {
"month": "2020-12-28",
"work": "Last Call (Hoogste tijd)"
}, {
"month": "2020-09-17",
"work": "Lizard, The (Marmoulak)"
}, {
"month": "2020-10-26",
"work": "Anthony Zimmer"
}, {
"month": "2020-10-09",
"work": "Swimming"
}]
},
{
"id": 7,
"author": "Adiana",
"details": [{
"month": "2020-10-28",
"work": "Won't Back Down"
}, {
"month": "2020-10-08",
"work": "Twelve Monkeys (a.k.a. 12 Monkeys)"
}, {
"month": "2020-11-23",
"work": "Scarlet Letter, The (Der scharlachrote Buchstabe)"
}, {
"month": "2021-09-02",
"work": "Destruction Force"
}, {
"month": "2021-05-02",
"work": "Unlikely Weapon, An"
}]
},
{
"id": 8,
"author": "Chickie",
"details": [{
"month": "2020-11-02",
"work": "Tyler Perry's Why Did I Get Married Too?"
}, {
"month": "2021-09-10",
"work": "Problem Child"
}, {
"month": "2021-08-12",
"work": "Eleventh Year, The (Odinnadtsatyy) "
}, {
"month": "2021-01-30",
"work": "Man in the Glass Booth, The"
}, {
"month": "2021-07-11",
"work": "Ten Little Indians"
}, {
"month": "2021-05-31",
"work": "Quitting (Zuotian)"
}, {
"month": "2021-07-26",
"work": "Little Thief, The (Le petit voleur)"
}, {
"month": "2021-07-06",
"work": "Miss Minoes"
}]
},
{
"id": 9,
"author": "Beret",
"details": [{
"month": "2021-03-01",
"work": "Twelve O'Clock High"
}, {
"month": "2020-11-25",
"work": "Taxi 4"
}, {
"month": "2021-04-14",
"work": "Loop the Loop (Up and Down) (Horem pádem)"
}, {
"month": "2021-04-04",
"work": "Boy Upside Down"
}, {
"month": "2020-10-30",
"work": "In Your Hands (Forbrydelser)"
}]
},
{
"id": 10,
"author": "Finley",
"details": [{
"month": "2021-01-22",
"work": "Man Push Cart"
}, {
"month": "2021-07-27",
"work": "Red Flag"
}, {
"month": "2021-03-02",
"work": "Neighbours"
}, {
"month": "2021-05-09",
"work": "Shakespeare-Wallah"
}]
}
];
</script>
</div>
</section>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="../../js/components/timeline-3.js"></script>
<section id="timeline-3">
<h1>Timeline concept</h1>
<div id="scrollbox">
<div id="svgOutput"></div>
</div>
<div class="data">
<script>
const dataset = [{
"id": 1,
"author": "Rory",
"details": [{"month": "2021-06-02", "work": "Snake Eyes"}, {
"month": "2021-03-18",
"work": "How to Eat Your Watermelon in White Company (and Enjoy It)"
}, {"month": "2021-01-25", "work": "Black Dragons"}, {
"month": "2021-01-03",
"work": "If You Only Knew"
}, {"month": "2021-03-04", "work": "Switchback"}, {
"month": "2020-09-17",
"work": "I'm Still Here"
}, {"month": "2021-03-07", "work": "Shut Up and Play the Hits"}, {
"month": "2021-04-11",
"work": "Accidental Husband, The"
}]
},
{
"id": 2,
"author": "Conny",
"details": [{"month": "2021-06-09", "work": "I Remember Mama"}, {
"month": "2021-08-21",
"work": "Aladdin and the King of Thieves"
}, {"month": "2021-01-19", "work": "Stavisky..."}]
},
{
"id": 3,
"author": "Sibbie",
"details": [{"month": "2020-11-01", "work": "Miami Blues"}, {
"month": "2021-04-26",
"work": "Nutty Professor II: The Klumps"
}, {"month": "2021-02-17", "work": "Bright Young Things"}, {
"month": "2021-08-22",
"work": "Crew, The"
}, {"month": "2021-03-21", "work": "Oh, Heavenly Dog!"}]
},
{
"id": 4,
"author": "Brittni",
"details": [{"month": "2021-01-23", "work": "Nobody"}, {
"month": "2020-11-13",
"work": "House of Mirth, The"
}, {"month": "2021-07-28", "work": "I Love You Phillip Morris"}]
},
{
"id": 5,
"author": "Avrit",
"details": [{"month": "2020-10-22", "work": "Commune, La (Paris, 1871)"}, {
"month": "2020-11-16",
"work": "Panic"
}, {"month": "2020-10-04", "work": "Igor"}, {
"month": "2021-03-01",
"work": "Front, The"
}, {"month": "2021-04-11", "work": "Jack the Giant Killer"}, {
"month": "2020-12-16",
"work": "How Wang-Fo Was Saved (Comment Wang-Fo fut sauvé)"
}]
},
{
"id": 6,
"author": "Kathy",
"details": [{"month": "2021-01-23", "work": "Ghost Adventures"}, {
"month": "2020-12-28",
"work": "Last Call (Hoogste tijd)"
}, {"month": "2020-09-17", "work": "Lizard, The (Marmoulak)"}, {
"month": "2020-10-26",
"work": "Anthony Zimmer"
}, {"month": "2020-10-09", "work": "Swimming"}]
},
{
"id": 7,
"author": "Adiana",
"details": [{"month": "2020-10-28", "work": "Won't Back Down"}, {
"month": "2020-10-08",
"work": "Twelve Monkeys (a.k.a. 12 Monkeys)"
}, {
"month": "2020-11-23",
"work": "Scarlet Letter, The (Der scharlachrote Buchstabe)"
}, {"month": "2021-09-02", "work": "Destruction Force"}, {
"month": "2021-05-02",
"work": "Unlikely Weapon, An"
}]
},
{
"id": 8,
"author": "Chickie",
"details": [{
"month": "2020-11-02",
"work": "Tyler Perry's Why Did I Get Married Too?"
}, {"month": "2021-09-10", "work": "Problem Child"}, {
"month": "2021-08-12",
"work": "Eleventh Year, The (Odinnadtsatyy) "
}, {"month": "2021-01-30", "work": "Man in the Glass Booth, The"}, {
"month": "2021-07-11",
"work": "Ten Little Indians"
}, {"month": "2021-05-31", "work": "Quitting (Zuotian)"}, {
"month": "2021-07-26",
"work": "Little Thief, The (Le petit voleur)"
}, {"month": "2021-07-06", "work": "Miss Minoes"}]
},
{
"id": 9,
"author": "Beret",
"details": [{"month": "2021-03-01", "work": "Twelve O'Clock High"}, {
"month": "2020-11-25",
"work": "Taxi 4"
}, {
"month": "2021-04-14",
"work": "Loop the Loop (Up and Down) (Horem pádem)"
}, {"month": "2021-04-04", "work": "Boy Upside Down"}, {
"month": "2020-10-30",
"work": "In Your Hands (Forbrydelser)"
}]
},
{
"id": 10,
"author": "Finley",
"details": [{"month": "2021-01-22", "work": "Man Push Cart"}, {
"month": "2021-07-27",
"work": "Red Flag"
}, {"month": "2021-03-02", "work": "Neighbours"}, {
"month": "2021-05-09",
"work": "Shakespeare-Wallah"
}]
}];
</script>
</div>
</section>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="{{ path '/js/components/timeline-3.js' }}"></script>
/* No context defined. */
(function () {
document.addEventListener('DOMContentLoaded', function () {
console.log("timeline-3 active");
// Debug mode?
const debug = false;
// Config
const width = 600;
const height = 400;
const margin = {
"top": 20,
"bottom": 60,
"left": 60,
"right": 40
}
const dotRadius = 4;
// Create the svg container
function zoom(svg) {
const extent = [[margin.left, margin.top], [width - margin.right, height - margin.top]];
svg.call(d3.zoom()
.scaleExtent([1, 8])
.translateExtent(extent)
.extent(extent)
.on("zoom", zoomed));
function zoomed(event) {
xScale.range([margin.left, width - margin.right].map(d => event.transform.applyX(d)));
svg.selectAll("circle.dot")
.attr("cx", d => xScale(d.month));
svg.selectAll("line.authorLine")
.attr('x1', (d) => xScale(d.x1))
.attr('y1', (d) => yScale(d.y1) + yScale.bandwidth() / 2)
.attr('x2', (d) => xScale(d.x2))
.attr('y2', (d) => yScale(d.y2) + yScale.bandwidth() / 2);
svg.selectAll(".xAxis").call(xAxis);
}
}
const svg = d3.select("#svgOutput")
.append("svg")
.attr("viewBox", [0, 0, width, height])
.attr("preserveAspectRatio", "xMidYMid meet")
.call(zoom);
// Date parser
const parseTime = d3.timeParse("%Y-%m-%d");
//
// Do stuff
//
// Data initialization
function Datapoint(author, month, work) {
this.author = author;
this.month = month;
this.work = work;
}
let datasetArray = [];
let authorsList = [];
for (let i = 0; i < dataset.length; i++) {
const author = dataset[i].author;
authorsList.push(author);
dataset[i].details.forEach((item) => {
const month = parseTime(item.month);
const work = item.work;
datasetArray.push(new Datapoint(author, month, work));
})
}
// Set up scales
const xScale = d3.scaleTime()
.domain(d3.extent(datasetArray, d => d.month))
.range([margin.left, width - margin.right]);
const yScale = d3.scaleBand()
.domain(datasetArray.map(d => d.author))
.range([margin.top, height - margin.bottom])
.paddingInner(0.15)
.paddingOuter(0.1);
// Create and draw the axes
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale).ticks(5);
const gx = svg.append("g")
.attr('class', 'xAxis')
.attr("transform", `translate(0, ${(height - margin.bottom)})`)
.call(xAxis);
gx.call(g => g.selectAll(".tick text")
.attr('class', 'x-axis-label')
.attr("transform", `translate(12, 0) rotate(45)`)
.attr('dy', '12'));
const gy = svg.append("g")
.attr('class', 'yAxis')
.attr("transform", "translate(" + margin.left + ", 0)")
.call(yAxis);
gy.call(g => g.select('.tick:nth-child(2) line').remove());
// Create and draw the dots
const clip = svg.append("clipPath")
.attr("id", "dotsWindow")
.append("rect")
.attr("x", margin.left)
.attr("y", margin.top)
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom);
const dotsPanel = svg.append("g")
.attr('id', 'dotsPanel')
.attr("clip-path", "url(#dotsWindow)");
const dots = dotsPanel.selectAll("circle.dot")
.data(datasetArray)
.join('circle');
dots.append('title')
.text((d) => `Work: ${d.work}`)
dots.attr('class', 'dot')
.attr('cx', (d) => xScale(d.month))
.attr("cy", (d) => yScale(d.author) + yScale.bandwidth() / 2)
.attr('r', dotRadius)
.attr('fill-opacity', 1);
// Create author lines
const linesData = [];
authorsList.forEach((author) => {
console.group(author);
const thisAuthor = d3.selectAll("circle.dot").filter((d) => d.author === author);
const data = thisAuthor.data();
const minIndex = d3.minIndex(data, d => d.month);
const maxIndex = d3.maxIndex(data, d => d.month);
const lineDatapoint = {
'author': author,
'x1': thisAuthor.filter((d, i) => i === minIndex).datum().month,
'y1': thisAuthor.filter((d, i) => i === minIndex).datum().author,
'x2': thisAuthor.filter((d, i) => i === maxIndex).datum().month,
'y2': thisAuthor.filter((d, i) => i === maxIndex).datum().author,
}
linesData.push(lineDatapoint)
console.groupEnd();
})
const lines = dotsPanel.selectAll("line.authorLine")
.data(linesData)
.join('line');
lines
.attr('x1', (d) => xScale(d.x1))
.attr('y1', (d) => yScale(d.y1) + yScale.bandwidth() / 2)
.attr('x2', (d) => xScale(d.x2))
.attr('y2', (d) => yScale(d.y2) + yScale.bandwidth() / 2)
.attr('class', 'authorLine');
dots.raise();
});
})();
#timeline-3 {
margin: 2rem;
font-family: var(--system-stack);
#scrollbox {
max-width: 100%;
overflow-x: auto;
#svgOutput {
min-width: 700px;
}
}
svg {
background-color: var(--white);
border: 1px solid var(--lightred);
* {
font-family: var(--system-stack);
}
.dot {
fill: var(--darkerblue);
}
.x-axis-label {
text-anchor: start;
font-weight: bold;
color: var(--mediumgray)
}
.authorLine {
stroke-width: 2px;
stroke: var(--lighterblue);
}
}
}
No notes defined.