How to Build Awesome infinity random Image Gallery Using Javascript Module All Free Code Here:
Today I wanna build something amazing random image Gallery Using HTML CSS and Javascript Module
You can watch Full Video Here: https://youtu.be/Z8tS1c9jWL8
HTML code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Random Image</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<ul>
<li class="a"> <img src="body.jpg" /> </li>
<li class="b"><img src="book.jpg" /></li>
<li class="c"><img src="boy.jpg" /></li>
<li class="d"><img src="laptop.jpg" /></li>
<li class="e"><img src="leange.jpg" /></li>
<li class="f"><img src="headphone.jpg" /></li>
<li class="g"><img src="hidden.jpg" /></li>
<li class="h"><img src="gym.jpg" /></li>
<li class="i"><img src="watch.jpg" /></li>
<li class="j"><img src="weson.jpg" /></li>
<li class="k"><img src="zoom.jpg" /></li>
<li class="l"><img src="dslr.jpg" /></li>
<li class="m"><img src="cat.jpg" /></li>
<li class="n"><img src="cube.jpg" /></li>
<li class="o"><img src="iphone.jpg" /></li>
<li class="p"><img src="style.jpg" /></li>
</ul>
<div class="drag-proxy"></div>
<script src="main.js" type="module"></script>
</body>
</html>
CSS code
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
min-height: 100vh;
display: grid;
place-items: center;
overflow-y: hidden;
background: var(--bg);
}
.drag-proxy {
visibility: hidden;
position: absolute;
}
ul {
height: 100vh;
width: 100%;
overflow: hidden;
position: absolute;
transform-style: preserve-3d;
perspective: 800px;
touch-action: none;
padding: 0;
margin: 0;
}
li {
position: absolute;
transform-style: preserve-3d;
top: 50%;
left: 50%;
height: 30vmin;
width: 30vmin;
min-height: 150px;
min-width: 150px;
display: none;
background: #b3f075;
}
img {
position: absolute;
height: 100%;
width: 100%;
-o-object-fit: cover;
object-fit: cover;
}
Javascript Code
import gsap from 'https://cdn.skypack.dev/gsap';
import ScrollTrigger from 'https://cdn.skypack.dev/gsap/ScrollTrigger';
import Draggable from 'https://cdn.skypack.dev/gsap/Draggable';
gsap.registerPlugin(ScrollTrigger);
gsap.registerPlugin(Draggable);
gsap.set('li', {
yPercent: -50
});
const STAGGER = 0.1;
const DURATION = 1;
const OFFSET = 0;
const BOXES = gsap.utils.toArray('li');
const LOOP = gsap.timeline({
paused: true,
repeat: -1,
ease: 'none'
});
const X_START = 200;
const X_FINISH = -300;
const Y_START = -150;
const Y_FINISH = 150;
const BEHAVIORS = new Array(BOXES.length).
fill().
map(() => [
gsap.utils.random(-360, 360),
gsap.utils.random(-360, 360),
gsap.utils.random(Y_START, Y_FINISH),
gsap.utils.random(-360, 360)]);
const HUES = [
'#333536',
'#86644e',
'#6d6a69',
'#c2c3c5',
'#172b2d',
'#fee162',
'#081313',
'#35393b',
'#1b2c56',
'#070b0f',
'#e5d4bb',
'#0b1113',
'#4c4e4d',
'#1e282a',
'#2a2e2c',
'#161f25'];
const SHIFTS = [...BOXES, ...BOXES, ...BOXES];
SHIFTS.forEach((BOX, index) => {
const BOX_TL = gsap.
timeline().
set(BOX, {
xPercent: 250,
opacity: 0,
filter: 'grayscale(1)',
scale: 0.1,
yPercent: () => BEHAVIORS[index % BOXES.length][2],
rotateX: () => BEHAVIORS[index % BOXES.length][0],
rotateY: () => BEHAVIORS[index % BOXES.length][1]
}).
to(
BOX,
{
opacity: 1,
scale: 0.5,
duration: 0.1
},
0).
to(
BOX,
{
opacity: 0,
scale: 0.1,
duration: 0.1
},
0.9).
to(
BOX,
{
filter: 'grayScale(0)',
repeat: 1,
yoyo: true,
duration: 0.1
},
0.4).
fromTo(
BOX,
{
rotateX: () => BEHAVIORS[index % BOXES.length][0],
rotateY: () => BEHAVIORS[index % BOXES.length][1],
rotate: () => BEHAVIORS[index % BOXES.length][2]
},
{
immediateRender: false,
rotateX: () => BEHAVIORS[index % BOXES.length][0] * -1,
rotateY: () => BEHAVIORS[index % BOXES.length][1] * -1,
rotate: () => BEHAVIORS[index % BOXES.length][2] * -1,
duration: 1,
ease: 'power1.inOut'
},
0)
// Panning
.fromTo(
BOX,
{
xPercent: X_START
},
{
xPercent: X_FINISH,
duration: 1,
immediateRender: false,
ease: 'power1.inOut'
},
0).
to(
BOX,
{
yPercent: -50,
duration: 0.5,
immediateRender: false
},
0).
to(
BOX,
{
yPercent: () => (BEHAVIORS[index % BOXES.length][2] + 100) * -1,
immediateRender: false,
duration: 0.5
},
0.5)
// Scale && Z
.to(
BOX,
{
z: 100,
scale: 1,
duration: 0.1,
repeat: 1,
yoyo: true
},
0.4).
fromTo(
BOX,
{
zIndex: 1
},
{
zIndex: BOXES.length,
repeat: 1,
yoyo: true,
ease: 'none',
duration: 0.5,
immediateRender: false
},
0);
LOOP.add(BOX_TL, index * STAGGER);
});
const CYCLE_DURATION = STAGGER * BOXES.length;
const START_TIME = CYCLE_DURATION + DURATION * 0.5 + OFFSET;
const LOOP_HEAD = gsap.fromTo(
LOOP,
{
totalTime: START_TIME
},
{
totalTime: `+=${CYCLE_DURATION}`,
duration: 1,
ease: 'none',
repeat: -1,
paused: true
});
const PLAYHEAD = {
position: 0
};
const POSITION_WRAP = gsap.utils.wrap(0, LOOP_HEAD.duration());
const SCRUB = gsap.to(PLAYHEAD, {
position: 0,
onUpdate: () => {
LOOP_HEAD.totalTime(POSITION_WRAP(PLAYHEAD.position));
},
paused: true,
duration: 0.25,
ease: 'power3'
});
let iteration = 0;
const TRIGGER = ScrollTrigger.create({
start: 0,
end: '+=2000',
horizontal: false,
pin: 'ul',
onUpdate: self => {
const SCROLL = self.scroll();
if (SCROLL > self.end - 1) {
// Go forwards in time
WRAP(1, 1);
} else if (SCROLL < 1 && self.direction < 0) {
// Go backwards in time
WRAP(-1, self.end - 1);
} else {
const NEW_POS = (iteration + self.progress) * LOOP_HEAD.duration();
SCRUB.vars.position = NEW_POS;
SCRUB.invalidate().restart();
}
}
});
const WRAP = (iterationDelta, scrollTo) => {
iteration += iterationDelta;
TRIGGER.scroll(scrollTo);
TRIGGER.update();
};
const SNAP = gsap.utils.snap(1 / BOXES.length);
const progressToScroll = (progress) =>
gsap.utils.clamp(
1,
TRIGGER.end - 1,
gsap.utils.wrap(0, 1, progress) * TRIGGER.end);
const scrollToPosition = position => {
const SNAP_POS = SNAP(position);
const PROGRESS =
(SNAP_POS - LOOP_HEAD.duration() * iteration) / LOOP_HEAD.duration();
const SCROLL = progressToScroll(PROGRESS);
if (PROGRESS >= 1 || PROGRESS < 0) return WRAP(Math.floor(PROGRESS), SCROLL);
gsap.to(document.documentElement, {
'--bg': HUES[PROGRESS * BOXES.length]
});
TRIGGER.scroll(SCROLL);
};
gsap.set(document.documentElement, {
'--bg': HUES[0]
});
ScrollTrigger.addEventListener('scrollEnd', () =>
scrollToPosition(SCRUB.vars.position));
const NEXT = () => scrollToPosition(SCRUB.vars.position - 1 / BOXES.length);
const PREV = () => scrollToPosition(SCRUB.vars.position + 1 / BOXES.length);
document.addEventListener('keydown', event => {
if (event.code === 'ArrowLeft' || event.code === 'KeyA') NEXT();
if (event.code === 'ArrowRight' || event.code === 'KeyD') PREV();
});
document.querySelector('ul').addEventListener('click', e => {
const BOX = e.target.closest('li');
if (BOX) {
let TARGET = BOXES.indexOf(BOX);
let CURRENT = gsap.utils.wrap(
0,
BOXES.length,
Math.floor(BOXES.length * SCRUB.vars.position));
let BUMP = TARGET - CURRENT;
if (TARGET > CURRENT && TARGET - CURRENT > BOXES.length * 0.5) {
BUMP = (BOXES.length - BUMP) * -1;
}
if (CURRENT > TARGET && CURRENT - TARGET > BOXES.length * 0.5) {
BUMP = BOXES.length + BUMP;
}
scrollToPosition(SCRUB.vars.position + BUMP * (1 / BOXES.length));
}
});
gsap.set(BOXES, { display: 'block' });
Draggable.create('.drag-proxy', {
type: 'x',
trigger: 'li',
onPress() {
this.startOffset = SCRUB.vars.position;
},
onDrag() {
SCRUB.vars.position = this.startOffset + (this.startX - this.x) * 0.001;
SCRUB.invalidate().restart(); // same thing as we do in the ScrollTrigger's onUpdate
},
onDragEnd() {
scrollToPosition(SCRUB.vars.position);
}
});


0 Comments