Showing posts with label css3. Show all posts
Showing posts with label css3. Show all posts

Sunday, June 26, 2011

NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7

Since Mibbu framework supports CSS animations, it's good moment to create version exclusively for mobile devices, without using heavy and hard to render canvas, and with very limited JavaScript DOM interactions - CSS FTW! So I remove about 50% of code from original branch and test it on my Samsung Wave (bada has one of the best mobile browsers ever, so that was my starting point). And it simply doesn't work:
NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7
After short research I saw that Allegro ('Polish Ebay') had the same problem on Desktop Chrome months ago. After couple more hours of reading documentation I found a clue, that Webkit is freaking out if you try to put HTML content into style tag. So I switch
var cssStyle = document.createElement('style');
    cssStyle.innerHTML = 'body { color: #000; }';
to
var cssStyle = document.createElement('style');
    cssStyle.innerText = 'body { color: #000; }';
and everything works.

Friday, June 24, 2011

Few words about my CSS Nyan Cat

Last week Mozilla together with Finnish demoscene hackers organized Flame Party in capital of Finland, Helsinki. More than 100 participants worked whole day on outstanding web demos in two main categories - Single Effect and Main Demo.
Because of nearly release of stable Firefox 5, first Mozilla's browser with CSS3 Animation support, I decide to create CSS3 demo for the Single Effect Compo.
Since I really enjoy all that 4chan-like mems stuff, I chose Nyan Cat, as one of the most 'fresh' ones. In case you don't know it (check the progress bar!):


I didn't use any graphics to code my CSS Nyan Cat. It is completely drawn and animated in CSS. The 'pop-tart' body is created with two rounded cornered divs and big, pink dots separated with non-breaking spaces:
#toastBody {
    background-color:#fad695;
    width:100px;
    height: 70px;
    border: solid #000 5px;
    border-radius: 15px;
    padding: 2px;
    position:absolute;
    z-index:19;
}

#toastBody > div {
    width:100px;
    height:70px;
    border-radius: 30px;
    background-color: #fc9dff;
    display:block;
    color: #da3eb9;
    font-size: 40px;
    line-height: 10px;
}
All the animations was declared with @-moz/webkit-keyframe (I wrote a lot about this method before).

I made couple of unusual things during development. For example, look on the cat's mouth:


Yup, it is rotated 'E' letter:
<div id="mainHead" class="skin">
    <div class="mouth">E</div>
</div>

.mouth {
    position: absolute;
    -moz-transform: scale(2, 0.7) rotate(-90deg);
    -webkit-transform: scale(2, 0.7) rotate(-90deg);
    font-family: Arial;
    font-size: 25px;
    font-weight: bold;
    top:9px;
    left:37px;
    color: #000;
}

