change snowflakes
This commit is contained in:
parent
32e609ad71
commit
1215f2f987
@ -6,8 +6,7 @@ const nextConfig = {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'media.tenor.com',
|
||||
pathname: '/1BCeG1aTiBAAAAAd/temptation-stairway-ena.gif'
|
||||
hostname: 'media.tenor.com'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 55 KiB |
BIN
public/images/event_santahat1.png
Normal file
BIN
public/images/event_santahat1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
public/images/event_snowflake.png
Normal file
BIN
public/images/event_snowflake.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
@ -191,7 +191,7 @@ export const FakeRelativeWindow = ({
|
||||
|
||||
{/* Main window */}
|
||||
<div
|
||||
className={clsx("md:border bg-background border-primary", withAnim && animation.window)}
|
||||
className={clsx("md:border bg-background bg-opacity-50 border-primary", withAnim && animation.window)}
|
||||
style={{
|
||||
transform: `translate(${currentWindow.offset.x}px, ${currentWindow.offset.y}px)`
|
||||
}}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
import { getEvent } from '@/lib/utils';
|
||||
import clsx from 'clsx';
|
||||
import Image from 'next/image';
|
||||
import NextImage from 'next/image';
|
||||
import { ReactNode, useEffect, useRef, useState } from 'react';
|
||||
|
||||
interface Snowflake {
|
||||
@ -13,12 +13,15 @@ interface Snowflake {
|
||||
sway: number;
|
||||
swayOffset: number;
|
||||
opacity: number;
|
||||
rotation: number;
|
||||
rotationSpeed: number;
|
||||
}
|
||||
|
||||
interface ChristmasProps {
|
||||
left: number;
|
||||
top: number;
|
||||
size: number;
|
||||
img: string;
|
||||
className?: string;
|
||||
flip?: boolean;
|
||||
absolute?: boolean;
|
||||
@ -31,9 +34,10 @@ export const ChristmasExclusive = ({ children }: { children: ReactNode }) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
export const ChristmasHat: React.FC<ChristmasProps> = ({
|
||||
export const ChristmasProperty: React.FC<ChristmasProps> = ({
|
||||
left,
|
||||
top,
|
||||
img,
|
||||
size,
|
||||
className,
|
||||
flip
|
||||
@ -46,12 +50,13 @@ export const ChristmasHat: React.FC<ChristmasProps> = ({
|
||||
left, top
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
<NextImage
|
||||
className='pointer-events-none'
|
||||
src={'/images/event_santahat01.png'}
|
||||
alt='Santa Hat'
|
||||
src={img}
|
||||
alt='Christmas prop'
|
||||
height={size}
|
||||
width={size}
|
||||
unoptimized={img.slice(img.length - 3, img.length) == 'gif'}
|
||||
/>
|
||||
</div>
|
||||
</ChristmasExclusive>
|
||||
@ -63,8 +68,8 @@ function SnowfallRawBackground() {
|
||||
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
|
||||
const snowflakesRef = useRef<Snowflake[]>([]);
|
||||
const animationFrameRef = useRef<number>(0);
|
||||
const imageRef = useRef<HTMLImageElement | null>(null);
|
||||
|
||||
// Update dimensions on resize
|
||||
useEffect(() => {
|
||||
const updateDimensions = () => {
|
||||
setDimensions({
|
||||
@ -80,76 +85,105 @@ function SnowfallRawBackground() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!canvasRef.current) return;
|
||||
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) return;
|
||||
|
||||
canvas.width = dimensions.width;
|
||||
canvas.height = dimensions.height;
|
||||
|
||||
const createSnowflake = (init?: boolean): Snowflake => {
|
||||
let posy = -10;
|
||||
let radius = Math.random() * 4 + 2;
|
||||
let speed = Math.random() * 1 + 0.5;
|
||||
let sway = Math.random() * 0.5 + 0.2;
|
||||
// Load the snowflake image using a plain Image so we can draw it to canvas reliably
|
||||
const img = new Image();
|
||||
img.src = '/images/event_snowflake.png';
|
||||
let mounted = true;
|
||||
|
||||
if (init) {
|
||||
const initHeight = (dimensions.height / 1.1);
|
||||
posy = Math.random() * initHeight + posy;
|
||||
radius = (posy / (initHeight + posy) - 1) * -radius;
|
||||
}
|
||||
const start = () => {
|
||||
if (!mounted) return;
|
||||
imageRef.current = img;
|
||||
|
||||
if (window.innerWidth < 768) {
|
||||
radius /= 1.4;
|
||||
}
|
||||
const createSnowflake = (init?: boolean): Snowflake => {
|
||||
let posy = -10;
|
||||
let radius = Math.random() * 18 + 10;
|
||||
let speed = Math.random() * 1 + 0.5;
|
||||
let sway = Math.random() * 0.5 + 0.2;
|
||||
|
||||
return {
|
||||
x: Math.random() * dimensions.width,
|
||||
y: posy,
|
||||
radius,
|
||||
speed,
|
||||
sway,
|
||||
swayOffset: Math.random() * Math.PI * 2,
|
||||
opacity: Math.random() * 0.5 + 0.5,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const snowflakes: Snowflake[] = [];
|
||||
for (let i = 0; i < 200; i++) {
|
||||
snowflakes.push(createSnowflake(true));
|
||||
}
|
||||
snowflakesRef.current = snowflakes;
|
||||
|
||||
const animate = () => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
snowflakesRef.current.forEach((flake, index) => {
|
||||
flake.y += flake.speed;
|
||||
flake.x += Math.sin(flake.swayOffset + flake.y * 0.02) * flake.sway;
|
||||
|
||||
const shrink = dimensions.height < 768 ? 0.001 : 0.005
|
||||
flake.radius = Math.max(0, flake.radius - shrink);
|
||||
|
||||
if (flake.y > dimensions.height || flake.radius <= 0.5) {
|
||||
snowflakesRef.current[index] = createSnowflake();
|
||||
return;
|
||||
if (init) {
|
||||
const initHeight = (dimensions.height / 1.1);
|
||||
posy = Math.random() * initHeight + posy;
|
||||
radius = (posy / (initHeight + posy) - 1) * -radius;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(flake.x, flake.y, flake.radius, 0, Math.PI * 2);
|
||||
ctx.fillStyle = `rgba(255, 255, 255, ${flake.opacity})`;
|
||||
ctx.fill();
|
||||
});
|
||||
if (window.innerWidth < 768) {
|
||||
radius /= 1.4;
|
||||
}
|
||||
|
||||
return {
|
||||
x: Math.random() * dimensions.width,
|
||||
y: posy,
|
||||
radius,
|
||||
speed,
|
||||
sway,
|
||||
swayOffset: Math.random() * Math.PI * 2,
|
||||
opacity: Math.random() * 0.5 + 0.2,
|
||||
rotation: Math.random() * Math.PI * 2,
|
||||
rotationSpeed: (Math.random() - 0.5) * 0.02,
|
||||
}
|
||||
};
|
||||
|
||||
const snowflakes: Snowflake[] = [];
|
||||
for (let i = 0; i < 80; i++) {
|
||||
snowflakes.push(createSnowflake(true));
|
||||
}
|
||||
snowflakesRef.current = snowflakes;
|
||||
|
||||
const animate = () => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
snowflakesRef.current.forEach((flake, index) => {
|
||||
flake.y += flake.speed;
|
||||
flake.x += Math.sin(flake.swayOffset + flake.y * 0.02) * flake.sway;
|
||||
flake.rotation += flake.rotationSpeed;
|
||||
|
||||
const shrink = dimensions.height < 768 ? 0.005 : 0.01;
|
||||
flake.radius = Math.max(2, flake.radius - shrink);
|
||||
|
||||
if (flake.y > dimensions.height || flake.radius <= 0.5) {
|
||||
snowflakesRef.current[index] = createSnowflake();
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
ctx.globalAlpha = flake.opacity;
|
||||
ctx.translate(flake.x, flake.y);
|
||||
ctx.rotate(flake.rotation);
|
||||
|
||||
ctx.drawImage(
|
||||
img,
|
||||
-flake.radius / 2,
|
||||
-flake.radius / 2,
|
||||
flake.radius,
|
||||
flake.radius
|
||||
);
|
||||
|
||||
ctx.restore();
|
||||
});
|
||||
|
||||
animationFrameRef.current = requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
animationFrameRef.current = requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
animationFrameRef.current = requestAnimationFrame(animate);
|
||||
if (img.complete) start();
|
||||
else img.onload = start;
|
||||
|
||||
return () => cancelAnimationFrame(animationFrameRef.current);
|
||||
return () => {
|
||||
mounted = false;
|
||||
cancelAnimationFrame(animationFrameRef.current);
|
||||
img.onload = null;
|
||||
imageRef.current = null;
|
||||
};
|
||||
}, [dimensions]);
|
||||
|
||||
return (
|
||||
@ -157,6 +191,7 @@ function SnowfallRawBackground() {
|
||||
ref={canvasRef}
|
||||
className="fixed top-0 left-0 w-full h-full pointer-events-none"
|
||||
style={{ zIndex: 0 }}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import { FloatingLabel } from "@/components/floating-label";
|
||||
import { FakeRelativeWindow, RestoreWindowsButton } from "./client-windows";
|
||||
import Image from "next/image"
|
||||
import Link from "next/link";
|
||||
import { ChristmasHat } from "./events/christmas";
|
||||
import { ChristmasProperty } from "./events/christmas";
|
||||
|
||||
export const FakeWindow = ({
|
||||
windowText, children
|
||||
@ -12,7 +12,12 @@ export const FakeWindow = ({
|
||||
children: React.ReactNode
|
||||
}) => (
|
||||
<div className="relative md:bg-background mx-auto w-[480px] md:w-[520px] md:border border-primary z-10">
|
||||
<ChristmasHat size={180} left={-60} top={-80} />
|
||||
<ChristmasProperty
|
||||
img="/images/event_santahat1.png"
|
||||
size={180}
|
||||
left={-60}
|
||||
top={-80}
|
||||
/>
|
||||
<div className="p-1 pb-0">
|
||||
<div className="hidden md:flex bg-primary p-2 justify-between text-background">
|
||||
<div className="ms-1 pointer-events-none">
|
||||
@ -48,7 +53,7 @@ export const HomeWindows = () => (
|
||||
>
|
||||
<FloatingLabel placeholder="This is Nola, my OC :3">
|
||||
<div className="relative">
|
||||
<ChristmasHat size={150} top={-40} left={70} flip />
|
||||
<ChristmasProperty img="/images/event_santahat1.png" size={150} top={-40} left={70} flip />
|
||||
<Image
|
||||
className=""
|
||||
alt="Nola"
|
||||
@ -93,13 +98,13 @@ export const HomeWindows = () => (
|
||||
/>
|
||||
</FakeRelativeWindow>
|
||||
<FakeRelativeWindow
|
||||
windowText="coral_cupcake.mkv"
|
||||
windowText="ena_spin.obj"
|
||||
className="-right-[85%] top-[440px] z-10"
|
||||
draggable
|
||||
>
|
||||
<Image
|
||||
alt="Coral Cupcake"
|
||||
src="https://media1.tenor.com/m/N5K-4AWj8QcAAAAC/coral-glasses-cupcake.gif"
|
||||
src="https://media.tenor.com/Uv-PLe5GIe0AAAAi/gyaruface.gif"
|
||||
width={240}
|
||||
height={200}
|
||||
quality={10}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user