added depthmap to oliver
This commit is contained in:
parent
7af9d05f48
commit
94b9eeea15
BIN
public/HATER2.jpg
Normal file
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
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
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
BIN
public/welcome.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
142
src/components/DepthMap.tsx
Normal file
142
src/components/DepthMap.tsx
Normal 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' }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user