What about the rainbow behind the cat? I just cropped part of original image, put it into CSS Gradient Editor by ColorZilla (awesome tool BTW, but still without couple of necessary features I use daily; I think I will create something like this on my own), which generates me css gradient ready for pasting into the div background:
.rainbow {
 position:absolute;
 width:45px;
 height:90px; 
 background: -moz-linear-gradient (top, #d91a12 15%, #e13300 15%, #ff7f14 16%, #f2ab03 32%, #ebc000 32%, #fade00 33%, #efff03 48%, #56fc02 49%, #52ff01 66%, #4ade7e 67%, #3baaf2 67%, #3baaf2 84%, #7337f7 84%, #6b40f2 100%);
}
The most annoying thing was the star. Animated stars in the background are made up from 8 animated elements. I google "nyan cat sprite" and found all the star frames [like this]. The only way to animate it was pixel-perfect animation of each of 8 divs. It took me really lot of time:
@-moz-keyframes star1 {
 0% { top: 0; height: 5px;}
 33.19% { top: 0; height: 5px; }
 33.2% { height:10px; top:0; }
 49.79% { height:10px; top:0; }
 49.8% { height:10px; top:5px; }
 66.39% {height:10px; top:5px; }
 66.4% { height:5px; top:10px;}
 82.99% { height:5px; top:10px;}
 83% { height: 5px; top: 15px; }
 99.99% { height: 5px; top: 15px; }
 100% { top: 0; height: 5px; }
}

@-moz-keyframes star2-3-6-7 {
 0% { visibility: hidden; }
 16.59% { visibility: hidden; }
 16.6% { visibility: visible; }
 33.19% { visibility: visible; }
 33.2% { visibility: hidden; }
 100% { visibility: hidden; }
}

@-moz-keyframes star4 {
 0% { left: 0; width: 5px; visibility: visible;}
 33.19% { left: 0; width: 5px; }
 33.2% { width:10px; left:0; }
 49.79% { width:10px; left:0; }
 49.8% { width:10px; left:5px; }
 66.39% {width:10px; left:5px; }
 66.4% { width:5px; left:10px;}
 82.99% { width:5px; left:10px;}
 83% { width: 5px; left: 15px; visibility:hidden;}
 99.99% { width: 5px; left: 15px; visibility:hidden;}
 100% { left: 0; width: 5px; visibility:hidden;}
}

@-moz-keyframes star5 {
 0% { left: 38px; width: 5px; visibility: visible;}
 33.19% { left: 38px; width: 5px; }
 33.2% { width:10px; left:33px; }
 49.79% { width:10px; left:33px; }
 49.8% { width:10px; left:28px; }
 66.39% {width:10px; left:28px; }
 66.4% { width:5px; left:28px;}
 82.99% { width:5px; left:28px;}
 83% { width: 5px; left: 15px; visibility:hidden;}
 99.99% { width: 5px; left: 15px; visibility:hidden;}
 100% { left: 0; width: 5px; visibility:hidden;}
}

@-moz-keyframes star8 {
 0% { top: 32px; height: 5px; visibility:visible;}
 33.19% { top: 32px; height: 5px; }
 33.2% { height:10px; top:28px; }
 49.79% { height:10px; top:28px; }
 49.8% { height:10px; top:23px; }
 66.39% {height:10px; top:23px; }
 66.4% { height:5px; top:18px;}
 82.99% { height:5px; top:18px;}
 83% { height: 5px; top: 15px; visibility:hidden;}
 99.99% { height: 5px; top: 15px; visibility:hidden;}
 100% { top: 0; height: 5px; visibility:hidden;}
}

.star {
 position: absolute;
 width: 40px;
 height: 40px;
 z-index: 10;
}

.star div {
 width: 5px;
 height: 5px;
 background-color: #fff;
 position: absolute;
 -moz-animation: star1 0.4s linear 0s infinite;
 -webkit-animation: star1 0.4s linear 0s infinite;
}

Here is the final result of everything: CSS NYAN CAT, and Github repo. If you like it, don't forget to click "I like it" on Mozilla's page!

Sunday, May 29, 2011

CSS3 animations in Mibbu

Last week I implement CSS Animations in my gamedev micro framework, Mibbu.
It is possible now to animate sprites in three different ways - cropping parts of the sprite with .drawImage() in 'canvas mode', manipulating 'top' & 'left' attributes of absolute position of the image [both described in here] and CSS Animation in DOM mode.
For now Mibbu supports CSS animations only in webkit based browsers. I know that beta version of Firefox supports it as well, but I didn't find easy way to detect it. In webkit we can just check what is the initial value of given attribute (use whatever DOM element you want), like this:
if (typeof document.body.style.webkitAnimation !== "undefined") {
//all your animation are belong to us
} else {
//no css animations:(
}
Unfortunately it don't work in Aurora, mozAnimation always return 'undefined'. Is there any way to easy detect it?

The main point in creating css animations is preparing proper keyframes in a css classes and connecting it to the DOM elements with description parameters like duration or number of iterations. CSS engine will be responsible for sprite animation so draw() function of each sprite object should be empty. The keyframes are generated during constructing the object and append to the document - one class in one script element, it will be easier to edit them when the parameters of the animation will change during the gameplay. I also wrote a little function to convert speed of an animation (from Canvas & DOM mode) to the CSS Animation Duration parameter.
var calculateSpeed = function(speed, frames) {
    return (~~((1 / (60 / speed)) * 100) / 100) * (frames+1);
};

constructAnimationClass = function(){
 var animClass = "@-webkit-keyframes 's" + t.id + "' {\n",
        step = 100 / (t.fs + 1),
        str = '% { -webkit-transform: translate(';

    for (var q = 0; q < t.fs+1; q++) {
        animClass += ~~((step * q) * 100) / 100 + str + t.animation * t.width*-1 + 'px,' + q * t.height * -1 + 'px); }\n';
        animClass += ~~((step * (q + 1) - 0.01) * 100) / 100 + str + t.animation * t.width * -1 + 'px,' + q * t.height * -1 + 'px); }\n';
    }
                
    return animClass += '100'+ str +t.animation*t.width+'px, 0px); }\n}';
                
};

//append created class to the document
t.animStyle = document.createElement('style');
t.animStyle.innerHTML = constructAnimationClass();
document.body.appendChild(t.animStyle);
Above code creates class like this: And every sprite needs to implement description of the animation (name is created by concatenating 's' and internal id of the sprite:
t.style.webkitAnimation = "'s"+t.id+"' "+calculateSpeed(t.speed, t.fs)+"s linear 0 infinite";
Main problem I had with implementing this was pausing the game - even if main loop stops, CSS engine still animates the keyframes. So I just set '0' for the -webkit-animaition-duration parameter:
'off': function(){
    MB_Stop();
    if (MB_usingCSSAnimations){
        var i = MB_elements.length;
        for (;i--;){
            if (MB_elements[i].image)
                MB_elements[i].image.style.webkitAnimationDuration = 0;
        }
    }
};
It sucks but it works. Anyone know better solution? Next step is to provide support of webkitAnimationIterations for iteration's callbacks (now it is calculated using JavaScript, not with the events, but contrary to what I thought webkit has already supported DOM events for animation [thanks Askoth]). If you want help feel free and contribute: Mibbu on github. There are also some issues I found creating new features and I have no time to fix it now. If you use Mibbu and have some ideas or found any bugs, write me about it or fork & pull request on Github.

BTW, Github will be one of the sponsors of onGameStart, HTML5 Game Conference. We will open registration on Monday evening Central European time, so check the conference page and don't miss it!

Sunday, February 27, 2011

CSS3 sprite animation, issues in Safari

Together with CSS3 standard we get awesome tool for creating hardware accelerated css-only animated sprites. For now it is implemented only in webkit based browsers like Safari, Chrome or most of the mobile browsers. Paul Bakaus described it on his blog months ago, with additional approaches and performance optimization methods. Also Marek Pawlowski said a lot about this on his DevMeeting gamedev workshop. Working on my new mobile game, I've tested everything I could find all over web. And some of the examples (like that Paul's created with Doug Neiner) did not works on Safari and some mobiles (like Samsung's Dolfin on my bada Wave). I spend couple of annoying hours to figure out what happens, analyzing different use cases, different examples and documentation pages. But solution was simple as hell:
Safari and some of mobile browsers cannot animate any element with CSS3 animation if there is no '0%' and '100%' step.
That's why example from Paul's blog didn't want to work when I test them:
@-webkit-keyframes 'animationName' {
  0% { background-position: 0px 0px; }
  12.5% { background-position: -128px 0px; }
  25% { background-position: -256px 0px; }
  37.5% { background-position: -384px 0px; }  
  50% { background-position: -512px 0px; }
  62.5% { background-position: -640px 0px; }
  75% { background-position: -768px 0px; }
  87.5% { background-position: -896px 0px; }
}
Adding the last frame, with the same parameters as the first one, fixes the problem:
@-webkit-keyframes 'animationName' {
  0% { background-position: 0px 0px; }
  12.5% { background-position: -128px 0px; }
  25% { background-position: -256px 0px; }
  37.5% { background-position: -384px 0px; }  
  50% { background-position: -512px 0px; }
  62.5% { background-position: -640px 0px; }
  75% { background-position: -768px 0px; }
  87.5% { background-position: -896px 0px; }
  100% { background-position: 0px 0px; }
}
Of course I didn't want to show that Paul and other guys was wrong - for sure all of them has bigger experience and knowledge than me. And their solutions will eventually work when browsers will implement the standards (what was the point I supposed) - but I was looking for something what will work here and now.