Reputation: 1157
I am creating a solitary game. So far I got most things working, but the card flip animation is a pain in the a**.
See this fiddle (it might be a bit slow since the whole game code is in it)
When you drag and drop a card, the back of the card is replaced with a front. This is done in this part of the code:
upturn: function () {
with(this) {
if (is_downturned()) {
element.children('.downturned')
.removeClass('downturned').addClass(_SUITS[_suit()].color)
.append('<img height="80px" width="50px" border="0" src="http://mauricederegt.com/test/solitaire/cards/' + _RANKS[_rank()] + '' + _SUITS[_suit()].symbol + '.jpg">') //NEW
element.addClass(_scope());
if (element.hasClass('ui-draggable-disabled')) {
element.draggable('enable');
} else {
element.draggable({
containment: '#field',
revert: 'invalid',
revertDuration: 200,
zIndex: 99
});
}
if (!element.hasClass('ui-droppable-disabled')) {
element.droppable($.extend(DROPPABLE_OPTIONS, {
accept: _tableau_pile_scope()
}));
}
}
}
}
Basically it removes the back of the card (.removeClass('downturned')
) and adds a new class (.addClass(_SUITS[_suit()].color)
) where suits
are the hart, clover etc and the color
is black or red.
Now when this action happens, I want to add a nice flipping animation.
I have played around with some tutorials on the web, but non gave me a working solution (mostly the cards starting to act weird or the game stopped working).
The closest I could get was adding:
-webkit-perspective: 600px;
-webkit-transform-style: preserve-3d;
-webkit-transform: rotateY(180deg);
/* -- transition is the magic sauce for animation -- */
-webkit-transition: 0.6s;
in the CSS in the class:
.red,
.black {
cursor: pointer;
<<<code added here>>>
}
This, however, resulted in some weird actions (though the card is flipping):
So how can I add a nice card flipping animation? Hope someone can help me out.
EDIT:
By changing this.element.addClass('container').append('<div class="downturned">');
to this.element.addClass('container').append('<div class="downturned">').append('<div class="hiddencardfront">');
in the JS part, I can create an extra empty div, (which I think I need for the card flip animation), but I still can't make it work
Upvotes: 4
Views: 9478
Reputation: 4592
I guess there are a couple of ways of doing it. But I guess I'm to suggest the old-ish way of doing it using only one element. Essentially since it's a 2D object, the front and back will never show at the same time and there is going to be a point where the card will "disappear". So we can split the animation into two. "Hiding" the card (Here we can animate the width to zero). Changing the image to the other card, then "showing" the card again (animate from zero to the original width again). So if we use jQuery, with an html of
<img class="card" src="http://mauricederegt.com/test/solitaire/cards/back.jpg" />
the jQuery will look something like:
var CARDWIDTH = 50;
function turnCompatible(elem, src) {
$(elem).animate({
width: 0, //animate to zero
marginLeft: CARDWIDTH / 2,
marginRight: CARDWIDTH / 2
}, function () {
this.src = src //change the image
$(this).animate({
width: CARDWIDTH, //show the image again
marginLeft: 0,
marginRight: 0,
})
})
}
$(".card").click(function(){
turnCompatible(this, src)
})
And this will more or less work. Though the animation could be better improved for example with CSS transforms and animations but this solution would be compatible with browsers that don't support CSS transforms (mostly IE. IE<10). And with that you can do something like
function turnCSS(elem, src) {
$(elem)
.addClass("flipping")
.bind("transitionend webkittransitionend", function () { //should add more prefixes
this.src = src;
$(this)
.unbind("transitionend webkittransitionend")
.removeClass("flipping")
})
}
with the following CSS
.card {
width:50px;
height:80px;
-webkit-transition:-webkit-transform 0.5s;
transition:transform 0.5s;
background:#FF0;
}
.flipping {
transform: translate(0, 20px) rotateY(90deg);
-webkit-transform: translate(0, 20px) rotateY(90deg);
}
So perhaps the look is not what you're looking for but it is possible to do the flip animation with just one element.
Upvotes: 3
Reputation: 1157
I think the big problem I am having is that when this was build, no flip animation was considered. So there is just 1 Div, where more are needed to make it work. Also the drag and drop code used is old and interrups with the animation code.
I guess the only solution is to start over from scratch, with animations in mind this time.
All thanks for helping and given solution, but starting over is the way to go I think
Greetings
Upvotes: 1
Reputation: 5548
Regarding your three issues with CSS 3d transforms.
For points 1 & 2 add:
-webkit-backface-visibility:hidden; /* Chrome, Safari, Opera */
backface-visibility:hidden;
And to center your element use:
transform-origin:50% 50%;
-ms-transform-origin:50% 50%; /* IE 9 */
-webkit-transform-origin:50% 50%; /* Chrome, Safari, Opera */
Upvotes: 0
Reputation: 1231
Try this
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style>
/* Chrome, Safari, Opera */
@-webkit-keyframes myfirst1 {
from {
-webkit-transform : rotateY(180deg);
-moz-transform : rotateY(180deg);
-ms-transform : rotateY(180deg);
transform: rotateY(180deg);}
to {
-webkit-transform : rotateY(90deg);
-moz-transform : rotateY(90deg);
-ms-transform : rotateY(90deg);
transform: rotateY(90deg);}
}
@-webkit-keyframes myfirst2 {
from {
-webkit-transform : rotateY(90deg);
-moz-transform : rotateY(90deg);
-ms-transform : rotateY(90deg);
transform: rotateY(90deg);}
to {
-webkit-transform : rotateY(0deg);
-moz-transform : rotateY(0deg);
-ms-transform : rotateY(0deg);
transform: rotateY(0deg);}
}
/* Standard syntax */
@keyframes myfirst1 {
from {
-webkit-transform : rotateY(180deg);
-moz-transform : rotateY(180deg);
-ms-transform : rotateY(180deg);
transform: rotateY(180deg);}
to {
-webkit-transform : rotateY(90deg);
-moz-transform : rotateY(90deg);
-ms-transform : rotateY(90deg);
transform: rotateY(90deg);}
}
@keyframes myfirst2 {
from {
-webkit-transform : rotateY(90deg);
-moz-transform : rotateY(90deg);
-ms-transform : rotateY(90deg);
transform: rotateY(90deg);}
to {
-webkit-transform : rotateY(0deg);
-moz-transform : rotateY(0deg);
-ms-transform : rotateY(0deg);
transform: rotateY(0deg);}
}
@-webkit-keyframes mylast1 {
from {
-webkit-transform : rotateY(0deg);
-moz-transform : rotateY(0deg);
-ms-transform : rotateY(0deg);
transform: rotateY(0deg);}
to {
-webkit-transform : rotateY(90deg);
-moz-transform : rotateY(90deg);
-ms-transform : rotateY(90deg);
transform: rotateY(90deg);}
}
@-webkit-keyframes mylast2 {
from {
-webkit-transform : rotateY(90deg);
-moz-transform : rotateY(90deg);
-ms-transform : rotateY(90deg);
transform: rotateY(90deg);}
to {
-webkit-transform : rotateY(180deg);
-moz-transform : rotateY(180deg);
-ms-transform : rotateY(180deg);
transform: rotateY(180deg);}
}
@keyframes mylast1 {
from {
-webkit-transform : rotateY(0deg);
-moz-transform : rotateY(0deg);
-ms-transform : rotateY(0deg);
transform: rotateY(0deg);}
to {
-webkit-transform : rotateY(90deg);
-moz-transform : rotateY(90deg);
-ms-transform : rotateY(90deg);
transform: rotateY(90deg);}
}
@keyframes mylast2 {
from {
-webkit-transform : rotateY(90deg);
-moz-transform : rotateY(90deg);
-ms-transform : rotateY(90deg);
transform: rotateY(90deg);}
to {
-webkit-transform : rotateY(180deg);
-moz-transform : rotateY(180deg);
-ms-transform : rotateY(180deg);
transform: rotateY(180deg);}
}
</style>
<script>
$(document).ready(function()
{
$("#btn2").hide();
$("#btn1").click(function(){
$("#btn1").hide();
$("#box1").css({ 'z-index':'2',
'-webkit-animation': 'myfirst1 5s',
'animation': 'myfirst1 5s'
});
$("#box2").css({ 'z-index':'0' ,
'-webkit-animation': 'mylast1 5s',
'animation': 'mylast1 5s'
});
setTimeout(function(){
$("#box1").css({ 'z-index':'0',
'-webkit-animation': 'myfirst2 5s',
'animation': 'myfirst2 5s'
});
$("#box2").css({ 'z-index':'2' ,
'-webkit-animation': 'mylast2 5s',
'animation': 'mylast2 5s'
});
}, 5000);
setTimeout(function(){$("#btn2").show();}, 10000);
});
$("#btn2").click(function(){
$("#btn2").hide();
$("#box2").css({ 'z-index':'2',
'-webkit-animation': 'myfirst1 5s',
'animation': 'myfirst1 5s'
});
$("#box1").css({ 'z-index':'0',
'-webkit-animation': 'mylast1 5s',
'animation': 'mylast1 5s'
});
setTimeout(function(){
$("#box2").css({ 'z-index':'0',
'-webkit-animation': 'myfirst2 5s',
'animation': 'myfirst2 5s'
});
$("#box1").css({ 'z-index':'2',
'-webkit-animation': 'mylast2 5s',
'animation': 'mylast2 5s'
});
}, 5000);
setTimeout(function(){$("#btn1").show()}, 10000);
});
});
</script>
</head>
<body>
<button id="btn1">flip</button>
<button id="btn2">Reset</button>
<div id="box1" style="position:fixed;background:#98bf21;height:100px;width:100px;margin:6px;">
</div><div id="box2" style="position:fixed;background:#bf2198;height:100px;width:100px;margin:6px;">
</div>
</body>
</html>
In this I have just animated two div kept back to back (you can replace it with necessary images,set positions and put things into function to reduce code. I have done this specially for you. so I didn't optimize it hence I ask you to customize to soot your requirement.
Upvotes: 0