You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Angular记忆游戏中用CSS Transform实现卡片翻转

Hey Gordon, let's fix that card flip issue for your Angular memory game! Since you already have an isFlipped property on your card data, we can leverage that with Angular's property binding and CSS 3D transforms to get a smooth, working flip effect. Here's a step-by-step solution tailored to your setup:

1. Refine Your Component Logic

First, make sure your click handler correctly toggles the isFlipped state while handling core memory game rules (like limiting flipped cards to 2 and checking matches). Here's a polished example:

import { Component } from '@angular/core';

// Define your card interface (match your existing data structure)
interface Card {
  id: number;
  value: string; // Replace with your card content (image path, emoji, etc.)
  isFlipped: boolean;
  isMatched: boolean;
}

@Component({
  selector: 'app-memory-game',
  templateUrl: './memory-game.component.html',
  styleUrls: ['./memory-game.component.css']
})
export class MemoryGameComponent {
  cards: Card[] = [];
  flippedCards: Card[] = [];
  lockBoard = false; // Prevent rapid clicks during match checks

  ngOnInit() {
    // Initialize your card deck (adjust values to fit your game)
    const cardValues = ['🍎', '🍌', '🍒', '🍇', '🍉', '🍊'];
    this.cards = [...cardValues, ...cardValues]
      .map(value => ({
        id: Math.random(),
        value,
        isFlipped: false,
        isMatched: false
      }))
      .sort(() => Math.random() - 0.5); // Shuffle cards
  }

  toggleFlip(card: Card) {
    // Skip action if board is locked, card is matched, or already flipped
    if (this.lockBoard || card.isMatched || card.isFlipped) return;

    // Toggle the flip state
    card.isFlipped = !card.isFlipped;

    // Track flipped cards for match checks
    card.isFlipped 
      ? this.flippedCards.push(card) 
      : this.flippedCards = this.flippedCards.filter(c => c.id !== card.id);

    // Check for matches when two cards are flipped
    if (this.flippedCards.length === 2) {
      this.checkMatch();
    }
  }

  private checkMatch() {
    const [card1, card2] = this.flippedCards;
    const isMatch = card1.value === card2.value;

    if (isMatch) {
      // Mark cards as matched to prevent further clicks
      card1.isMatched = true;
      card2.isMatched = true;
      this.flippedCards = [];
    } else {
      // Flip cards back after a short delay so users can see both
      this.lockBoard = true;
      setTimeout(() => {
        card1.isFlipped = false;
        card2.isFlipped = false;
        this.flippedCards = [];
        this.lockBoard = false;
      }, 1000);
    }
  }
}
2. Add CSS for 3D Flip Effect

This is the critical part—CSS transforms will create the actual flip animation. Replace your existing card styles with this:

.memory-game {
  display: grid;
  grid-template-columns: repeat(4, 1fr); /* Adjust columns for your game size */
  gap: 1rem;
  padding: 2rem;
  max-width: 600px;
  margin: 0 auto;
}

.card {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1; /* Square cards */
  transform-style: preserve-3d;
  transition: transform 0.6s ease;
  cursor: pointer;
}

/* Apply flip transform when isFlipped is true */
.card.flipped {
  transform: rotateY(180deg);
}

/* Style for matched cards (optional) */
.card.matched {
  cursor: default;
  opacity: 0.7;
}

.card-front, .card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden; /* Hide the back of each face when flipped */
  border-radius: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.5rem;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}

.card-front {
  background-color: #2c3e50; /* Card back color */
  color: white;
}

.card-back {
  background-color: white; /* Card front color */
  transform: rotateY(180deg); /* Start hidden (flipped away from user) */
}
3. Update Your HTML Template

Bind the isFlipped state to the CSS class and wire up the click handler:

<div class="memory-game">
  <div 
    *ngFor="let card of cards"
    class="card"
    [class.flipped]="card.isFlipped"
    [class.matched]="card.isMatched"
    (click)="toggleFlip(card)"
  >
    <div class="card-front">?</div> <!-- Card back content -->
    <div class="card-back">{{ card.value }}</div> <!-- Card front content -->
  </div>
</div>
Key Notes to Avoid Common Issues
  • CSS 3D Setup: transform-style: preserve-3d and backface-visibility: hidden are non-negotiable—they ensure the card faces don't overlap during the flip.
  • Angular Binding: Using [class.flipped]="card.isFlipped" ensures the flip class is added/removed automatically when isFlipped changes, triggering the CSS transition.
  • Board Locking: The lockBoard flag prevents users from spamming clicks while cards are flipping back, which can break your game logic.

This setup should give you a smooth, reliable card flip effect that works with your existing isFlipped property. Let me know if you need to adjust any part to fit your specific game design!

内容的提问来源于stack exchange,提问作者Gordon

火山引擎 最新活动