<div class="container">
<section class="section hero"></section>
<section class="section two"></section>
<section class="section three"></section>
</div>
body {
margin: 0;
}
.section {
min-height: 100vh;
}
.hero {
position: relative;
overflow: hidden;
}
.hero > canvas {
top: 0;
left: 0;
width: 100%;
height: 100%;
position: absolute;
}
.two {
background-color: darkcyan;
}
.three {
background-color: darkorange;
}
gsap.registerPlugin(ScrollTrigger);
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
const hero = document.querySelector(".hero");
// PIXI ======================
const glitchFilterHor = new PIXI.filters.GlitchFilter({
fillMode: PIXI.filters.GlitchFilter.MIRROR,
slices: 128,
offset: 0,
average: true
});
const glitchFilterVert = new PIXI.filters.GlitchFilter({
fillMode: PIXI.filters.GlitchFilter.MIRROR,
slices: 64,
offset: 0,
direction: 90,
average: true
});
const RGBSplitFilter = new PIXI.filters.RGBSplitFilter([0, 0], [0, 0], [0, 0]);
RGBSplitFilter.padding = 20;
const blurFilter = new PIXI.filters.BlurFilter(0);
blurFilter.padding = 20;
const app = new PIXI.Application({
resizeTo: hero,
transparent: true
});
hero.appendChild(app.view);
const text = new PIXI.Text("This is\na PixiJS text", {
fontFamily: "Arial",
fontSize: 48,
fontWeight: 900,
fill: 0xffffff,
align: "center"
});
text.anchor.set(0.5);
text.filters = [RGBSplitFilter, blurFilter];
const background = PIXI.Sprite.from(
"https://images.unsplash.com/photo-1516125073169-9e3ecdee83e7?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=750&q=80"
);
background.anchor.set(0.5);
background.tint = 0x777777;
background.filters = [glitchFilterVert, glitchFilterHor];
app.stage.addChild(background);
app.stage.addChild(text);
app.ticker.add((delta) => {
app.resize();
text.x = app.screen.width / 2;
text.y = app.screen.height / 2;
background.x = app.screen.width / 2;
background.y = app.screen.height / 2;
const scale = coverImage(
app.screen.width,
app.screen.height,
background.texture.baseTexture.width,
background.texture.baseTexture.height
);
background.scale.set(scale);
});
// GSAP ======================
ScrollTrigger.create({
trigger: hero,
start: "top top",
end: "+=100%",
pin: true
});
const heroPin = hero.closest(".pin-spacer");
let pSpeed = 0;
let prevProgress = 0;
let currProgress = 0;
gsap.ticker.add(() => {
pSpeed = clamp(currProgress - prevProgress, -0.01, 0.01) / 0.01;
prevProgress = currProgress;
});
const simplex = new SimplexNoise();
gsap.to(
{},
{
ease: "none",
scrollTrigger: {
trigger: heroPin,
start: "top top",
end: "+=200%",
scrub: 2
// markers: true
},
onUpdate() {
currProgress = this.progress();
const distort = simplex.noise2D((pSpeed * 4) % 4, 0);
RGBSplitFilter.red = [-8 * pSpeed, 0];
RGBSplitFilter.blue = [6 * pSpeed, 0];
blurFilter.blur = Math.abs(pSpeed);
glitchFilterHor.offset = 64 * distort;
glitchFilterHor.red = [-16 * distort, 0];
glitchFilterHor.blue = [8 * distort, 0];
glitchFilterVert.offset = -8 * distort;
}
}
);
function coverImage(targetWidth, targetHeight, imageWidth, imageHeight) {
const rx = targetWidth / imageWidth;
const ry = targetHeight / imageHeight;
const scale = Math.max(rx, ry);
return scale;
}
This Pen doesn't use any external CSS resources.