Animationen mit CSS3 - Teil 5 -Beispiel einer komplexen CSS3 Keyframe Animation

Ich möchte hier noch eine CSS3-Animation komplexerer Art vorstellen. Es handelt sich um eine Szene, die aus einer Wiese mit Gras und bunten Blumen besteht. Eine Blume ist besonders groß und steht im Vordergrund. Eine Biene kommt in die Szene geflogen, sieht die Blume und fliegt auf die Blume im Vordergrund zu. Die Blume reagiert auf die Annäherung der Biene, in dem sie sich emporreckt. Die Biene flirtet mit der Blume (Herzen), die sich nun noch stärker der Biene zuwendet. Doch dann fliegt die Biene weiter und die Blume sinkt enttäuscht in ihre Ausgangsposition zurück. Auf dem Rückweg kommt die Biene wieder bei der Blume vorbei, beachtet sie aber nicht.

Das Ganze soll so aufgebaut werden, dass der Webseitenbesucher die Animation ab- und wieder anschalten kann. Außerdem soll die Animation bei mehrfachem Aufruf (z.B. für den Fall, dass sie auf mehreren Seiten einer Website eingebaut wird) für eine Weile deaktiviert werden.

Grundaufbau der Animation

Die verwendeten Grafiken

Alle getrennt zu animierenden Elemente müssen durch getrennte Grafiken dargestellt werden. Es gibt daher die Grafiken:

  • auge.png
  • braue1.png
  • braue2.png
  • flower-156452-01.png
  • fluegel1.png
  • fluegel2.png
  • herz.png
  • koerper.png
  • mund.png
  • pupille.png
  • stachel.png
  • wiese-3.png
  • wiese-4.png

Der HTML-Code

Den einzelnen Grafiken entsprechen jeweils div-Layer, die mit eindeutigen Kennungen versehen sind. Außerdem sieht man, dass einige HTML-Elemente auch noch die Klasse ani haben und dass es am Ende des gezeigten HTML-Codes einen Link mit der ID anausbutton gibt. Auf diese beiden Besonderheiten gehe ich am Ende des Beitrages ein.
<div id="kopf">
    <div id="animation">
    <div id="blume1" class="ani"></div>
    <div id="biene" class="ani">
        <div id="fluegel1" class="ani"></div>
        <div id="koerper">
        </div>
            <div id="stachel"></div>
            <div id="mund"></div>
            <div id="brauel"></div>
            <div id="brauer"></div>                
            <div id="brauge"></div>
            <div id="augel">
                <div id="pupillel" class="ani"></div>
            </div>                
            <div id="auger">
                <div id="pupiller" class="ani"></div>
            </div>
            <div id="herz1" class="ani"></div>
            <div id="herz2" class="ani"></div>
        <div id="fluegel2" class="ani"></div>
    </div>
    <div id="vordergrund"></div>
    <div id="schalter">
       <a id="anausbutton" title="Animation aus- bzw- anschalten" href="#" onclick="switchanimation()">Animation aus</a> 
    </div><!-- Ende schalter -->
    </div><!-- Ende animation -->            
</div><!-- Ende kopf -->

Die CSS3-Animationen

Die eigentlichen Animation werden mit Hilfe von keyframes realisiert. Es sind eigentlich mehrere Animationen, denn nicht nur die Biene wird animiert, sondern mit der Biene ihre Augen und Flügel, schließlich auch noch die Blume und die Herzen, die die aussendet. Wichtig ist dabei, dass die Animation der Biene und die Animationen der Blume und der Herzen miteinander synchronisiert werden. Die erreicht man, in dem die Animationsdauer dieser drei Animationen identisch ist, man findet jeweils

animation-duration: 10s;

Ich verzichte hier darauf, den kompletten CSS-Code einzufügen, den kann man sich bei Bedarf direkt aus dem Quellcode der Quellcode der CSS3-Animation holen. Exemplarisch wird nur der CSS-Code für die Biene gezeigt:

