smart | Webentwicklung
Alles rund um HTML5, PHP, WordPress & Co.

CSS3: Flip-Effekt für Kartenspiel

14. Dezember 2012
Stephan
CSS3: Flip-Effekt für Karten

In diesem Artikel möchte ich euch eine Möglichkeit vorstellen, einen Flip-Effekt mit CSS3 umzusetzen.

Falls ihr z.B. ein webasiertes Kartenspiel entwickeln wollt, ist so ein animierter Flip-Effekt der Karten sehr nett anzusehen. Damit ihr eine Vorstellung habt, wie das Endergebnis aussieht, habt ich euch eine Demo bereitgestellt:

Demo: Karten mit CSS3 Flip-Effekt

HTML-Grundgerüst

Als erstes legen wir uns eine einfache HTML-Datei an und fügen Folgendes ein:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<meta charset="utf-8"/>
<link href="css/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="wrapper">
	<header>
        <h1>Kartenspiel</h1>
    </header>
	<section>
		<div id="gameBoard">
			<div id="cardWrap">
				<div id="cards"></div>
			</div>
		</div>
	</section>
</div>
<script type="text/javascript" src="js/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="js/card.js"></script>
</body>
</html>

Wie dem Code zu entnehmen ist, benötigt ihr noch eine zusätzliche CSS-Datei, jQuery und eine JavaScript-Datei. Letztere nennen wir in unserem Fall card.js. In dieser Datei fügen wir später unseren benötigten JavaScript-Code ein.

CSS

In unsere CSS-Datei fügen wir nun unser CSS ein:

