✨ Add Rarity-Based Gradients & Animated Particles
🎨 Rarity-Based Visual System: - Replaced TCG-based gradients with subtle rarity-based backgrounds - Common: Subtle gray gradient (no particles) - Uncommon: Subtle green gradient (15 particles) - Rare: Subtle gold gradient (25 particles) - Mythic: Rich gold gradient (40 particles) - Holographic: Subtle pink gradient (50 particles) - Enchanted: Subtle purple gradient (60 particles) - Super Rare: Subtle blue gradient (45 particles) - Legendary: Vibrant gold gradient (80 particles) ✨ Animated Particle Effects: - Floating particle animation with random positioning - Particles match rarity colors with glowing effects - Random animation delays and durations for natural movement - More rare cards = more magical particle effects - Particles are pointer-events-none (do not interfere with UI) 🎯 Smart Text Contrast: - Light rarities (common/uncommon/rare) use dark text - Dark rarities (mythic+) use white text for readability - Automatic contrast adaptation based on background 🌟 Enhanced Atmosphere: - Subtle background patterns (reduced opacity) - Rarity-appropriate visual hierarchy - Immersive, magical feel for rare cards The hero section now creates a truly magical experience
This commit is contained in:
parent
36fe4a6f0f
commit
2867a8ff23
2 changed files with 99 additions and 9 deletions
|
|
@ -132,13 +132,49 @@ export default function CardDetail() {
|
|||
}
|
||||
}, [card, id]);
|
||||
|
||||
const getTCGGradient = (game) => {
|
||||
const getRarityGradient = (rarity) => {
|
||||
const rarityKey = rarity?.toLowerCase();
|
||||
const gradients = {
|
||||
'MTG': '#9333ea, #8b5cf6, #4f46e5',
|
||||
'Pokemon': '#2563eb, #3b82f6, #0891b2',
|
||||
'Lorcana': '#db2777, #ec4899, #a855f7'
|
||||
'common': '#f3f4f6, #e5e7eb, #d1d5db', // Subtle gray
|
||||
'uncommon': '#ecfdf5, #d1fae5, #a7f3d0', // Subtle green
|
||||
'rare': '#fef3c7, #fde68a, #fcd34d', // Subtle gold
|
||||
'mythic': '#fef9c3, #fef08a, #facc15', // Rich gold
|
||||
'holographic': '#fce7f3, #fbcfe8, #f9a8d4', // Subtle pink
|
||||
'enchanted': '#f3e8ff, #e9d5ff, #c4b5fd', // Subtle purple
|
||||
'super rare': '#dbeafe, #bfdbfe, #93c5fd', // Subtle blue
|
||||
'legendary': '#fef3c7, #fde68a, #f59e0b' // Vibrant gold
|
||||
};
|
||||
return gradients[game] || '#4b5563, #374151';
|
||||
return gradients[rarityKey] || '#f9fafb, #f3f4f6, #e5e7eb';
|
||||
};
|
||||
|
||||
const getParticleCount = (rarity) => {
|
||||
const rarityKey = rarity?.toLowerCase();
|
||||
const particleCounts = {
|
||||
'common': 0,
|
||||
'uncommon': 15,
|
||||
'rare': 25,
|
||||
'mythic': 40,
|
||||
'holographic': 50,
|
||||
'enchanted': 60,
|
||||
'super rare': 45,
|
||||
'legendary': 80
|
||||
};
|
||||
return particleCounts[rarityKey] || 0;
|
||||
};
|
||||
|
||||
const getParticleColor = (rarity) => {
|
||||
const rarityKey = rarity?.toLowerCase();
|
||||
const colors = {
|
||||
'common': '#ffffff',
|
||||
'uncommon': '#10b981',
|
||||
'rare': '#f59e0b',
|
||||
'mythic': '#ffd700',
|
||||
'holographic': '#ff6b6b',
|
||||
'enchanted': '#a855f7',
|
||||
'super rare': '#3b82f6',
|
||||
'legendary': '#ffd700'
|
||||
};
|
||||
return colors[rarityKey] || '#ffffff';
|
||||
};
|
||||
|
||||
const getTCGIcon = (game) => {
|
||||
|
|
@ -338,13 +374,39 @@ export default function CardDetail() {
|
|||
<div
|
||||
className="relative min-h-96 flex items-center justify-center overflow-hidden"
|
||||
style={{
|
||||
background: `linear-gradient(135deg, ${getTCGGradient(card.game)})`
|
||||
background: `linear-gradient(135deg, ${getRarityGradient(card.rarity)})`
|
||||
}}
|
||||
>
|
||||
{/* Animated Particles Background */}
|
||||
{getParticleCount(card.rarity) > 0 && (
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
{Array.from({ length: getParticleCount(card.rarity) }).map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="absolute animate-float"
|
||||
style={{
|
||||
left: `${Math.random() * 100}%`,
|
||||
top: `${Math.random() * 100}%`,
|
||||
animationDelay: `${Math.random() * 3}s`,
|
||||
animationDuration: `${3 + Math.random() * 2}s`
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="w-1 h-1 rounded-full opacity-60"
|
||||
style={{
|
||||
backgroundColor: getParticleColor(card.rarity),
|
||||
boxShadow: `0 0 6px ${getParticleColor(card.rarity)}`
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Background Pattern */}
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<div className="absolute inset-0 opacity-5">
|
||||
<div className="absolute inset-0" style={{
|
||||
backgroundImage: `url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.1'%3E%3Ccircle cx='30' cy='30' r='2'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")`
|
||||
backgroundImage: `url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23000000' fill-opacity='0.1'%3E%3Ccircle cx='30' cy='30' r='2'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")`
|
||||
}}></div>
|
||||
</div>
|
||||
|
||||
|
|
@ -385,7 +447,11 @@ export default function CardDetail() {
|
|||
</div>
|
||||
|
||||
{/* Card Info */}
|
||||
<div style={{ color: 'white' }}>
|
||||
<div style={{
|
||||
color: ['common', 'uncommon', 'rare'].includes(card.rarity?.toLowerCase())
|
||||
? 'var(--text-primary)'
|
||||
: 'white'
|
||||
}}>
|
||||
<div className="mb-6">
|
||||
<h1 className="text-4xl font-bold mb-2">{card.name}</h1>
|
||||
<p className="text-xl opacity-90 mb-4">{card.oracle_text || card.card_type}</p>
|
||||
|
|
|
|||
|
|
@ -674,3 +674,27 @@ body {
|
|||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Floating particle animation */
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0px) translateX(0px) scale(1);
|
||||
opacity: 0.6;
|
||||
}
|
||||
25% {
|
||||
transform: translateY(-20px) translateX(10px) scale(1.1);
|
||||
opacity: 0.8;
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px) translateX(-15px) scale(0.9);
|
||||
opacity: 1;
|
||||
}
|
||||
75% {
|
||||
transform: translateY(-25px) translateX(5px) scale(1.05);
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-float {
|
||||
animation: float 4s ease-in-out infinite;
|
||||
}
|
||||
Loading…
Reference in a new issue