#biene{
    position:relative;
    top:-250px;
    left:885px;
    width:190px;
    height:95px;
    transform: scale(0.1);
    -webkit-transform: scale(0.5);
    animation-name: bienebewegdich;
    animation-duration: 10s;
    animation-iteration-count: infinite;
    -webkit-animation-name: bienebewegdich;
    -webkit-animation-duration: 10s;
    -webkit-animation-iteration-count: infinite;
}

@keyframes bienebewegdich {
    10%{
    top:-200px;
    left:550px;
    }
    
    25%{
    top:-120px;
    left:520px;
    transform: scale(0.5);        
    }

    28%{
    top:-120px;
    left:520px;
    transform: scale(0.5);        
    }    

    40%{
    top:-20px;
    left:400px;
    transform: scale(0.3);        
    }

    45% {
    top:-70px;    
    left: 220px;
    transform: scale(0.5);        
  }

    50% {
    top:-70px;    
    left: -220px;
    transform: scale(0.5);        
    }

    51% {
    top:-70px;    
    left: -220px;
    transform: scale(-0.5,0.5);        
    }
    
    99% {
    transform: scale(-0.1,0.1);
    }
}        

@-webkit-keyframes bienebewegdich {
    10%{
    top:-200px;
    left:550px;
    }
    
    25%{
    top:-120px;
    left:520px;
    -webkit-transform: scale(0.5);        
    }

    28%{
    top:-120px;
    left:520px;
    -webkit-transform: scale(0.5);        
    }    

    40%{
    top:-20px;
    left:400px;
    -webkit-transform: scale(0.3);        
    }

    45% {
    top:-70px;    
    left: 220px;
    -webkit-transform: scale(0.5);        
  }

    50% {
    top:-70px;    
    left: -220px;
    -webkit-transform: scale(0.5);        
    }

    51% {
    top:-70px;    
    left: -220px;
    -webkit-transform: scale(-0.5,0.5);        
    }
    
    99% {
    -webkit-transform: scale(-0.1,0.1);
    }
}        

CSS3 Animation stoppen