*{margin:0;padding:0;}
header,section{display:block;}
body{background:url(../images/bg.png) repeat;font:100.01% Arial,Verdana,sans-serif;}
header{margin:15px auto;width:280px;height:75px;background:url(../images/wood.jpg);-webkit-box-shadow:0px 0px 10px #000;box-shadow:0px 0px 10px #000;}
header h1{margin:5px;padding:10px 0 0 0;position:absolute;width:270px;height:55px;text-align:center;font-weight:bold;color:#fff;background:#00491e;-webkit-box-shadow:0 0 20px #000 inset;box-shadow:0 0 20px #000 inset;}
#gameBoard{margin:15px auto;width:400px;height:370px;background:url(../images/wood.jpg);-webkit-box-shadow:0px 0px 10px #000;box-shadow:0px 0px 10px #000;}
#cardWrap{margin:15px;position:absolute;width:370px;height:340px;background:#00491e;-webkit-box-shadow:0 0 20px #000 inset;box-shadow:0 0 20px #000 inset;color:#fff;}
#cards{margin:30px;position:relative;}
.card{position:absolute;width:80px;height:80px;cursor:pointer;}
.face{position:absolute;width:100%;height:100%;border-radius:10px;-moz-transition:all .3s;-webkit-transition:all .3s;transition:all .3s;-moz-backface-visibility:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden;}
.front{background:url(../images/cards.png) 0 80px;z-index:20;}
.back{background:url(../images/cards.png);-webkit-transform:rotate3d(0,1,0,-180deg);transform:rotate3d(0,1,0,-180deg);z-index:10;}
.card:hover .face,.flipped .face{-webkit-box-shadow:0 0 15px #aaa;box-shadow:0 0 15px #aaa;}
.flipped .front{-webkit-transform:rotate3d(0,1,0,180deg);transform:rotate3d(0,1,0,180deg);z-index:10;}
.flipped .back{-webkit-transform:rotate3d(0,1,0,0deg);transform:rotate3d(0,1,0,0deg);z-index:20;}
.cardB1{background-position:0 0;}
.cardB2{background-position:-80px 0;}
.cardB3{background-position:-160px 0;}
.cardP1{background-position:0 -80px;}
.cardP2{background-position:-80px -80px;}
.cardP3{background-position:-160px -80px;}
.cardG1{background-position:0 -160px;}
.cardG2{background-position:-80px -160px;}
.cardG3{background-position:-160px -160px;}

Da wir nicht jede Karte einzeln laden wollen, habe ich die Karten als CSS-Sprite zusammengefügt. Zum Ausprobieren könnt ihr gerne die Karten aus der Demo verwenden oder einen eigenen Kartensatz erstellen.

Informationen zu der CSS-Eigenschaft backface-visibilty findet hier: w3schools.com

JavaScript

Nun benötigen wir noch ein wenig JavaScript, welches wir in die cards.js-Datei einfügen:

var cards = [
	'cardB1',
	'cardB2',
	'cardB3',
	'cardP1',
	'cardP2',
	'cardP3',
	'cardG1',
	'cardG2',
	'cardG3'
];

$( document ).ready( function ()
{
	renderCards();

	$( '.card' ).click( function ()
	{
		flipCard( $( this ).attr( 'data-card-index' ) );
	} );
} );

function renderCards()
{
	$( '#cards' ).html(
			'<div class="card">' +
					'<div class="face front"></div>' +
					'<div class="face back"></div>' +
					'</div>'
	);

	var numOfCards = 9;

	for ( var i = 0; i < numOfCards - 1; i++ ) {
		$( '.card:first-child' ).clone().appendTo( '#cards' );
	}

	$( '#cards' ).children().each( function ( index )
	{
		$( this ).css( {
			'left':($( this ).width() + 35) * ( index % 3 ),
			'top':($( this ).height() + 20) * Math.floor( index / 3 )
		} );

		$( this ).attr( 'id', 'card' + index );
		$( this ).attr( 'data-card-index', index );
		$( '#card' + index + ' .back' ).addClass( cards[index] );
	} );

	$( '#cards' ).show();
}

function flipCard( cardIndex )
{
	if ( $( '#card' + cardIndex ).hasClass( 'flipped' ) ) {
		$( '#card' + cardIndex ).removeClass( 'flipped' );
	}
	else {
		$( '#card' + cardIndex ).addClass( 'flipped' );
	}
}

Zeile 1
Hier erzeugen wir uns als erstes einmal ein Array, dass unsere Karten enthält. Die enthaltenen Strings werden als Klasse (class) genutzt, so dass mittels unserem CSS, die entsprechende Karte angezeigt wird.

Zeile 13 – 21
Wenn das DOM fertig geladen ist, rufen wir die renderCards-Funktion auf. Weiterhin geben wir an, dass beim Klick auf eine Karte die flipCard-Funktion aufgerufen wird.

Zeile 23 – 51
Die renderCards-Funktion dient zum Erzeugen und Anzeigen unserer Karten. Über das data-Attribut card-index können wir feststellen um welche Karte es sich handelt. Der Index entspricht dem Index der jeweiligen Karte innerhalb unseres cards-Array.

Zeile 53 – 61
Die flipCard-Funktion dient dazu eine Karte umzudrehen. Entweder wird die Karte von der Vorderansicht zur Rückansicht oder umgekehrt umgedreht.

Fazit

Mit ein wenig CSS3 und JavaScript lässt sich auf einfache Weise eine schön anzuschauende Karten-Flip-Animation erstellen.

Wie findet ihr diese Flip-Animation?

Kommentare  
8 Kommentare vorhanden
1 Romeo schrieb am 12. März 2013 um 10:26 Uhr

Hallo Stephan

Vielen Dank für das Tutorial. 🙂

Ich finde den Code super.

Kannst du mir sagen was für ein JavaScript im cards.js stehen müssten, wenn ich nun will, dass die Karten zufällig verteilt werden und beim reloaden wieder neu gemischt/verteilt wird.

Viele Grüsse
Romeo

2 Stephan L. schrieb am 12. März 2013 um 11:17 Uhr

Hallo Romeo,

dazu müsstest du einfach das Array cards mischen.

Leider gibt es in JavaScript standardmäßig keine shuffle-Funktion oder ähnliches für Arrays (man möge mich korrigieren, falls ich falsch liege :P).

Du musst dir also selber eine solche Funktion erstellen. Fündig wirst du z.B. bei stackoverflow.com: How can i shuffle an array in JavaScript?.

Je nachdem, ob du nun eine einfache Funktion nutzt oder die Array-Klasse mittels prototype erweiterst, kannst du die Karten dann wie folgt mischen:

$( document ).ready( function ()
{
	// shuffle-Funktion
	cards = shuffle(cards);

	// oder falls per prototype umgesetzt
	cards.shuffle();

	renderCards();

	$( '.card' ).click( function ()
	{
		flipCard( $( this ).attr( 'data-card-index' ) );
	} );
} );

Bei jedem Reload hast du dann zufällig sortierte/gemischte Karten.

Gruß

Stephan

3 Romeo schrieb am 13. März 2013 um 02:27 Uhr

Etwa so? 🙂

Array.prototype.shuffle = function () {
    for (var i = this.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var tmp = this[i];
        this[i] = this[j];
        this[j] = tmp;
    }

    return this;
}

var cards = [
    'cardB1',
    'cardB2',
    'cardB3',
    'cardP1',
    'cardP2',
    'cardP3',
    'cardG1',
    'cardG2',
    'cardG3'
];
	  	    
$( document ).ready( function ()
{
    // shuffle-Funktion
    // cards = shuffle(cards);
	 
    // oder falls per prototype umgesetzt
    cards.shuffle();
4 Stephan L. schrieb am 13. März 2013 um 08:33 Uhr

Ja, genau so etwas habe ich gemeint. 😉 Damit sollten nun die Karten jedes mal zufällig gemischt sein.

Gruß Stephan

5 Romeo schrieb am 13. März 2013 um 13:50 Uhr

Super. Danke. 🙂

und wenn wir das erweitern würden?

Z.b ich will dass die Karte-1 eine zufällige blaue Karte ausgibt.

Karte-2, zufällige Grüne
Karte 3, zufällige Violette

In meiner Fantasie denke ich da an ein Array-im-Array.

6 Stephan L. schrieb am 13. März 2013 um 15:10 Uhr

Joah, mehrdimensionales Array wäre eine Möglichkeit:

var cards = [
	[
		'cardB1',
		'cardB2',
		'cardB3'
	],
	[
		'cardP1',
		'cardP2',
		'cardP3'
	],
	[
		'cardG1',
		'cardG2',
		'cardG3'
	]
];

$( document ).ready( function ()
{
	$.each(cards, function(index, tmpCards)
	{
		cards[index] = tmpCards.shuffle();
	});
	
	// [...]
} );

In der renderCards-Gunktion müsstest du dann halt immer auf das entsprechende Farb-Array zugeifen und dir daraus eine Karte ziehen.

7 Romeo schrieb am 13. März 2013 um 16:23 Uhr

Hallo Stephan

Hört sich interessant an.
Ich habe es nun selber versucht weiter zu programmieren.
Leider komme ich nicht weiter!

in der renderCards-Funktion.
Wie würdest du den Code texten?
Ist innerhalb der Funktion eine While-Schleife?

Viele Grüsse
Romeo

8 Stephan L. schrieb am 14. März 2013 um 09:42 Uhr

Hi Romeo,

habe im Moment nicht wirklich die Zeit mich damit näher zu beschäftigen.

Im Prinzip musst du nur den Inhalt in dieser Schleife anpassen:

$( '#cards' ).children().each( function ( index )
{
}

Bei 9 Karten die wie im Beispiel 3×3 angeorndet sind, würde ja z.B. ein extra Counter helfen. Den erhöhst du dann in der Schleife immer um 1. Am Anfang der Schleife testet du dann, ob der Counter < 3 ist (angenommen du initialisierst den Counter mit 0) und wenn das nicht der Fall ist, setzt du Counter wieder auf 0. Dadurch nimmt der Counter immer die Werte 0, 1 und 2 an. Damit kannst du dann immer auf das jeweilige Farb-Array zugreifen. Zusätzlich musst du dann nur noch irgndwie speichern, welches Element des jeweiligen Farb-Arrays du bereits verwendest hast.GrüßeStephan

0 Trackbacks/Pingbacks vorhanden
Du bist herzlich eingeladen auch ein Kommentar zu hinterlassen!
Kommentar schreiben

Vielen Dank für dein Kommentar!