JSFiddle - React, Tailwind, and code Playground
by kontrach
HTML
<script src="//d3js.org/d3.v4.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Detailed timeline</title>
<script src="//d3js.org/d3.v4.min.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="navigation"></div>
<script src="script1.js"></script>
</body>
</html>
CSS
#navigation {
display: flex;
}
#navigation svg {
border-top: 1px solid #DADADA;
border-bottom: 1px solid #DADADA;
}
.circle {
fill: #F5A623;
}
.overlay {
cursor: default;
}
.domain {
/*stroke: #fff;*/
opacity: 0;
}
.selected {
fill: #ff00d0;
fill-opacity: 1;
}
.selection {
fill: #f2f9fd;
fill-opacity: 0.8;
/*stroke-dasharray: 50, 150, 50;*/
/*stroke: #005B92;*/
}
.button {
width: 24px;
background-color: #005B92;
color: #fff;
border: none;
}
TypeScript
const timelineWidth = 800;
const cardWidth = 200;
const borderGap = 40;
const rightDirectionZoneStart = timelineWidth - cardWidth - borderGap;
const dateXs = [
40,
50,
200,
400,
420,
600,
720,
760
];
enum ConnectorSide {
Left,
Right
}
enum TimelinePart {
Top,
Bottom
}
let sideForConnector: ConnectorSide;
function isCloseToTheRightBorder(x: number): boolean {
return x >= rightDirectionZoneStart;
}
if ( isCloseToTheRightBorder(dateXs[7]) ) {
sideForConnector = ConnectorSide.Left;
} else {
sideForConnector = ConnectorSide.Rigth;
}
function getTimelinePartToCheck(index: number): TimelinePart {
return index % 2 === 0 ? TimelinePart.Top : TimelinePart.Bottom;
}
const data = [{
date: '2017-01-21'
}, {
date: '2017-04-01'
}, {
date: '2017-05-21'
}, {
date: '2017-12-12'
}];
const buttonWidth = 24;
const container = d3.select("#navigation");
const leftButton = container.append('button')
.text("<")
.attr("class", 'button')
.on("click", () => handleClick("left"));
const svg = container.append("svg")
.attr("width", 800 - 2 * buttonWidth)
.attr("wmode", "Transparent")
.attr("height", 64);
const rightButton = container.append('button')
.text(">")
.attr("class", 'button')
.on("click", () => handleClick("right"));
const margin = {top: 0, right: 10, bottom: 20, left: 10};
const width = +svg.attr("width");
const height = +svg.attr("height");
const group = svg.append("g");
// Create scale
const x = d3.scaleTime()
.domain([new Date(data[0].date), new Date(data[data.length - 1].date)])
.range([margin.left, width - margin.right]);
// Add axis
const axisGroup = group.append("g");
axisGroup
.attr("class", "axis")
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b")));
// Add dots
const dotsGroup = group.append("g")
.attr("fill-opacity", 1)
.selectAll("circle")
.data(data)
...