Um zu vermeiden, dass die CSS3-Animation den Besucher der Website ablenkt oder nervt, soll ihm die Möglichkeit gegeben werden, sie selbst abzuschalten (und bei Bedarf auch wieder in Gang zu setzen). Dazu wird JavaScript benutzt. Ich habe die Funktionen switchanimation() und switchbutton() erstellt. switchanimation() schaltet die CSS3-Animation aus bzw. wieder an, switchbutton() dient lediglich dazu den am Link angezeigten Text zu ändern. In switchanimation() ist der Code für ältere Versionen des Firefox-Browsers auskommentiert (mit vendor-Präfix MozAnimationPlayState. Ebenfalls ist eine offensichtlich nicht wirksame Schreibweise mit Großbuchstaben AnimationPlayState.

function switchanimation(){
    switchbutton();
    for ( var i = 0; i < anis.length; i++ ) {
        /* if ( anis[i].style.MozAnimationPlayState === 'running' ) {
            anis[i].style.MozAnimationPlayState = 'paused';
        } else {
            anis[i].style.MozAnimationPlayState = 'running';
        }*/
        if ( anis[i].style.webkitAnimationPlayState === 'running' ) {
            anis[i].style.webkitAnimationPlayState = 'paused';
        } else {
            anis[i].style.webkitAnimationPlayState = 'running';
        }
        /*if ( anis[i].style.AnimationPlayState === 'running' ) {
            anis[i].style.AnimationPlayState = 'paused';
        } else {
            anis[i].style.AnimationPlayState = 'running';
        }*/
        if ( anis[i].style.animationPlayState === 'running' ) {
            anis[i].style.animationPlayState = 'paused';
        } else {
            anis[i].style.animationPlayState = 'running';
        }
    }                  
}

function switchbutton(){
    if ( document.getElementById("anausbutton").innerHTML === 'Animation an'){
        document.getElementById("anausbutton").innerHTML = 'Animation aus';
    } else {
        document.getElementById("anausbutton").innerHTML = 'Animation an';
    }
}
Bei der Statussetzung wird auf das Array anis[i] zugegriffen. Das erkläre ich weiter unten.

Animation bei Mehrfachaufruf verhindern

Es wird davon ausgegangen, dass man diese Animation auch in eine Website mit mehreren Einzelseiten einbauen kann. Da erscheint es mir sinnvoll, dass die Animation nicht bei jedem weiteren Seitenaufruf automatisch startet. Dies kann man im Grunde nur verhindern, in dem man Cookies nutzt.

Kleine Cookie-JavaScript-Bibliothek

Um den Umgang mit Cookies zu vereinfachen, verwende ich eine kleine JavaScript-Bibliothek mit Funktionen zum Umgang mit Cookies. Die Bibliothek sieht so aus:

/**
* Funktion: get_cookie()
* holt cookie-Wert
* Parameter:cookie-Name
* Rückgabewert: cookie-Wert/ false
**/
function get_cookie( cookieName )
{
    strValue = false;
    if( strCookie = document.cookie )
        {
            if( arrCookie = strCookie.match( new RegExp( cookieName + '=([^;]*)', 'g')))
                {
                    strValue=RegExp.$1;
                }
        }
    return(strValue);
}
   
/**
* Funktion:set_cookie()
* setzt cookie
* Parameter: cookie-Name,cookie-Wert,nicht mehr Haltbarkeit in Tagen sondern Haltbarkeit in Minuten
* Rückgabewert: true/false
**/
//function set_cookie(cookieName,cookieValue,intDays)
function set_cookie(cookieName,cookieValue,intMin)
{
    if(!is_cookie_enabled())
        {
            return false;
        }
    objNow = new Date();
    //strExp = new Date( objNow.getTime() + ( intDays * 86400000) );
    strExp = new Date( objNow.getTime() + ( intMin * 60000) );
    document.cookie = cookieName + '=' +
                      cookieValue + ';expires=' +
                      strExp.toGMTString() + ';';
    return true;
}
 
/**
* Funktion:delete_cookie()
* Löscht cookie
* Parameter: cookie-Name
* Rückgabewert: true/false
**/
 
function delete_cookie(cookieName)
{
    if(document.cookie)
        {
            document.cookie = cookieName + '=' +
                              get_cookie(cookieName) +
                              ';expires=Thu, 01-Jan-1970 00:00:01 GMT;';
            return true;
        }
    return false;
}

/**
* Funktion is_cookie_enabled()
* prüft ob cookies erlaubt sind
* Parameter: nix
* Rückgabewert: true/false
**/
function is_cookie_enabled()
{
    if(typeof navigator.cookieEnabled!='undefined')
        {
            return navigator.cookieEnabled;
        }
    set_cookie('testcookie','testwert',1);
    if(!document.cookie)
        {
            return false;
        }
   
    delete_cookie('testcookie');
    return true;        
}

Initialisierung

In einer window.onload=function() wird die Initialisierung und Statusabfrage vorgenommen. Zunächst wird die Variable anis angelegt und als Feld mit allen HTML-Objekten gefüllt, die die Klasse .ani haben. Dann wird abgefragt, ob der Cookie Biene schon existiert, weil der Besucher schon vorher eine Seite mit der Animation aufgerufen hat. Wenn der Cookie existiert, werden die Animationen in den Pausen-Status versetzt (zu den auskommentierten Zeilen siehe meine Anmerkung weiter oben). Wenn er noch nicht existiert, wird er mit einer Verfallszeit von 5 Minuten gesetzt und die Animation wird gestartet. Der JavaScript-Code dazu sieht dann so aus:

var anis;
window.onload=function(){
    anis = document.querySelectorAll('.ani');
    if (get_cookie('Biene')){
        // alert('keks ist da');
        switchbutton();
        for ( var i = 0; i < anis.length; i++ ) {
            //anis[i].style.MozAnimationPlayState = 'paused';
            anis[i].style.webkitAnimationPlayState = 'paused';
            //anis[i].style.AnimationPlayState = 'paused';
            anis[i].style.animationPlayState = 'paused';
        }
    }
    else {
    set_cookie('Biene','1',5);
        for ( var i = 0; i < anis.length; i++ ) {
            //anis[i].style.MozAnimationPlayState = 'running';
            anis[i].style.webkitAnimationPlayState = 'running';
            //anis[i].style.AnimationPlayState = 'running';
            anis[i].style.animationPlayState = 'running';
        }
    }
}