Skip to content

Instantly share code, notes, and snippets.

@moelle89
Created June 8, 2022 16:27
Show Gist options
  • Save moelle89/9ea483f409fc50085404e9a1d60e864a to your computer and use it in GitHub Desktop.
Save moelle89/9ea483f409fc50085404e9a1d60e864a to your computer and use it in GitHub Desktop.
Slider RB
<!----- loading overlay ----->
<div class="loading-overlay">
<div class="loading__line loading__line-1"></div>
<div class="loading__line loading__line-2"></div>
</div>
<!----- main container ----->
<div class="container">
<!----- navbar ----->
<nav class="main-nav">
<span class="name__nav link-active">Alain Barrios</span>
<span class="all-stories__nav link-active">All Stories<span class="icon-plus"></span></span>
<div class="main-menu">
<button class="button-menu link-active">
<a class="button-menu__text">Menu</a>
<div class="button-menu__lines">
<span class="button-menu__line"></span>
<span class="button-menu__line"></span>
<span class="button-menu__line"></span>
</div>
</button>
</div>
</nav>
<!----- slider content ----->
<div class="slider-content">
<div class="slider__item">
<img src="https://i.ibb.co/B2gwhKV/shea-rouda-m-RQk1-B4-OM0k-unsplash.jpg" alt="" class="slider__image">
<div class="slider__grid">
<div class="slider__grid-horizontal">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
<div class="slider__grid-vertical">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
</div>
<div class="slider__text-content">
<div class="slider__title" data-splitting>Right Out of the Gate</div>
<div class="slider__names">Chris & Claire</div>
<a href="#" class="slider__explorer link-active">explorer <span class="icon-plus"></span></a>
</div>
</div>
<div class="slider__item">
<img src="https://i.ibb.co/6vZ4wxP/everton-vila-Ueca-Ggu-AV1-M-unsplash.jpg" alt="" class="slider__image">
<div class="slider__grid">
<div class="slider__grid-horizontal">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
<div class="slider__grid-vertical">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
</div>
<div class="slider__text-content">
<div class="slider__title" data-splitting>Needle In a Haystack</div>
<div class="slider__names">Fredrick & Saundra</div>
<a href="#" class="slider__explorer link-active">explorer <span class="icon-plus"></span></a>
</div>
</div>
<div class="slider__item">
<img src="https://i.ibb.co/zVy3zK5/daniel-frank-jqvd-Db-Xo-DI-unsplash.jpg" alt="" class="slider__image">
<div class="slider__grid">
<div class="slider__grid-horizontal">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
<div class="slider__grid-vertical">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
</div>
<div class="slider__text-content">
<div class="slider__title" data-splitting>Lovey Dovey</div>
<div class="slider__names">Ashlee Mullins</div>
<a href="#" class="slider__explorer link-active">explorer <span class="icon-plus"></span></a>
</div>
</div>
<div class="slider__item">
<img src="https://i.ibb.co/XbPK30j/jacob-rank-p-GKyqck99cg-unsplash.jpg" alt="" class="slider__image">
<div class="slider__grid">
<div class="slider__grid-horizontal">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
<div class="slider__grid-vertical">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
</div>
<div class="slider__text-content">
<div class="slider__title" data-splitting>You Can't Judge a Book</div>
<div class="slider__names">Sherman Wilkins</div>
<a href="#" class="slider__explorer link-active">explorer <span class="icon-plus"></span></a>
</div>
</div>
<div class="slider__item">
<img src="https://i.ibb.co/nDV7X1P/joao-silas-a-Kz-Ja-Pk6b-J0-unsplash.jpg" alt="" class="slider__image">
<div class="slider__grid">
<div class="slider__grid-horizontal">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
<div class="slider__grid-vertical">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
</div>
<div class="slider__text-content">
<div class="slider__title" data-splitting>Drawing a Blank</div>
<div class="slider__names">Vance & Ericka</div>
<a href="#" class="slider__explorer link-active">explorer <span class="icon-plus"></span></a>
</div>
</div>
<div class="slider__item">
<img src="https://i.ibb.co/TKXkNDH/joel-overbeck-f-GPGd9-PFd3w-unsplash.jpg" alt="" class="slider__image">
<div class="slider__grid">
<div class="slider__grid-horizontal">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
<div class="slider__grid-vertical">
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
<div class="slider__grid-item"></div>
</div>
</div>
<div class="slider__text-content">
<div class="slider__title" data-splitting>Read 'Em and Weep</div>
<div class="slider__names">Theron & Nicole</div>
<a href="#" class="slider__explorer link-active">explorer<span class="icon-plus"></span></a>
</div>
</div>
</div>
<!----- slider numbers target ----->
<div class="slider-bottom">
<div class="slider__numbers-target">
<div class="slider__number-target">
1
</div>
<div class="slider__number-target">
2
</div>
<div class="slider__number-target">
3
</div>
<div class="slider__number-target">
4
</div>
<div class="slider__number-target">
5
</div>
<div class="slider__number-target">
6
</div>
</div>
<div class="slider-bottom__line-progress">
</div>
</div>
</div>
<div class="cursor">
</div>
class Cursor {
constructor() {
this.cursor = document.querySelector(".cursor");
this.linkActive = document.querySelectorAll(".link-active");
this.boundCursor = {
width: this.cursor.getBoundingClientRect().width / 2,
height: this.cursor.getBoundingClientRect().height / 2
};
this.moveCursor = this.moveCursor.bind(this);
this.onMouseEnter = this.onMouseEnter.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);
this.initEvents();
}
initEvents() {
window.addEventListener("mousemove", this.moveCursor);
this.linkActive.forEach((item) => {
item.addEventListener("mouseenter", this.onMouseEnter);
});
this.linkActive.forEach((item) => {
item.addEventListener("mouseleave", this.onMouseLeave);
});
}
onMouseEnter() {
gsap.to(this.cursor, {
duration: 0.3,
scale: 3,
opacity: 0.5
});
}
onMouseLeave() {
gsap.to(this.cursor, {
duration: 0.3,
scale: 1,
opacity: 1
});
}
moveCursor({ clientX: x, clientY: y }) {
gsap.to(this.cursor, {
duration: 0.3,
x: x - this.boundCursor.width,
y: y - this.boundCursor.height
});
}
}
class LoadingOverlay {
constructor() {
this.overlay = document.querySelector(".loading-overlay");
this.loadingLine = this.overlay.children;
this.heightBound = this.overlay.getBoundingClientRect().height;
this.imagesInWeb = document.querySelectorAll("img");
this.imageLength = this.imagesInWeb.length;
this.imageLoaded = 0;
this.removeOverlayCompleted = false;
this.tlRemoveOverlay = gsap.timeline({
onComplete: () => (this.removeOverlayCompleted = true)
});
this.loadElements();
}
loadElements() {
const split = Splitting({ whitespace: true });
this.imagesInWeb.forEach((image, i) => {
const img = new Image();
img.src = image.src;
img.addEventListener("load", () => {
this.imageLoaded++;
const heightLine =
this.heightBound /
(this.imageLength + 1 - this.imageLoaded) /
this.heightBound;
this.tlRemoveOverlay.to(this.loadingLine[0], {
duration: 0.05,
scaleY: heightLine,
scaleX: 1
});
if (this.imageLoaded == this.imageLength) {
const slider = new Slider(split);
this.enterSlider(slider, heightLine);
}
});
});
}
enterSlider(slider, heightLine) {
const gridHorizontal = slider.gridLines[0].children[0].children;
const gridVertical = slider.gridLines[0].children[1].children;
this.tlRemoveOverlay
.to(
this.loadingLine,
{
duration: 1,
y: `${-heightLine * 100}%`,
ease: "expo.inOut"
},
"+=0.8"
)
.to(
this.overlay,
{
duration: 1.2,
y: `${-heightLine * 100}%`,
ease: "expo.inOut"
},
"-=0.8"
)
.from(
slider.slideImages[0],
{
duration: 1,
scale: 1.1
},
"-=1"
)
.from(
gridHorizontal,
{
duration: 0.8,
scaleX: 0,
transformOrigin: "0 50%",
stagger: 0.1,
ease: "expo.inOut"
},
"-=1"
)
.from(
gridVertical,
{
duration: 0.8,
scaleY: 0,
transformOrigin: "50% 100%",
stagger: 0.05,
ease: "expo.inOut"
},
"-=1"
)
.from(
gridHorizontal,
{
duration: 0.5,
opacity: 0.3,
stagger: 0.1,
ease: "expo.out"
},
"-=0.7"
)
.from(
gridVertical,
{
duration: 0.5,
opacity: 0.3,
stagger: 0.05,
ease: "expo.out"
},
"-=0.7"
)
.from(
slider.splitTitle[0].chars,
{
duration: 1,
y: "100%",
opacity: 0,
ease: "expo.out",
stagger: 0.04
},
"-=1"
)
.from(
slider.textContent[0],
{
duration: 1,
opacity: 0,
stagger: 0.1
},
"-=0.5"
)
.from(
slider.splitTitle[0],
{
duration: 0.5,
y: "100%",
opacity: 0,
ease: "expo.out",
stagger: 0.02
},
"-=1"
);
}
}
class Slider {
constructor(splitTitle) {
this.sliderContent = document.querySelector(".slider-content");
this.sliderItems = Array.from(this.sliderContent.children);
this.textContent = this.sliderItems.map((item) => {
const [child1, child2, child3] = item.children[2].children;
return [child2, child3];
});
this.slideImages = this.sliderItems.map((item) => item.children[0]);
this.gridLines = this.sliderItems.map((item) => item.children[1]);
this.sliderBottom = document.querySelector(".slider-bottom");
this.numbers = Array.from(
this.sliderBottom.querySelectorAll(".slider__number-target")
);
this.lineProgress = this.sliderBottom.querySelector(
".slider-bottom__line-progress"
);
this.lineProgress.style.transform = `scaleX(${
this.numbers[0].getBoundingClientRect().width /
this.sliderBottom.getBoundingClientRect().width
})`;
this.itemsLength = this.sliderItems.length;
this.splitTitle = splitTitle.map((item) => {
return item.chars.sort(() => 0.4 - Math.random());
});
this.index = {
next: 0,
last: 0
};
this.animationEnd = false;
this.tl = gsap.timeline();
this.slideMove = this.slideMove.bind(this);
this.initEvents();
}
initEvents() {
window.addEventListener("mousewheel", this.slideMove);
window.addEventListener("keyup", this.slideMove);
window.addEventListener("touchmove", this.slideMove);
}
getIndex(index, deltaY) {
const increment = deltaY > 0 ? index + 1 : index - 1;
const fixedIndex =
increment < 0 ? this.itemsLength - 1 : increment % this.itemsLength;
return fixedIndex;
}
getWidthLine() {
let acc = 0;
for (let i = 0; i <= this.index.next; i++) {
const bounding = this.numbers[i].getBoundingClientRect().width;
acc += bounding;
}
acc /= this.sliderBottom.getBoundingClientRect().width;
return acc;
}
detectDevice(e) {
let value = false;
if (e.deltaY) {
value = Math.sign(e.deltaY);
} else if (e.keyCode === 37) {
value = -1;
} else if (e.keyCode === 39) {
value = 1;
}
return value;
}
slideMove(e) {
const deltaY = this.detectDevice(e);
if (!deltaY) return;
if (this.animationEnd) return;
this.animationEnd = true;
this.index.next = this.getIndex(this.index.next, deltaY);
const gridHorizontal = this.gridLines[this.index.next].children[0].children;
const gridVertical = this.gridLines[this.index.next].children[1].children;
const widthLine = this.getWidthLine();
this.tl
.set(this.sliderItems[this.index.next], {
zIndex: 2
})
.set(this.sliderItems[this.index.last], {
zIndex: 3
})
.to(
this.sliderItems[this.index.last],
{
duration: 2,
clipPath:
deltaY > 0
? "polygon(-50% 50%, 50% 150%, 50% 150%, -50% 50%)"
: "polygon(50% -50%, 150% 50%, 150% 50%, 50% -50%)",
ease: "expo.inOut"
},
"-=intro"
)
.to(
this.lineProgress,
{
duration: 0.5,
scaleX: widthLine,
ease: "expo.inOut"
},
"-=1.5"
)
.from(
this.slideImages[this.index.next],
{
duration: 1,
scale: 1.1
},
"-=1"
)
.from(
gridHorizontal,
{
duration: 0.8,
scaleX: 0,
transformOrigin: deltaY > 0 ? "100% 50%" : "0 50%",
stagger: 0.1,
ease: "expo.inOut"
},
"-=1"
)
.from(
gridVertical,
{
duration: 0.8,
scaleY: 0,
transformOrigin: deltaY > 0 ? "50% 0" : "50% 100%",
stagger: 0.05,
ease: "expo.inOut"
},
"-=1"
)
.from(
gridHorizontal,
{
duration: 0.5,
opacity: 0.3,
stagger: 0.1,
ease: "expo.out"
},
"-=0.7"
)
.from(
gridVertical,
{
duration: 0.5,
opacity: 0.3,
stagger: 0.05,
ease: "expo.out"
},
"-=0.7"
)
.from(
this.splitTitle[this.index.next],
{
duration: 1,
y: "100%",
opacity: 0,
ease: "expo.out",
stagger: 0.02
},
"-=1"
)
.from(
this.textContent[this.index.next],
{
duration: 1,
opacity: 0,
stagger: 0.1
},
"-=0.5"
)
.set(this.sliderItems[this.index.last], {
clipPath: "polygon(50% -50%, 150% 50%, 50% 150%, -50% 50%)",
zIndex: 1,
onComplete: () => {
this.index.last = this.index.next;
this.animationEnd = false;
}
});
}
}
new Cursor();
new LoadingOverlay();
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js"></script>
<script src="https://unpkg.com/splitting/dist/splitting.min.js"></script>
@font-face {
font-family: Prestage;
src: url(https://rawcdn.githack.com/AlainBarrios/Fonts/56300fca5559c17ab45c3e6187d3e0c19a62a9f1/Prestage Regular.otf?raw=true);
}
@font-face {
font-family: PlayfairDisplay;
src: url(https://rawcdn.githack.com/AlainBarrios/Fonts/56300fca5559c17ab45c3e6187d3e0c19a62a9f1/BodoniFLF-Roman.ttf?raw=true);
}
*,
*::before,
*::after {
box-sizing: border-box;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-kerning: auto;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
font-family: Prestage;
text-transform: uppercase;
overflow: hidden;
cursor: none;
}
img {
max-width: 100%;
display: block;
}
a{
text-decoration: none;
}
button {
outline: none;
border: 0;
background-color: transparent;
cursor: none;
font-size: 14px;
font-family: Prestage;
}
.cursor{
position: absolute;
top: 0;
left: 0;
width: 15px;
height: 15px;
background-color: rgb(255, 63, 63);
z-index: 100;
border-radius: 50%;
pointer-events: none;
}
.loading-overlay{
background-color: rgb(27, 27, 27);
z-index: 50;
position: fixed;
left: 0;
width: 100%;
height: 100vh;
top: 0;
}
.loading__line{
position: absolute;
left: calc(50% - 1px);
top: 0%;
width: 2px;
height: 100%;
transform-origin: 50% 100%;
}
.loading__line-1{
transform: scale(0, 0);
background-color: rgba(194, 199, 195, 1);
z-index: 10
}
.loading__line-2{
background-color: rgba(194, 199, 195, 0.5);
}
.container {
position: relative;
height: 100vh;
}
/***** navbar *****/
.main-nav {
position: fixed;
width: 100%;
height: 104px;
left: 0;
top: 0;
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 5%;
padding-right: 5%;
text-transform: uppercase;
z-index: 20;
}
.main-nav .button-menu {
display: flex;
width: 100px;
justify-content: space-between;
align-items: center;
}
.main-nav .name__nav,.main-nav .all-stories__nav,.main-nav .main-menu{
margin-left: 2%;
margin-right: 2%;
}
.icon-plus{
width: 15px;
height: 15px;
margin-left: 5px;
display: inline-block;
position: relative;
}
.all-stories__nav .icon-plus:before, .all-stories__nav .icon-plus:after{
content: "";
position: absolute;
left: 0;
top: 0;
background-color: rgb(255, 255, 255);
}
.all-stories__nav .icon-plus:before{
left: calc(50% - 0.5px);
width: 1px;
height: 100%;
}
.all-stories__nav .icon-plus:after{
top: calc(50% - 0.5px);
width: 100%;
height: 1px;
}
.main-nav,
.main-nav .button-menu {
font-size: 1.2rem;
letter-spacing: 0.3rem;
color: rgb(255, 255, 255);
}
.main-nav .button-menu__lines {
display: flex;
height: 20px;
width: 20px;
justify-content: space-between;
}
.main-nav .button-menu__line {
display: block;
width: 1px;
height: 100%;
background-color: rgb(255, 255, 255);
}
.slider-content {
position: relative;
height: 100%;
}
.slider__item {
display: flex;
justify-content: center;
clip-path: polygon(50% -50%, 150% 50%, 50% 150%, -50% 50%);
align-items: center;
}
.slider__item:nth-child(1) {
z-index: 2;
}
.slider__item:nth-child(2) {
z-index: 1;
}
.slider__item,
.slider__image {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.slider__image {
object-fit: cover;
pointer-events: none;
object-position: center;
}
.slider__text-content {
text-align: center;
z-index: 20;
color: rgb(255, 255, 255);
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.slider__title,
.slider__names,
.slider__explorer {
position: relative;
}
.slider__title {
letter-spacing: 1.2rem;
font-size: 5vmax;
top: 40px;
font-family: PlayfairDisplay;
overflow: hidden;
padding-left: 15px;
padding-right: 15px;
}
.slider__title .word{
display: inline-block;
margin-bottom: 20px;
overflow: hidden;
}
.slider__title .char{
display: inline-block;
}
.slider__names {
top: 80px;
}
.slider__explorer {
color: rgb(255, 63, 63);
top: 130px;
font-size: 1.3rem;
display: flex;
align-items: center;
cursor: none;
}
.slider__names,
.slider__explorer {
letter-spacing: 0.5rem;
}
.slider__explorer .icon-plus:before, .slider__explorer .icon-plus:after{
content: "";
position: absolute;
left: 0;
top: 0;
background-color: rgb(255, 63, 63);
}
.slider__explorer .icon-plus:before{
left: calc(50% - 0.5px);
width: 1px;
height: 100%;
}
.slider__explorer .icon-plus:after{
top: calc(50% - 0.5px);
width: 100%;
height: 1px;
}
.slider__item:before {
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgb(0, 0, 0);
opacity: 0.6;
overflow: hidden;
z-index: 10;
}
.slider-bottom {
position: fixed;
width: 100%;
color: rgb(255, 255, 255);
bottom: 0;
left: 0;
z-index: 20;
}
.slider__numbers-target {
position: relative;
display: flex;
justify-content: space-between;
text-align: center;
padding-top: 15px;
padding-bottom: 15px;
}
/**** numbers target ****/
.slider__number-target:nth-child(1) {
width: 15.2%;
}
.slider__number-target:nth-child(2) {
width: 30%;
}
.slider__number-target:nth-child(3) {
width: 30%;
}
.slider__number-target:nth-child(4) {
width: 30%;
}
.slider__number-target:nth-child(5) {
width: 30%;
}
.slider__number-target:nth-child(6) {
width: 15.2%;
}
.slider-bottom__line-progress {
height: 2px;
background-color: rgb(255, 255, 255);
}
.slider__grid {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: grid;
grid-template-areas: "center";
}
.slider__grid-vertical,
.slider__grid-horizontal {
position: relative;
z-index: 10;
grid-area: center;
}
.slider__grid-item {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgb(255, 255, 255);
}
.slider__grid-vertical .slider__grid-item {
width: 1px;
height: 100%;
opacity: 0.1;
}
.slider__grid-horizontal .slider__grid-item {
width: 100%;
height: 1px;
opacity: 0.1;
}
.slider-bottom__line-progress{
transform-origin: 0 50%;
}
/**** horizontal lines ****/
.slider__grid-vertical .slider__grid-item:nth-child(1) {
left: 10%;
display: none;
}
.slider__grid-vertical .slider__grid-item:nth-child(2) {
left: 20%;
}
.slider__grid-vertical .slider__grid-item:nth-child(3) {
left: 50%;
}
.slider__grid-vertical .slider__grid-item:nth-child(4) {
left: 80%;
}
.slider__grid-vertical .slider__grid-item:nth-child(5) {
left: 90%;
display: none;
}
/**** vertica lines ****/
.slider__grid-horizontal .slider__grid-item:nth-child(1) {
top: 20%;
}
.slider__grid-horizontal .slider__grid-item:nth-child(2) {
top: 50%;
}
.slider__grid-horizontal .slider__grid-item:nth-child(3) {
top: 80%;
}
@media screen and (min-width: 600px) {
.icon-plus{
width: 20px;
height: 20px;
}
.main-nav,
.main-nav .button-menu {
font-size: 1.5rem;
}
.slider__title{
padding-left: 30px;
padding-right: 30px;
}
.slider__names {
top: 70px;
font-size: 1.3rem;
}
.slider__explorer {
font-size: 1.6rem;
top: 120px;
}
.slider__grid-vertical .slider__grid-item:nth-child(1) {
left: 10%;
display: block;
}
.slider__grid-vertical .slider__grid-item:nth-child(2) {
left: 30%;
}
.slider__grid-vertical .slider__grid-item:nth-child(3) {
left: 50%;
}
.slider__grid-vertical .slider__grid-item:nth-child(4) {
left: 70%;
}
.slider__grid-vertical .slider__grid-item:nth-child(5) {
left: 90%;
display: block;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment