<div class="container" id="container">
<div class="slide-container" id="slide-container">
<div class="panel active green">
<h1>Forest</h1>
<div class="circle">
<img src="https://i.imgur.com/XdoDMOu.png" alt="">
</div>
<div class="circle-1"></div>
<div class="circle-2"></div>
<div class="circle-3"></div>
<div class="background"></div>
<canvas class="canvas"></canvas>
</div>
<div class="panel blue">
<h1>Mountains</h1>
<div class="circle">
<img src="https://i.imgur.com/UfpZnPA.png" alt="">
</div>
<div class="circle-1"></div>
<div class="circle-2"></div>
<div class="circle-3"></div>
<div class="background"></div>
<canvas class="canvas"></canvas>
</div>
<div class="panel purple">
<h1>Rain</h1>
<div class="circle">
<img src="https://i.imgur.com/8nLpgOM.png" alt="">
</div>
<div class="circle-1"></div>
<div class="circle-2"></div>
<div class="circle-3"></div>
<div class="background"></div>
<canvas class="canvas"></canvas>
</div>
</div>
<div class="prev hide"> <a href="#"> ‹ </a></div>
<div class="next"> <a href="#"> › </a></div>
</div>
*
box-sizing: border-box
body
background: #dee0dd
font-family: serif
a
text-decoration: none;
color: #eee;
.noselect
touch-callout: none
user-select: none
-khtml-user-select: none
user-select: none
user-select: none
user-select: none
circle(radius)
border-radius: radius
width: radius
height: radius
.transitions
transition: transform 0.3s cubic-bezier(.76,.16,.19,.78)
transition: transform 0.3s cubic-bezier(.76,.16,.19,.78)
transition: transform 0.3s cubic-bezier(.76,.16,.19,.78)
h1
text-align: center
color: #eee
/*text-transform: uppercase*/
padding: 15px 0
font-weight: normal;
filter: blur(0.000001px);
@extend .transitions
.panel-next h1
transform: translate(-200%, 0)
.panel-prev h1
transform: translate(200%,0)
.center
position: absolute
top: 50%
left: 50%
transform: translateX(-50%) translateY(-50%)
.container
width: 540px
height: 540px
overflow: hidden
background: #21313E
@extend .center
.slide-container
width: 400%
height: 100%
transform: translate(0, 0)
position: relative
will-change: transform
.circle-1
circle(320px)
z-index: 2
transition-delay: 0.25s
transition-duration: 0.55s
@extend .center
.circle-2
circle(280px)
z-index: 3
transition-delay: 0.2s
transition-duration: 0.5s
@extend .center
.circle-3
circle(240px)
z-index: 4
transition-delay: 0.1s;
transition-duration: 0.4s
@extend .center
.circle
circle(200px)
background: #D06F79
z-index: 5
border: 4px solid #eee
overflow: hidden
@extend .center
img
margin: -4px 0 0 -4px
.panel
&.active
.circle-1
.circle-2
.circle-3
transform: translate(-50%, -50%) scale(1)
transition-timing-function: cubic-bezier(0.71, 0.13, 0.13, 1.4)
.circle-1
.circle-2
.circle-3
transform: translate(-50%, -50%) scale(0)
transition-delay: 0
@extend .transitions
.canvas
z-index: 4
position: absolute
@extend .center
@extend .noselect
.background
z-index: 4
background: #eee
position: absolute
top: 50%
width: 100%
height: 50%
.next
.prev
z-index: 6
position: absolute
top: 50%
font-size: 4em
transform: translate(0, -120%)
font-family: serif
@extend .transitions
@extend .noselect
.next
right: 15px
&.hide
transform: translate(200%, -120%)
.prev
left: 15px
&.hide
transform: translate(-200%, -120%)
.panel
display: inline-block
width: 25%
height: 100%
float: left
position: relative
will-change: transform
color_set(color1, color2, color3, color4, color5, color6)
/*background: color1*/
.circle-1
background: color2
.circle-2
background: color3
.circle-3
background: color4
.circle
background: color5
/*.background
border-bottom: 5px solid color6*/
.green
color_set(#21313E, #24545F, #247B79, #39A287, #68CA8A, #A8EF85)
.blue
color_set(#21313E, #314D5F, #416B81, #4F8BA4, #5BADC8, #66D0ED)
.purple
color_set(#21313E, #40445A, #685573, #966587, #C77594, #F6869A)
View Compiled
const PI_TWO = Math.PI * 2;
const TO_DEG = 180 / Math.PI;
const TO_RAD = Math.PI / 180;
const $container = $('#container');
const $sliceContainer = $('#slide-container');
let nextPanelPosition = 0;
let panelIndex = 0;
let state = 'forward';
let start = 0;
let end = 0;
let barSize = 0;
let per = 0;
const $next = $('.next');
const $prev = $('.prev');
const panels = [];
const colors = [
'#A8EF85',
'#66D0ED',
'#F6869A'
];
const tween = new TWEEN.Tween( {x: 0} )
.to( { x: 25 }, 500 )
.easing( TWEEN.Easing.Exponential.InOut )
.onUpdate( function () {
$sliceContainer.css('transform', `translate(-${this.x}%, 0)`);
} ).onStart(function() {
nextPanelPosition = Math.max(0, Math.min(50, nextPanelPosition))
tween.to( { x: nextPanelPosition } );
panelIndex = nextPanelPosition / 25 >> 0;
app.loader.reset();
app.loader.stop();
checkNavigation();
panels[panelIndex].container.addClass('active');
panels[panelIndex].container.removeClass('panel-prev panel-next');
}).onComplete(function(){
app.loader.start();
});
class Panel{
constructor($element, index){
this.container = $element;
this.index = index;
this.canvas = $element.children('canvas')[0];
this.ctx = this.canvas.getContext('2d');
this.color = colors[index];
this.canvas.width = 540;
this.canvas.height = 210;
}
}
$('.panel').forEach(function(item, index){
panels[index] = new Panel($(item), index)
});
$(window).on('resize', function(){
for (let i = 0; i < panels.length; i++) {
panels[i].canvas.width = panels[i].container.width();
};
});
function checkNavigation(){
if(panelIndex == 0){
$prev.addClass('hide');
} else {
$prev.removeClass('hide');
}
if(panelIndex == panels.length - 1){
$next.addClass('hide');
} else {
$next.removeClass('hide');
}
}
function next(){
tween.stop();
panels[panelIndex].container.removeClass('active');
panels[panelIndex].container.addClass('panel-next');
nextPanelPosition += 25;
tween.start();
state = 'forward';
}
function prev(){
tween.stop();
panels[panelIndex].container.removeClass('active');
panels[panelIndex].container.addClass('panel-prev');
nextPanelPosition -= 25;
tween.start();
state = 'back';
}
$next.on('click', next);
$prev.on('click', prev);
class Loader{
constructor(){
var self = this;
/*
* Percentage in float numbers
*/
this.percentage = 0;
this.radialPercentage = 0;
this.pause = false;
this.tween = new TWEEN.Tween( {percentage: 0} )
.to( { percentage: 1 }, 5000 )
.easing( TWEEN.Easing.Circular.In )
.onUpdate( function () {
self.percentage = this.percentage;
} ).onStart(function() {
this.percentage = 0;
}).onComplete(function(){
if(panelIndex == 0) state = 'forward';
if(panelIndex == panels.length - 1) state = 'back';
if(state == 'forward') {
next();
return false;
};
prev();
});
this.tween.start();
}
setPercentage(percentage = 0){
this.percentage = percentage;
}
reset(){
this.percentage = 0;
this.radialPercentage = 0;
}
start(){
this.pause = false;
this.tween.start();
}
stop(){
this.pause = true;
this.tween.stop();
}
}
class APP{
constructor(){
this.loader = new Loader();
//set the right size on start
for (let i = 0; i < panels.length; i++) {
panels[i].canvas.width = panels[i].container.width();
};
requestAnimationFrame(this.step.bind(this));
}
update(){
start = (panels[panelIndex].canvas.width / 2) - 100;
end = (panels[panelIndex].canvas.width / 2) + 100;
barSize = (panels[panelIndex].canvas.width * this.loader.percentage) - start;
per = ((barSize) / (end - start));
this.loader.radialPercentage = (per);
}
draw(){
panels[panelIndex].ctx.save();
panels[panelIndex].ctx.strokeStyle = panels[panelIndex].color;
panels[panelIndex].ctx.fillStyle = panels[panelIndex].color;
panels[panelIndex].ctx.fillRect(0, (panels[panelIndex].canvas.height / 2) - 2, panels[panelIndex].canvas.width * this.loader.percentage, 4);
panels[panelIndex].ctx.translate(panels[panelIndex].canvas.width / 2, panels[panelIndex].canvas.height / 2);
panels[panelIndex].ctx.rotate(180 * TO_RAD);
panels[panelIndex].ctx.translate(-(panels[panelIndex].canvas.width / 2), -(panels[panelIndex].canvas.height / 2));
panels[panelIndex].ctx.lineWidth = 4;
panels[panelIndex].ctx.beginPath();
panels[panelIndex].ctx.arc(panels[panelIndex].canvas.width / 2, panels[panelIndex].canvas.height / 2, 102, 0, (Math.PI) * Math.max(0, Math.min(1, this.loader.radialPercentage)), false);
panels[panelIndex].ctx.stroke();
panels[panelIndex].ctx.beginPath();
panels[panelIndex].ctx.globalCompositeOperation = 'destination-out';
panels[panelIndex].ctx.arc(panels[panelIndex].canvas.width / 2, panels[panelIndex].canvas.height / 2, 100, 0, PI_TWO, false);
panels[panelIndex].ctx.closePath();
panels[panelIndex].ctx.fill();
panels[panelIndex].ctx.restore();
}
step(){
requestAnimationFrame(this.step.bind(this));
var delta = Date.now() - this.lastTick;
this.lastTick = Date.now();
var dt = delta / 1000;
this.elapsed = dt;
TWEEN.update();
panels[panelIndex].ctx.clearRect(0,0,panels[panelIndex].canvas.width, panels[panelIndex].canvas.height);
this.update();
this.draw();
}
}
const app = new APP();
View Compiled
This Pen doesn't use any external CSS resources.