JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.4/fabric.min.js"></script>
<script src="https://goodsight.hk/raptor/hkida/js/jquery.panelSnap.js"></script>
<div class="indicator">
<div class="section"><span>Section 1</span></div>
<div class="section"><span>Section 2</span></div>
<div class="section"><span>Section 3</span></div>
<div class="section"><span>Section 4</span></div>
<canvas id="line_effect" width="50" height="100%"></canvas>
</div>
<div class="contents">
<section class="page" data-panel="page1">
<div id="page1">Page 1</div>
</section>
<section class="page" data-panel="page2">
<div id="page2">Page 2</div>
</section>
<section class="page" data-panel="page3">
<div id="page3">Page 3</div>
</section>
<section class="page" data-panel="page4">
<div id="page4">Page 4</div>
</section>
</div>
CSS
html, body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
body {
font-size: 1em;
background-color: #EEE;
overflow: hidden;
}
.indicator {
position: relative;
width: 50px;
height: 100%;
float: left;
}
.indicator .section {
height: 25%;
width: 99%;
border-right: 1px #FFF solid;
border-bottom: 2px #FFF dashed;
}
.indicator .section span {
font-size: 0.3em;
}
.indicator .canvas-container {
position: absolute !important;
width: 100% !important;
height: 100% !important;
top: 0;
left: 0;
}
.indicator .canvas-container #line_effect {
width: 100% !important;
height: 100% !important;
top: 0;
left: 0;
}
.contents {
width: calc(100% - 50px);
height: 100%;
float: left;
overflow: auto;
}
.contents .page {
width: 100%;
height: 100%;
font-size: 4em;
}
.contents .page > div {
height: 100%;
line-height: 200px;
text-align: center;
}
.contents #page1 {
background-color: #ABCDEF;
}
.contents #page2 {
background-color: #67890A;
}
.contents #page3 {
background-color: #345678;
}
.contents #page4 {
background-color: #7890AB;
}
JavaScript
var canvas;
var current_page = 1;
var is_animating = false;
var line_options = {
stroke: 'red',
strokeWidth: 3
};
$(document).ready(function() {
canvas = new fabric.Canvas('line_effect');
canvas.setHeight($('.indicator').height());
canvas.setWidth(50);
canvas.renderAll();
var section_h = $('.section').height();
var startPts = [
{x: 48, y: 0},
{x: 48, y: $('.section').height()}
];
var endPts = [
{x: 48, y: $('.section').height() * 2},
{x: 48, y: $('.section').height()}
];
var line = new fabric.Polyline(startPts, line_options);
canvas.add(line);
function animateLine(i, prop, endPts) {
fabric.util.animate({
startValue: line.points[i][prop],
endValue: endPts[i][prop],
duration: 1000,
easing: fabric.util.ease.easeInOutCubic,
onChange: function(value) {
line.points[i][prop] = value;
if(i === startPts.length - 1 && prop == 'y') {
canvas.renderAll();
}
},
onComplete: function() {
line.setCoords();
if(i === startPts.length - 1 && prop == 'y') {
even = !even;
animateLine(i, prop, endPts);
}
}
});
}
function animate(startPage, endPage) {
if(is_animating) {
return;
} else if(startPage == endPage) {
return;
} else if(Math.abs(startPage - endPage) > 1) {
// Jump to that section immediately.
console.log('Jump to Page ' + endPage);
canvas.remove(line);
if(endPage == 1) {
line = new fabric.Line([48, section_h * 0, 48, section_h * 1], line_options);
} else if(endPage == 2) {
line = new fabric.Line([48, section_h * 1, 48, section_h * 2], line_options);
} else if(endPage == 3) {
line = new fabric.Line([48, section_h * 2, 48, section_h * 3], line_options);
} else if(endPage == 4) {
line = new fabric.Line([48, section_h * 3, 48, section_h * 4], line_options);
}
canvas.add(line);
} else {
is_animating = true;
if(startPage == 1 && endPage == 2) {
console.log('Page 1 > 2');
startPts = [
{x: 48, y: section_h *...