Added wiggle animation to images + badges
This commit is contained in:
@@ -52,15 +52,11 @@ export default function Filters({ originalPosts, posts, setPosts }: Props) {
|
||||
),
|
||||
);
|
||||
|
||||
console.log("CLICK", filterResults);
|
||||
console.log("CLICK-Original", originalPosts);
|
||||
|
||||
setPosts(filterResults.length > 0 ? filterResults : originalPosts);
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
handleResetFilters();
|
||||
console.log("RESET", originalPosts);
|
||||
setPosts(originalPosts);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { WiggleWrapper } from "~/app/components/wiggle-wrapper";
|
||||
import { Badge } from "~/app/components/ui/badge";
|
||||
|
||||
const BadgeList: React.FC<{ badges: string[] }> = ({ badges }) => {
|
||||
@@ -5,7 +6,9 @@ const BadgeList: React.FC<{ badges: string[] }> = ({ badges }) => {
|
||||
<ul className="not-prose flex flex-row flex-wrap gap-x-2 gap-y-1">
|
||||
{badges.map((badge) => (
|
||||
<li key={badge} className="inline">
|
||||
<Badge>{badge}</Badge>
|
||||
<WiggleWrapper>
|
||||
<Badge>{badge}</Badge>
|
||||
</WiggleWrapper>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Image from "next/image";
|
||||
import { Card } from "~/app/components/card";
|
||||
import { WiggleWrapper } from "~/app/components/wiggle-wrapper";
|
||||
import { cn } from "~/app/utils/styles";
|
||||
|
||||
const BannerImage: React.FC<{
|
||||
@@ -8,15 +9,17 @@ const BannerImage: React.FC<{
|
||||
className?: string;
|
||||
}> = ({ src, alt = "", className }) => {
|
||||
return (
|
||||
<Card
|
||||
className={cn(
|
||||
"not-prose relative aspect-video h-auto max-w-full",
|
||||
className,
|
||||
)}
|
||||
overlayShadow
|
||||
>
|
||||
<Image src={src} alt={alt} className="object-cover" fill />
|
||||
</Card>
|
||||
<WiggleWrapper>
|
||||
<Card
|
||||
className={cn(
|
||||
"not-prose relative aspect-video h-auto max-w-full",
|
||||
className,
|
||||
)}
|
||||
overlayShadow
|
||||
>
|
||||
<Image src={src} alt={alt} className="object-cover" fill />
|
||||
</Card>
|
||||
</WiggleWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { clamp01 } from "~/app/utils/math";
|
||||
import { random, randomInt0 } from "~/app/utils/random";
|
||||
|
||||
const RingBackground = () => {
|
||||
const numRings = 10; // Adjust the number of rings as needed
|
||||
|
||||
const getRandomPosition = () => {
|
||||
const randomValueX = randomInt0(100);
|
||||
|
||||
const randomWeightY = random();
|
||||
|
||||
// Choose a random percentage for the second value with a bias towards 100%
|
||||
// 80% of the time, generate a number close to 100%
|
||||
// 20% of the time, generate a completely random number
|
||||
const randomValueY =
|
||||
randomWeightY < 0.5 ? 50 + randomInt0(50) : randomInt0(100);
|
||||
|
||||
return { x: randomValueX, y: randomValueY };
|
||||
};
|
||||
|
||||
function getColorByDepth(percentage: number) {
|
||||
const color1 = "#92beb8";
|
||||
const color2 = "#272828";
|
||||
|
||||
// Ensure the percentage is within the range [0, 1]
|
||||
percentage = clamp01(percentage);
|
||||
|
||||
// Parse the input colors as hex values
|
||||
const hexColor1 = parseInt(color1.slice(1), 16);
|
||||
const hexColor2 = parseInt(color2.slice(1), 16);
|
||||
|
||||
// Interpolate between the two colors
|
||||
const r1 = (hexColor1 >> 16) & 255;
|
||||
const g1 = (hexColor1 >> 8) & 255;
|
||||
const b1 = hexColor1 & 255;
|
||||
const r2 = (hexColor2 >> 16) & 255;
|
||||
const g2 = (hexColor2 >> 8) & 255;
|
||||
const b2 = hexColor2 & 255;
|
||||
|
||||
const r = Math.round(r1 + (r2 - r1) * percentage);
|
||||
const g = Math.round(g1 + (g2 - g1) * percentage);
|
||||
const b = Math.round(b1 + (b2 - b1) * percentage);
|
||||
|
||||
// Convert the interpolated RGB values back to a hex color
|
||||
const interpolatedColor = `#${((1 << 24) | (r << 16) | (g << 8) | b)
|
||||
.toString(16)
|
||||
.slice(1)}`;
|
||||
|
||||
return interpolatedColor;
|
||||
}
|
||||
|
||||
const renderRings = () => {
|
||||
const rings = [];
|
||||
|
||||
for (let i = 0; i < numRings; i++) {
|
||||
const position = getRandomPosition();
|
||||
const color = getColorByDepth((randomInt0(50) + position.y) / 100);
|
||||
|
||||
rings.push(
|
||||
<circle
|
||||
key={i}
|
||||
cx={position.x + "%"}
|
||||
cy={Math.max(5, position.y) + "%"}
|
||||
r={24}
|
||||
stroke={color}
|
||||
strokeWidth={16}
|
||||
fillOpacity={0}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
|
||||
return rings;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="absolute inset-0 top-[100vh] -z-40">
|
||||
<svg className="h-full w-full" xmlns="http://www.w3.org/2000/svg">
|
||||
{renderRings()}
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export { RingBackground };
|
||||
28
src/app/components/wiggle-wrapper.tsx
Normal file
28
src/app/components/wiggle-wrapper.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import { motion } from "framer-motion";
|
||||
import { type PropsWithChildren } from "react";
|
||||
|
||||
const height = -5;
|
||||
|
||||
const WiggleWrapper = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ y: 0, rotate: 0 }}
|
||||
whileHover={{
|
||||
y: [0, height, height, height, height, height, height],
|
||||
rotate: [0, 0, -3, 2, -2, 1, 0],
|
||||
transition: {
|
||||
delay: 0.025,
|
||||
duration: 0.75,
|
||||
times: [0, 0.2, 0.475, 0.625, 0.775, 0.925, 1],
|
||||
},
|
||||
}}
|
||||
style={{ originX: "50%", originY: "80%" }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export { WiggleWrapper };
|
||||
@@ -6,7 +6,7 @@ import { TRPCReactProvider } from "~/trpc/react";
|
||||
import { ThemeProvider } from "~/app/components/theme/theme-provider";
|
||||
import { Navigation } from "~/app/components/navigation/navigation";
|
||||
import { type PropsWithChildren } from "react";
|
||||
import { Footer } from "~/app/components/footer";
|
||||
import { Footer } from "~/app/components/navigation/footer";
|
||||
import { Toaster } from "~/app/components/ui/toaster";
|
||||
|
||||
const inter = Inter({
|
||||
|
||||
Reference in New Issue
Block a user