Skip to content

Instantly share code, notes, and snippets.

@Pocztadoai
Created June 19, 2025 19:40
Show Gist options
  • Save Pocztadoai/6ef34ec27266404dd70dd18370c23852 to your computer and use it in GitHub Desktop.
Save Pocztadoai/6ef34ec27266404dd70dd18370c23852 to your computer and use it in GitHub Desktop.
Hero :: Easeljs
<script src="https://code.createjs.com/1.0.0/easeljs.min.js"></script>
<div class="hero-container">
<canvas id="heroCanvas"></canvas>
<div class="content-overlay">
<div class="cta-container">
<a href="#" class="cta-button primary-cta">Get Started</a>
<a href="#" class="cta-button secondary-cta">Learn More</a>
</div>
</div>
<div class="scroll-indicator">
<div class="mouse-icon"></div>
<span>Scroll to explore</span>
</div>
</div>
class Particle {
constructor(x, y, stage) {
this.homeX = x;
this.homeY = y;
this.x = x + (Math.random() - 0.5) * 500;
this.y = y + (Math.random() - 0.5) * 500;
this.vx = 0;
this.vy = 0;
this.size = Math.random() * 3 + 1;
this.alpha = 0;
this.stage = stage;
this.shape = new createjs.Shape();
this.shape.graphics.beginFill("#ffffff").drawCircle(0, 0, this.size);
this.shape.x = this.x;
this.shape.y = this.y;
this.shape.alpha = 0;
stage.addChild(this.shape);
}
update(mouseX, mouseY, introComplete) {
if (!introComplete) {
this.alpha = Math.min(1, this.alpha + 0.02);
const dx = this.homeX - this.x;
const dy = this.homeY - this.y;
this.vx = dx * 0.05;
this.vy = dy * 0.05;
} else {
const dx = mouseX - this.homeX;
const dy = mouseY - this.homeY;
const distance = Math.sqrt(dx * dx + dy * dy);
const maxDistance = 100;
if (distance < maxDistance) {
const force = (maxDistance - distance) / maxDistance;
const angle = Math.atan2(dy, dx);
this.vx = -Math.cos(angle) * force * 20;
this.vy = -Math.sin(angle) * force * 20;
} else {
this.vx *= 0.95;
this.vy *= 0.95;
}
const returnX = (this.homeX - this.x) * 0.05;
const returnY = (this.homeY - this.y) * 0.05;
this.vx += returnX;
this.vy += returnY;
}
this.x += this.vx;
this.y += this.vy;
this.vx *= 0.95;
this.vy *= 0.95;
this.shape.x = this.x;
this.shape.y = this.y;
this.shape.alpha = this.alpha;
}
}
class BackgroundParticle {
constructor(stage) {
this.x = Math.random() * stage.canvas.width;
this.y = Math.random() * stage.canvas.height;
this.z = Math.random() * 0.5 + 0.5;
this.vx = (Math.random() - 0.5) * 0.5;
this.vy = (Math.random() - 0.5) * 0.5;
this.size = Math.random() * 2 + 0.5;
this.shape = new createjs.Shape();
this.shape.graphics
.beginFill("rgba(255,255,255,0.3)")
.drawCircle(0, 0, this.size * this.z);
this.shape.x = this.x;
this.shape.y = this.y;
this.shape.alpha = this.z * 0.5;
stage.addChild(this.shape);
}
update(mouseX, mouseY, stageWidth, stageHeight) {
const parallaxX = (mouseX - stageWidth / 2) * 0.02 * this.z;
const parallaxY = (mouseY - stageHeight / 2) * 0.02 * this.z;
this.x += this.vx + parallaxX;
this.y += this.vy + parallaxY;
if (this.x < -10) this.x = stageWidth + 10;
if (this.x > stageWidth + 10) this.x = -10;
if (this.y < -10) this.y = stageHeight + 10;
if (this.y > stageHeight + 10) this.y = -10;
this.shape.x = this.x;
this.shape.y = this.y;
}
}
let stage,
textContainer,
particles = [],
backgroundParticles = [],
mouseX = 0,
mouseY = 0;
let introComplete = false,
resizeTimeout = null;
function init() {
const canvas = document.getElementById("heroCanvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
stage = new createjs.Stage(canvas);
stage.enableMouseOver(20);
createjs.Touch.enable(stage);
createBackgroundParticles();
createTextParticles();
stage.on("stagemousemove", handleMouseMove);
createjs.Ticker.framerate = 60;
createjs.Ticker.addEventListener("tick", update);
setTimeout(() => {
introComplete = true;
}, 2000);
window.addEventListener("resize", handleResize);
}
function createBackgroundParticles() {
const particleCount = 100;
for (let i = 0; i < particleCount; i++) {
backgroundParticles.push(new BackgroundParticle(stage));
}
}
function createTextParticles() {
textContainer = new createjs.Container();
stage.addChild(textContainer);
const text1 = new createjs.Text("INNOVATE", "bold 120px Arial", "#ffffff");
const text2 = new createjs.Text("BEYOND LIMITS", "300 60px Arial", "#ffffff");
text1.textAlign = "center";
text2.textAlign = "center";
const tempContainer = new createjs.Container();
tempContainer.addChild(text1);
tempContainer.cache(-600, -80, 1200, 160);
const bounds1 = text1.getBounds();
const centerX = stage.canvas.width / 2;
const centerY = stage.canvas.height / 2 - 60;
for (let x = -bounds1.width / 2; x < bounds1.width / 2; x += 6) {
for (let y = -bounds1.height / 2; y < bounds1.height / 2; y += 6) {
const pixel = tempContainer.cacheCanvas
.getContext("2d")
.getImageData(x + 600, y + 80, 1, 1).data;
if (pixel[3] > 128) {
particles.push(new Particle(centerX + x, centerY + y, textContainer));
}
}
}
tempContainer.removeAllChildren();
text2.x = 0;
text2.y = 0;
tempContainer.addChild(text2);
tempContainer.cache(-600, -80, 1200, 160);
const bounds2 = text2.getBounds();
const centerY2 = centerY + 150;
for (let x = -bounds2.width / 2; x < bounds2.width / 2; x += 5) {
for (let y = -bounds2.height / 2; y < bounds2.height / 2; y += 5) {
const pixel = tempContainer.cacheCanvas
.getContext("2d")
.getImageData(x + 600, y + 110, 1, 1).data;
if (pixel[3] > 128) {
particles.push(new Particle(centerX + x, centerY2 + y, textContainer));
}
}
}
}
function handleMouseMove(event) {
mouseX = event.stageX;
mouseY = event.stageY;
}
function update() {
backgroundParticles.forEach((particle) => {
particle.update(mouseX, mouseY, stage.canvas.width, stage.canvas.height);
});
particles.forEach((particle) => {
particle.update(mouseX, mouseY, introComplete);
});
stage.update();
}
function handleResize() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(() => {
const oldWidth = stage.canvas.width;
const oldHeight = stage.canvas.height;
stage.canvas.width = window.innerWidth;
stage.canvas.height = window.innerHeight;
const scaleX = window.innerWidth / oldWidth;
const scaleY = window.innerHeight / oldHeight;
particles.forEach((particle) => {
particle.homeX *= scaleX;
particle.homeY *= scaleY;
particle.x *= scaleX;
particle.y *= scaleY;
});
stage.update();
}, 250);
}
document.addEventListener("DOMContentLoaded", init);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #0a0a0a;
overflow-x: hidden;
}
.hero-container {
position: relative;
width: 100%;
height: 100vh;
min-height: 600px;
display: flex;
align-items: center;
justify-content: center;
}
canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.content-overlay {
position: relative;
z-index: 10;
text-align: center;
pointer-events: none;
}
.cta-container {
margin-top: 40px;
display: flex;
gap: 20px;
justify-content: center;
pointer-events: all;
}
.cta-button {
padding: 15px 40px;
font-size: 16px;
font-weight: 600;
border: none;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-block;
}
.primary-cta {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.primary-cta:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
}
.secondary-cta {
background: transparent;
color: white;
border: 2px solid rgba(255, 255, 255, 0.3);
}
.secondary-cta:hover {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.5);
}
.scroll-indicator {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
color: rgba(255, 255, 255, 0.5);
font-size: 14px;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
animation: bounce 2s infinite;
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateX(-50%) translateY(0);
}
40% {
transform: translateX(-50%) translateY(-10px);
}
60% {
transform: translateX(-50%) translateY(-5px);
}
}
.mouse-icon {
width: 25px;
height: 40px;
border: 2px solid rgba(255, 255, 255, 0.5);
border-radius: 15px;
position: relative;
}
.mouse-icon::after {
content: "";
width: 3px;
height: 10px;
background: rgba(255, 255, 255, 0.5);
position: absolute;
top: 8px;
left: 50%;
transform: translateX(-50%);
animation: scroll 1.5s infinite;
}
@keyframes scroll {
0% {
opacity: 1;
top: 8px;
}
100% {
opacity: 0;
top: 20px;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment