style: Improve CSS formatting and animation adjustments

This commit is contained in:
Jan K9f 2025-04-23 14:16:03 +02:00
parent 45c5b19e41
commit 55fb776052
Signed by: jank
GPG key ID: 22BEAC760B3333D6
3 changed files with 124 additions and 33 deletions

View file

@ -33,8 +33,12 @@ body {
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Open button styling */
@ -65,24 +69,30 @@ body {
.case-indicator {
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%);
width: 6px;
left: 50%; /* Back to center - we'll adjust the animation instead */
transform: translate(-50%, -50%); /* Center precisely */
width: 4px;
height: 100%;
background: #facc15;
box-shadow: 0 0 10px #facc15, 0 0 15px rgba(255, 255, 255, 0.5);
background: #ff0000; /* Bright red for debugging */
box-shadow:
0 0 10px #ff0000,
0 0 15px rgba(255, 0, 0, 0.5);
z-index: 3;
animation: indicator-pulse 1.5s ease-in-out 3s infinite alternate;
animation: indicator-pulse 1.5s ease-in-out 10s infinite alternate;
}
@keyframes indicator-pulse {
0% {
opacity: 0.6;
box-shadow: 0 0 10px #facc15, 0 0 15px rgba(255, 255, 255, 0.3);
box-shadow:
0 0 10px #ff0000,
0 0 15px rgba(255, 0, 0, 0.3);
}
100% {
opacity: 1;
box-shadow: 0 0 15px #facc15, 0 0 20px rgba(255, 255, 255, 0.7);
box-shadow:
0 0 15px #ff0000,
0 0 20px rgba(255, 0, 0, 0.7);
}
}
@ -94,6 +104,9 @@ body {
width: 100%;
height: 150px; /* Fixed height for the horizontal row */
overflow: hidden; /* Hide scrollbar */
display: flex;
justify-content: center; /* Center the items container */
align-items: center;
}
.case-items {
@ -102,70 +115,123 @@ body {
justify-content: center;
align-items: center;
gap: 8px;
padding: 5px;
padding: 5px 0px; /* Remove horizontal padding */
height: 100%;
width: 100%;
animation: slide-in 3s cubic-bezier(0.25, 1, 0.5, 1) forwards;
transform: translateX(120%); /* Initial position far to the right */
animation: slide-in 10s cubic-bezier(0.05, 0.82, 0.17, 1) forwards;
transform: translateX(3000%); /* Extremely far initial position for 200 items */
position: relative; /* Ensure positioning context */
}
@keyframes slide-in {
0% {
transform: translateX(120%);
transform: translateX(2000%);
}
90% {
transform: translateX(-5%); /* Slight overshoot */
transform: translateX(-16%); /* Single overshoot for dramatic effect */
}
100% {
transform: translateX(0%); /* Final centered position */
transform: translateX(-8%); /* Centered position */
}
}
.case-item {
transition: all 0.2s ease;
padding: 2px;
animation: item-flash 0.3s ease-out forwards;
animation-play-state: paused;
}
@keyframes item-flash {
0% {
filter: brightness(1);
}
50% {
filter: brightness(1.8);
}
100% {
filter: brightness(1.2);
}
}
.case-item-inner {
background: #232c43;
border: 2px solid #2d3748;
border-radius: 8px;
padding: 12px 8px;
padding: 10px 5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100px;
width: 65px;
height: 100%;
}
.case-item-won {
z-index: 2;
animation: highlight-winner 0.5s ease-out 3s forwards;
animation: highlight-winner 1s ease-out 10s forwards;
}
.case-item-won .case-item-inner {
box-shadow: 0 0 15px rgba(255, 255, 255, 0.3);
background: linear-gradient(to right, #232c43, #2a3354, #232c43);
border: 3px solid #ff0000 !important; /* Bright red border for debugging */
}
/* Specific ID for the winning item to ensure it's visible */
#winning-item {
z-index: 5; /* Higher than indicator */
}
@keyframes highlight-winner {
0% {
transform: scale(1);
filter: brightness(1);
}
10% {
transform: scale(1.3);
filter: brightness(2);
}
20% {
transform: scale(1.2);
filter: brightness(1.8);
}
30% {
transform: scale(1.25);
filter: brightness(2);
}
40% {
transform: scale(1.2);
filter: brightness(1.8);
}
50% {
transform: scale(1.15);
transform: scale(1.25);
filter: brightness(2);
}
75% {
transform: scale(1.1);
60% {
transform: scale(1.2);
filter: brightness(1.8);
}
70% {
transform: scale(1.25);
filter: brightness(2);
}
80% {
transform: scale(1.2);
filter: brightness(1.8);
}
90% {
transform: scale(1.25);
filter: brightness(2);
}
100% {
transform: scale(1.05);
transform: scale(1.2);
filter: brightness(1.5);
}
}
.amount {
font-size: 1.2rem;
font-size: 1rem;
font-weight: bold;
margin-bottom: 4px;
}
@ -173,4 +239,4 @@ body {
.rarity {
font-size: 0.75rem;
opacity: 0.7;
}
}

View file

@ -36,7 +36,7 @@
<!-- Case opening display - CSGO style -->
<div *ngIf="isOpen && !isOpening" class="w-full max-w-lg">
<!-- Winner display - only shown after animation completes -->
<div class="flex flex-col items-center mb-6" style="opacity: 0; animation: fade-in 0.5s ease-out 3.5s forwards;">
<div class="flex flex-col items-center mb-6" style="opacity: 0; animation: fade-in 0.5s ease-out 10.5s forwards;">
<div class="text-2xl font-bold text-green-400 mb-2">Dein Gewinn:</div>
<div class="text-4xl font-bold text-white mb-4">{{ wonReward?.value | currency:'EUR' }}</div>
</div>
@ -56,21 +56,36 @@
<!-- Horizontal row of prizes -->
<div class="case-items-container">
<div class="case-items">
<!-- Add a reference element first to help with alignment -->
<div class="case-item case-item-ref" style="opacity: 0; pointer-events: none;"></div>
<div *ngFor="let reward of prizeList; let i = index"
class="case-item"
[class.case-item-won]="isWonReward(reward)">
[class.case-item-won]="isWonReward(reward)"
[id]="isWonReward(reward) ? 'winning-item' : ''"
[style.border]="isCenterItem(i) ? '3px solid #00ff00' : 'none'"
[style.animation-delay]="isWonReward(reward) ? '10s' : (8 + (i % 50) * 0.04) + 's'">
<div class="case-item-inner"
[ngClass]="getRarityClass(reward.probability)">
<div class="amount">{{ reward.value | currency:'EUR' }}</div>
<div class="rarity">{{ (reward.probability * 100) | number:'1.0-0' }}%</div>
[ngClass]="getRarityClass(reward.probability)"
[style.border]="isCenterItem(i) ? '5px solid lime' : ''"
[style.background-color]="isCenterItem(i) ? '#004400' : ''"
[style.transform]="isCenterItem(i) ? 'scale(1.1)' : ''"
[style.box-shadow]="isCenterItem(i) ? '0 0 15px lime' : ''"
[style.margin-left]="isWonReward(reward) ? getCenterOffset() : '0'"
[style.transition-delay]="(i % 20) * 0.01 + 's'">
<div class="amount" [style.color]="isCenterItem(i) ? '#00ff00' : ''">{{ reward.value | currency:'EUR' }}</div>
<div class="rarity" [style.color]="isCenterItem(i) ? '#00ff00' : ''">{{ (reward.probability * 100) | number:'1.0-0' }}%</div>
</div>
</div>
<!-- Add another reference element at the end to help with alignment -->
<div class="case-item case-item-ref" style="opacity: 0; pointer-events: none;"></div>
</div>
</div>
</div>
<!-- Action buttons - only shown after animation completes -->
<div class="flex gap-4 justify-center mt-8" style="opacity: 0; animation: fade-in 0.5s ease-out 3.7s forwards;">
<div class="flex gap-4 justify-center mt-8" style="opacity: 0; animation: fade-in 0.5s ease-out 10.7s forwards;">
<button (click)="openAgain()" class="open-btn text-white px-6 py-2 rounded-lg font-semibold transition-all">Nochmal öffnen</button>
<button (click)="goBack()" class="bg-[#232c43] hover:bg-[#2d3748] text-white px-6 py-2 rounded-lg font-semibold transition">Zurück zur Übersicht</button>
</div>

View file

@ -94,8 +94,8 @@ export default class LootboxOpeningComponent {
generateCasePrizes(wonReward: Reward) {
if (!this.lootbox) return;
// Create a case opening display with fewer prizes to fit on screen without scrolling
const prizeCount = 9; // Total number of prizes to show (odd number to have center prize)
// Create a case opening display with an extremely large number of prizes for a massive scrolling animation
const prizeCount = 200; // Set to 200 for an extremely long scrolling animation
const winningPosition = Math.floor(prizeCount / 2); // Position of the winning prize (middle)
// Get possible rewards from the lootbox
@ -166,4 +166,14 @@ export default class LootboxOpeningComponent {
reward.value === this.wonReward.value &&
reward.probability === this.wonReward.probability;
}
// Calculate the center position for better alignment
getCenterOffset(): string {
return '0px'; // No additional offset - using animation transform instead
}
// Check if item is at center position (100th item)
isCenterItem(index: number): boolean {
return index === Math.floor(200 / 2); // Center item at index 100 (0-indexed)
}
}