added depthmap to oliver

This commit is contained in:
NicholaiVogel 2025-10-13 00:58:29 -06:00
parent 7af9d05f48
commit 94b9eeea15
7 changed files with 149 additions and 8 deletions

BIN
public/HATER2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
public/no_pigeons_zone.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
public/open 24 hours.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
public/welcome.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

142
src/components/DepthMap.tsx Normal file
View File

@ -0,0 +1,142 @@
"use client";
import { useEffect, useRef, useState } from "react";
interface DepthMapProps {
originalImg: string;
depthImg: string;
verticalThreshold?: number;
horizontalThreshold?: number;
}
export function DepthMap({
originalImg,
depthImg,
verticalThreshold = 15,
horizontalThreshold = 15,
}: DepthMapProps) {
const canvasRef = useRef<HTMLCanvasElement>(null);
const [mousePos, setMousePos] = useState({ x: 0.5, y: 0.5 });
const [loaded, setLoaded] = useState(false);
const originalImgRef = useRef<HTMLImageElement | null>(null);
const depthImgRef = useRef<HTMLImageElement | null>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext("2d");
if (!ctx) return;
// Load images
const original = new Image();
const depth = new Image();
original.crossOrigin = "anonymous";
depth.crossOrigin = "anonymous";
let loadedCount = 0;
const onLoad = () => {
loadedCount++;
if (loadedCount === 2) {
originalImgRef.current = original;
depthImgRef.current = depth;
setLoaded(true);
}
};
original.onload = onLoad;
depth.onload = onLoad;
original.src = originalImg;
depth.src = depthImg;
}, [originalImg, depthImg]);
useEffect(() => {
if (!loaded || !canvasRef.current) return;
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
if (!ctx || !originalImgRef.current || !depthImgRef.current) return;
const original = originalImgRef.current;
const depth = depthImgRef.current;
// Set canvas size to match image
canvas.width = original.width;
canvas.height = original.height;
// Calculate displacement based on mouse position
const offsetX = (mousePos.x - 0.5) * horizontalThreshold;
const offsetY = (mousePos.y - 0.5) * verticalThreshold;
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw the original image
ctx.drawImage(original, 0, 0);
// Get image data for manipulation
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const pixels = imageData.data;
// Draw depth map to get depth values
ctx.drawImage(depth, 0, 0);
const depthData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const depthPixels = depthData.data;
// Create displaced image
const displaced = ctx.createImageData(canvas.width, canvas.height);
for (let y = 0; y < canvas.height; y++) {
for (let x = 0; x < canvas.width; x++) {
const idx = (y * canvas.width + x) * 4;
// Get depth value (using red channel) - inverted so darker = more movement
const depthValue = 1 - (depthPixels[idx] / 255);
// Calculate displacement
const displaceX = Math.round(offsetX * depthValue);
const displaceY = Math.round(offsetY * depthValue);
// Source pixel position
const srcX = Math.max(0, Math.min(canvas.width - 1, x - displaceX));
const srcY = Math.max(0, Math.min(canvas.height - 1, y - displaceY));
const srcIdx = (srcY * canvas.width + srcX) * 4;
// Copy pixel
displaced.data[idx] = pixels[srcIdx];
displaced.data[idx + 1] = pixels[srcIdx + 1];
displaced.data[idx + 2] = pixels[srcIdx + 2];
displaced.data[idx + 3] = pixels[srcIdx + 3];
}
}
ctx.putImageData(displaced, 0, 0);
}, [loaded, mousePos, horizontalThreshold, verticalThreshold]);
const handleMouseMove = (e: React.MouseEvent<HTMLCanvasElement>) => {
const canvas = canvasRef.current;
if (!canvas) return;
const rect = canvas.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = (e.clientY - rect.top) / rect.height;
setMousePos({ x, y });
};
const handleMouseLeave = () => {
setMousePos({ x: 0.5, y: 0.5 });
};
return (
<canvas
ref={canvasRef}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
className="w-full h-full object-cover"
style={{ display: loaded ? 'block' : 'none' }}
/>
);
}

View File

@ -4,8 +4,8 @@ import { CursorDotBackground } from "./CursorDotBackground";
import { HorizontalAccordion } from "./HorizontalAccordion";
import { InstagramFeed } from "./InstagramFeed";
import { useEffect, useRef, useState } from "react";
import Image from "next/image";
import { motion, AnimatePresence } from "framer-motion";
import { DepthMap } from "./DepthMap";
export function TempPlaceholder() {
const titleRef = useRef<HTMLHeadingElement | null>(null);
@ -168,12 +168,11 @@ export function TempPlaceholder() {
}}
className="relative w-full aspect-square"
>
<Image
src="/OLIVER.jpeg"
alt="Easter egg"
fill
unoptimized
className="object-cover"
<DepthMap
originalImg="/OLIVER.jpeg"
depthImg="/OLIVER_depth.jpeg"
verticalThreshold={40}
horizontalThreshold={70}
/>
</motion.div>
</div>

View File

@ -5,7 +5,7 @@ export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Allow only the home page and Next.js internal routes
if (pathname === '/' || pathname.startsWith('/_next') || pathname.startsWith('/favicon.') || pathname === '/OLIVER.jpeg') {
if (pathname === '/' || pathname.startsWith('/_next') || pathname.startsWith('/favicon.') || pathname === '/OLIVER.jpeg' || pathname === '/OLIVER_depth.jpeg') {
return NextResponse.next();
}