Download raw (6.9 KB)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Timeline</title>
</head>
<body>
<object id="timeline" data="timeline.svg" type="image/svg+xml" style="max-height:90vh"></object>
<script src="raphael.min.js"></script>
<script>
// lastDirection = 1;
var loopSwitch = true,
daySwitch = true,
event = 0,
day = 0,
loop = 0,
timelineSVG,
highlightpath,
timelineSegments;
const timeline = [
[
[0],
[0, 1, 2, 3],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[0]
],
[
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4, 5, 6, 7],
[0]
],
[
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[0]
]
];
function timelineSubset(loop, day, event) {
if (typeof(day) !== "undefined") {
if(typeof(event) !== "undefined") {
return timeline[loop][day][event];
}
return timeline[loop][day];
}
return timeline[loop];
}
function getLength(input) {
if (Array.isArray(input)) {
// If the subpath has an uneven amount of children
// on of them is positioned in the middle of the loop
// therefor we loose a point on the loop
var length = (input.length % 2 == 0) ? 3 : 2;
for (var i=0;i<input.length;i++) {
length += getLength(input[i]);
}
return length;
} else {
return 3;
}
}
// If the parent(path) has an even amount of children, and the child
// is located over the half of the path we have to insert and extra
// point (top of the loop)
function middlepointCompensation (parent, key) {
if (key > 0 && (key + 1) * 2 > parent.length && parent.length % 2 == 0) {
return 1;
} else {
return 0;
}
}
function getStart(loop, day, event) {
var coord = 1, l = 0, d = 0, e = 0;
while (l < loop) {
coord += getLength(timelineSubset(l));
l++;
};
if (typeof(day) !== "undefined") {
coord++;
while (d < day) {
coord += getLength(timelineSubset(l, d));
d++;
}
coord += middlepointCompensation(timelineSubset(l), d);
if (typeof(event) !== "undefined") {
coord++;
while (e < event) {
coord += getLength(timelineSubset(l,d,e));
e++;
}
coord += middlepointCompensation(timelineSubset(l,d), e);
}
}
return coord;
}
function getEnd(loop, day, event) {
var start = getStart(loop, day, event);
if (typeof(event) !== 'undefined') {
return start + getLength(timelineSubset(loop, day, event));
} else if (typeof(day) !== 'undefined') {
return start + getLength(timelineSubset(loop, day));
}
return start + getLength(timelineSubset(loop));
}
function getSegmentCoords(segment) {
if (segment[0] == 'C') {
return [segment[5], segment[6]];
} else {
return [segment[1], segment[2]];
}
}
function getSubpathFromSegments(segments, start, end) {
subset = [];
if (start > 0 || segments[start][0] !== 'M') {
subset.push(['M'].concat(getSegmentCoords(segments[start-1])));
}
return subset.concat(segments.slice(start, end+1));
}
function makeCoordinateString(x, y) {
return x + ' ' + y;
}
function makePathString(segments) {
var pathstring = '';
for (var s = 0; s < segments.length;s++) {
var command = segments[s][0];
coordinates = [];
for (var c=1; c < segments[s].length; c+=2) {
coordinates.push(makeCoordinateString(segments[s][c], segments[s][c+1]));
}
pathstring += command + coordinates.join(',');
}
return pathstring
}
function highlight(start, end) {
highlightpath.setAttribute('d', makePathString(getSubpathFromSegments(timelineSegments, start, end)));
}
function highlightSection(loop, day, event) {
highlight(getStart(loop, day, event)+1, getEnd(loop, day, event)-1);
}
function next () {
// highlight next event
// on loop switch higlight whole loop
// on day switch highlight whole day
// highlight previous event
if (loopSwitch) {
loopSwitch = false;
// highlight loop
highlightSection(loop, day)
} else if (daySwitch) {
daySwitch = false;
highlightSection(loop, day, event);
} else {
event++;
if (event >= timeline[loop][day].length) {
// switch day, highlight day
daySwitch = true;
day++;
if (day >= timeline[loop].length) {
// switch loop highlight whole loop
loopSwitch = true
loop++;
if (loop >= timeline.length) {
loop = 0;
}
day = 0;
highlightSection(loop);
} else {
highlightSection(loop, day);
}
event = 0;
} else {
highlightSection(loop, day, event);
}
}
}
function previous () {
// highlight previous event
if (loopSwitch) {
loopSwitch = false;
// highlight loop
highlightSection(loop, day)
} else if (daySwitch) {
daySwitch = false;
// on day switch higlight whole day
// switch day, highlight day
highlightSection(loop, day, event);
} else {
event--;
if (event < 0) {
daySwitch = true;
day--;
if (day < 0) {
// switch loop highlight whole loop
loopSwitch = true
loop--;
if (loop < 0) {
loop = timeline.length-1;
}
highlightSection(loop);
day = timeline[loop].length - 1;
} else {
highlightSection(loop, day);
}
event = timeline[loop][day].length - 1;
} else {
highlightSection(loop, day, event);
}
}
}
window.addEventListener('load', function () {
timelineSVG = document.querySelector('#timeline').contentDocument.rootElement;
const paths = timelineSVG.querySelectorAll('path');
highlightpath = paths[5]; //document.querySelector('#timeline').contentDocument.createElement('path');
timelineSegments = Raphael.parsePathString(paths[4].getAttribute('d'));
highlightpath.setAttribute("style", "stroke:rgb(100%,0%,0%); stroke-width:5.0;fill:none;");
window.addEventListener('wheel', function (e) {
(e.deltaY > 0) ? next() : previous();
});
highlightSection(loop);
});
</script>
</body>
</html>