begin process at 2010 03 22 11:10:00
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Graphique

 > ANIMATION VIA LES ÉQUATIONS DE ROBERT PENNER

ANIMATION VIA LES ÉQUATIONS DE ROBERT PENNER


 Information sur la source

Note :
9 / 10 - par 3 personnes
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Graphique Classé sous :animation, effets, equation Niveau :Débutant Date de création :26/06/2008 Date de mise à jour :26/06/2008 13:58:29 Vu :4 648

Auteur : XtremDuke

Ecrire un message privé
Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Cette source est une 'base' pour ceux et celles qui désirent créer leur moteur d'animations en Javascript.
Robert Penner, mathématicien en herbe plus connu dans l'univers du Flash, a mis au point il y a déjà quelques temps une serie d'équations permettant l'animation d'objets sous divers effets. On retrouve ces équations dans plusieurs librairies JS connues (mootools par exemple).

Mon exemple fournis 4 des effets les plus sympa et leur système d'utilisation. Vous trouverez l'ensemble des équations à l'adresse suivante :

http://www.robertpenner.com/easing/

Source

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  • <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
  • <head>
  • <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  • <title>Effets</title>
  • <style type="text/css">
  • body{ font: 11px/16px Arial, "Trebushet MS", Helvetica; color: #333; }
  • h2{ font-weight: bold; font-size: 14px; }
  • td.libelle{ width: 180px; }
  • td.valeur{ width: 100px; }
  • td.inputs, td.select{ width: 100%; }
  • #animation{ height: 32px; width: 32px; background: #aaccf6; margin: 22px; }
  • </style>
  • </head>
  • <body>
  • <table>
  • <tr>
  • <td class="libelle">Durée de l'animation (en ms)</td>
  • <td class="valeur"><input type="text" id="duration" value="800"/></td>
  • </tr>
  • <tr>
  • <td class="libelle">Nombre de pixels à animer</td>
  • <td class="valeur"><input type="text" id="nbPix" value="180"/></td>
  • </tr>
  • <tr>
  • <td class="libelle">Transition</td>
  • <td class="valeur">
  • <select id="transition">
  • <option value="linear" selected="selected">Lineaire</option>
  • <option value="elastic">Elastique</option>
  • <option value="bounce">Bonds</option>
  • <option value="skid">Liquide</option>
  • </select>
  • </td>
  • </tr>
  • <tr>
  • <td class="libelle">Valeur à modifier</td>
  • <td class="valeur">
  • <select id="cssRule">
  • <option value="height" selected="selected">Hauteur</option>
  • <option value="width">Largeur</option>
  • <option value="both">Hauteur et largeur</option>
  • </select>
  • </td>
  • </tr>
  • </table>
  • <input type="button" value="GO" onclick="animate()"/> <input type="button" value="Reset" onclick="reset()"/>
  • <div id="animation"></div>
  • <script type="text/javascript">
  • function $(idObj){
  • return document.getElementById(idObj);
  • };
  • var transitions = {
  • linear: function(t, b, c, d){ return c*t/d + b; },
  • elastic: function (t,b,c,d,a,p){
  • if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
  • if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
  • else var s = p/(2*Math.PI) * Math.asin (c/a);
  • return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b);
  • },
  • bounce: function(t,b,c,d){
  • if((t/=d) < (1/2.75)) {
  • return c*(7.5625*t*t) + b;
  • }else if (t < (2/2.75)) {
  • return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
  • }else if (t < (2.5/2.75)) {
  • return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
  • }else{
  • return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
  • }
  • },
  • skid: function(t,b,c,d){
  • var s = 1.70158;
  • return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
  • }
  • };
  • function reset(){
  • $('animation').style.height = '32px';
  • $('animation').style.width = '32px';
  • };
  • function animate(){
  • var target = $('animation');
  • var tmr = (1000/80); //assure une moyenne de 80 images par secondes
  • var nbSteps = Math.round($('duration').value/tmr);
  • var step = Math.abs(32 - $('nbPix').value)/nbSteps;
  • var mapping = [];
  • //On remplis un tableau contenant toutes les étapes de l'animation
  • for(var i=1; i<=nbSteps; i++){
  • mapping.push(transitions[$('transition').value](i*tmr, 32, $('nbPix').value - 32, $('duration').value));
  • }
  • var currentStep = 0;
  • var timer = window.setInterval(function(){
  • if(mapping[currentStep]){
  • if($('cssRule').value=='both'){
  • $('animation').style['height'] = mapping[currentStep]+'px';
  • $('animation').style['width'] = mapping[currentStep]+'px';
  • }else $('animation').style[$('cssRule').value] = mapping[currentStep]+'px';
  • currentStep++;
  • }else{
  • window.clearInterval(timer);
  • return;
  • }
  • }, tmr);
  • };
  • </script>
  • </body>
  • </html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Effets</title>
<style type="text/css">
	body{ font: 11px/16px Arial, "Trebushet MS", Helvetica; color: #333; }
	h2{ font-weight: bold; font-size: 14px; }
	td.libelle{ width: 180px; }
	td.valeur{ width: 100px; }
	td.inputs, td.select{ width: 100%; }
	#animation{ height: 32px; width: 32px; background: #aaccf6;	margin: 22px; }
</style>
</head>
<body>
<table>
	<tr>
		<td class="libelle">Durée de l'animation (en ms)</td>
		<td class="valeur"><input type="text" id="duration" value="800"/></td>
	</tr>
	<tr>
		<td class="libelle">Nombre de pixels à animer</td>
		<td class="valeur"><input type="text" id="nbPix" value="180"/></td>
	</tr>
	<tr>
		<td class="libelle">Transition</td>
		<td class="valeur">
			<select id="transition">
				<option value="linear" selected="selected">Lineaire</option>
				<option value="elastic">Elastique</option>
				<option value="bounce">Bonds</option>
				<option value="skid">Liquide</option>
			</select>
		</td>
	</tr>
	<tr>
		<td class="libelle">Valeur à modifier</td>
		<td class="valeur">
			<select id="cssRule">
				<option value="height" selected="selected">Hauteur</option>
				<option value="width">Largeur</option>
				<option value="both">Hauteur et largeur</option>
			</select>
		</td>
	</tr>
</table>

<input type="button" value="GO" onclick="animate()"/> <input type="button" value="Reset" onclick="reset()"/>

<div id="animation"></div>

<script type="text/javascript">
	function $(idObj){
		return document.getElementById(idObj);
	};
	
	var transitions = {
		linear: function(t, b, c, d){ return c*t/d + b; },
		elastic: function (t,b,c,d,a,p){
			if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
			if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
			else var s = p/(2*Math.PI) * Math.asin (c/a);
			return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b);
		},
		bounce: function(t,b,c,d){
			if((t/=d) < (1/2.75)) {
				return c*(7.5625*t*t) + b;
			}else if (t < (2/2.75)) {
				return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
			}else if (t < (2.5/2.75)) {
				return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
			}else{
				return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
			}
		},
		skid: function(t,b,c,d){
			var s = 1.70158;
			return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
		}
	};
	
	function reset(){
		$('animation').style.height = '32px';
		$('animation').style.width = '32px';
	};
	
	function animate(){
		var target = $('animation');
		var tmr = (1000/80); //assure une moyenne de 80 images par secondes
		var nbSteps = Math.round($('duration').value/tmr);
		var step = Math.abs(32 - $('nbPix').value)/nbSteps;
		var mapping = [];
		//On remplis un tableau contenant toutes les étapes de l'animation
		for(var i=1; i<=nbSteps; i++){
			mapping.push(transitions[$('transition').value](i*tmr, 32, $('nbPix').value - 32, $('duration').value));
		}
		var currentStep = 0;
		var timer = window.setInterval(function(){
			if(mapping[currentStep]){
				if($('cssRule').value=='both'){
					$('animation').style['height'] = mapping[currentStep]+'px';
					$('animation').style['width'] = mapping[currentStep]+'px';
				}else $('animation').style[$('cssRule').value] = mapping[currentStep]+'px';
				currentStep++;
			}else{
				window.clearInterval(timer);
				return;
			}
		}, tmr);
	};

</script>
</body>
</html>



 Historique

26 juin 2008 13:58:29 :
Petit oubli corrigé...

 Sources du même auteur

Source avec Zip Source avec une capture EXPLORATEUR WEB
Source avec Zip Source avec une capture PERSONNALISER LES BOÎTES DE DIALOGUE
Source avec Zip Source avec une capture PERSONNALISER SES SELECT

 Sources de la même categorie

Source avec Zip Source avec une capture STOCK/FOREX CANDLE CHART USING CANVAS API par BlackWizzard
MODIFIER SES FEUILLES DE STYLES .CSS À LA VOLÉE AVEC JAVASCR... par Phildepantin
Source avec Zip Source avec une capture FARMVILLE - HEURE ET COMBO LIST IMAGES par ym_trainz
Source avec Zip [-CLASS-] -> CARROUSSEL D'IMAGES par TheWeasel47
Source avec Zip Source avec une capture OGG MEDIA PLAYER par kazma

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture RÉSOUDRE UNE ÉQUATION EN 6 ÉTAPES par Zestyr
Source avec Zip Source avec une capture MENU HORIZONTALE RÉALISÉ AVEC DYNAMIC par Kimjoa
Source avec Zip Source avec une capture DYNAMIC VERSION 0.9 par Kimjoa
Source avec Zip ANIMATION LOGO par opossum_farceur
Source avec Zip Source avec une capture DYNAMIQUE.JS POUR FAIRE DE JOLIE ANIMATION )) par Kimjoa

Commentaires et avis

Commentaire de nickadele le 26/06/2008 20:56:09 administrateur CS 8/10

Très bonne source au niveau du résultat et de l'effet !
Vu que l'objet de cette source c'est de montrer les effets de ROBERT PENNER, un + aurait été des commentaires sur la méthode utilisée.

Nickadele

Commentaire de ralecul le 27/06/2008 00:06:18 9/10

Bravo!

Cette source me donne effectivement envie de faire mon moteur d'animation à la mootools.
C'est une très bonne base pour découvrir les effets de Robert Penner.
Cela permettra également à certain de découvrir les singletons en JS.

La version de mootools n'utilise pas exactement les mêmes équations.
En revanche, j'ai pu constaté que tu as scrupuleusement respecté la version AS de Robert Penner ;-)
Ça aurait été sympa aussi de pouvoir choisir entre les modes easeIn, easeOut et easeInOut.
La version de mootools est beaucoup plus simple pour cela par rapport aux équations fournies par Robert Penner.

Commentaires sur le code :
var step = Math.abs(32 - $('nbPix').value)/nbSteps;  -> tu ne te sers pas de cette variable.
window.setInterval et window.clearInterval -> pourquoi tu spécifies window ? je suppose que tu n'utilises pas window.alert...
corps de animate() -> j'aurais bien vu une version objet à la place (du genre : new Animate("animation", {duration: 800, type: linear}); )

Commentaire de ralecul le 27/06/2008 00:38:31

Désolé, je n'ai pas résisté à "prototyper" ta source :

function animate() {
   new Animation("animation", {
      duration   : $('duration').value,
      transition : $('transition').value,
      amplitude  : $('nbPix').value,
      mode       : $('cssRule').value,
      initSize   : 32
   });
};

function Animation(div, options) {
   var _options    = options             || {};
   var _fps        = _options.fps        || 80;
   var _duration   = _options.duration   || 800;
   var _transition = _options.transition || "linear";
   var _amplitude  = _options.amplitude  || 180;
   var _mode       = _options.mode       || "both";
   var _initSize   = _options.initSize   || 42; //because 42 is the answer ;-)
   var _div        = $(div);

   var _interval   = 1000/_fps;
   var _nbSteps    = Math.round(_duration/_interval);

   var _mapping = [];
   for(var i=1; i<=_nbSteps; ++i)
      _mapping.push(transitions[_transition](i*_interval, _initSize, _amplitude - _initSize, _duration));

   var currentStep = 0;
   var timer = setInterval(iter, _interval);

   function iter() {
      if (_mapping[currentStep]) {
         if (_mode == 'both') {
            _div.style.height = _mapping[currentStep]+'px';
            _div.style.width  = _mapping[currentStep]+'px';
         }
         else {
            _div.style[_mode] = _mapping[currentStep]+'px';
         }
         currentStep++;
      }
      else {
         clearInterval(timer);
         return;
      }
   }
}

PS : c'est fait à la va-vite, ya peut-être quelques erreurs...
PPS : Il suffit de remplacer la fonction animate par celle-ci et d'ajouter la classe Animation.

Commentaire de XtremDuke le 27/06/2008 10:37:58

"tu ne te sers pas de cette variable"

>> Effectivement je ne m'en sers pas. Il s'agit en fait d'un simple copie/colle d'un travaille personnel.

"pourquoi tu spécifies window "

>> Alors ça, aucune idée, c'est une mauvaise (ou bonne ???) habitude.

"Il suffit de remplacer la fonction animate par celle-ci et d'ajouter la classe Animation"

>> tu n'as pas ecris de classe mais deux objets.

Pour parler de ta 'classe', il te faut rajouter une gestion des timers. Sinon, tu vas avoir des surprises si tu utilises cette fonction sur des 'mouseover'.

Remarque : Cette base que j'ai fournis et normalement ecrit sous forme de classe ds un projet perso. Voir :
http://joof-api.net/demo.html

Commentaire de lakichemole le 27/06/2008 13:54:08

Il manque l'include de prototype dans ton exemple :/

Commentaire de lakichemole le 27/06/2008 13:56:32 10/10

à non au temps pour moi, erreur de copier coller :)

Commentaire de ralecul le 27/06/2008 17:34:53

Utilisation de window.setInterval au lieu de interval
>> Alors ça, aucune idée, c'est une mauvaise (ou bonne ???) habitude.
A mon avis c'est facultatif et surtout je trouve que ça n'apporte pas grand chose au niveau de la lisibilité.
En revanche si tu souhaites remplacer la fonction alert par une méthode perso, ça me parait intéressant.
(En gros pour l'appel je ne m'en sers pas, mais pour la redéfinition je m'en sers)

>> tu n'as pas écris de classe mais deux objets.
Pourquoi deux objets ? -> ya une fonction (animate, qui créé un objet) et une définition de classe (Animation).
Animation est bien une classe vu que je l'utilise comme un constructeur.
Le problème de gestion des timers dont tu parles est également présent dans la source que tu présentes ici.
Je n'ai fait que la convertir à la mode Prototype, cependant j'ai ensuite tenté de reproduite ta démo avec cette source.
Le résultat : http://astre.henri.free.fr/creations_sandbox_mootools.php utilise les fichiers :
http://astre.henri.free.fr/js/effect.js
http://astre.henri.free.fr/js/myPrototype.js

Je serais curieux de voir comment tu as fait dans ta démo pour pouvoir comparer avec ma version.
En effet, j'ai été obligé de rajouter un Singleton Fx.Listener qui contient une liste de tous les effets appliqués à un élément.
Ya peut-être une méthode plus élégante ? Je n'ai pas pu comparer avec ta source car minified.js est assez illisible ;-)

Commentaire de XtremDuke le 27/06/2008 20:28:45

"j'ai été obligé de rajouter un Singleton Fx.Listener"

Je ne connais pas ce singleton mais d'après son nom, c'est exactement ça. Faut créer un pseudo gestionnaire d'effets afin de supprimer les effets qui sont déjà en application.

"Animation est bien une classe vu que je l'utilise comme un constructeur."

Effectivement, j'ai lu en diagonale, toutes mes confuses.

"Le problème de gestion des timers dont tu parles est également présent dans la source que tu présentes ici."

Comme dis plus haut, ce n'est qu'une base pour l'utilisation des équations.

Commentaire de Kimjoa le 28/06/2008 12:06:12

salut , je connais bien ses formules , pour les avoir utilisé dans mon propre script d'animation que je sortirais avec ma bibliothèques, qui me prend plus de temps que prévu. J'ai créer une formule d'élasticité en 'tatonant' pour permettre d'y inclure des options de résistance, nombre de va et viens,  et de tension , je suis pas bon en math, et cette formule est sans doute fausse mais l'effet est pas mal , voici la fonction


elasticDown : function(t,s,e,obj){
       return (e-s)*(((1-Math.cos(Math.pow(t,(1/obj.tension)) * Math.PI * obj.bounce)) * (1 - Math.pow(t,1/(t*obj.resistance)))) + Math.pow(t,1/(t*obj.resistance)))+s;
}
concernant les variables
t est le temp (compris entre 0 et 1)
s est la valeur de départ
e est la valeur d'arrivé
obj est l'objet avec les options

si un matheu pouvais me dire se kil en pense .

Pour les curieux http://www.dblog.free.fr/?act=article&art=64

bye



Commentaire de XtremDuke le 28/06/2008 18:23:40

Slt,

Pour l'équation 'élastique', tu as deux paramètres supplémentaires qui servent à gérer l'effet de l'animation.

function (t,b,c,d,a /!\ ,p /!\){

Commentaire de Kimjoa le 28/06/2008 22:12:19

ok , j'ai regardé a koi il correspondait, le a correspond a l étirement maximum, le p a l'élasticité

Cependant ma fonction permet de gérer les  va et viens et la tension meme si les valeur doivent etre precise pour un resultat satisfaisant

J ai modifié la fonction de ROBERT PENNER pour kel prenne en compte le nbr de  va et viens.
J'ai ajouté une fonction classic d'élasticité et de rebond.

voici le code a modifié
pour le select:


     <option value="elasticKimjoa">elasticKimjoa</option>elasticClassic
     <option value="elasticBounce">elasticBounce</option>
     <option value="elasticClassic">elasticClassic</option>

pour l'objet transition

elasticClassic : function(t,b,c,d){
       return c*(((1-Math.cos((t/=d) * Math.PI * 4)) * (1 - t)) + t)+b;
     },
     elasticKimjoa : function(t,b,c,d,te,bo,r){
       // te=tension ,r=resistance, bo=rebont  formule test
       return c*(((1-Math.cos(Math.pow((t/=d),(1/(te || 1.5))) * Math.PI * (bo || 4))) * (1 - Math.pow(t,1/(t*(r || 10))))) + Math.pow(t,1/(t*(r || 10))))+b;
     },
     elastic: function (t,b,c,d,a,p){
     t/=d;
     if (!a)a=c*3;
     //p=nbr de va et viens a etirement max reste tension
     p=(p)?(p>1)?(c*10)/((p-1)/(d/1000)):(c*10)/(1/(d/1000)):(c*10)/(3/(d/1000));
     if (a < Math.abs(c))  
      var s=p/4;
     else
      var s = p/(2*Math.PI) * Math.asin (c/a);
     return (a*Math.pow(2,-10*(t)) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b);
     },
     elasticBounce: function (t,b,c,d,a,p){//p=bounce
       var value=transitions.elastic(t,b,c,d,a,p);
   if(Math.abs((value-b))>Math.abs(c))
  return b+c-(value-c-b);  
   else return value;
     }

je sais pas encore kel fonction je vais mettre dans ma librairie , j'aimerait bien pouvoir géré la tension

voila, a+

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

différents effets sur les liens d'une meme page [ par geoffroy ] Salut, J'aimerais savoir comment fait on pour qu'un lien devienne plus gros au survolage de la souris . Mais j'aimerais que cet effet ne marche que su chargement dans cadre différent à la fin d'une animation [ par zygene ] bonjour,je souahite charger un menu dans un cadre de gauche, une fois que l'animation flash du cadre principal est terminée...euh, comment faire? (sac du flash dans un fichier .JS [ par bernard09 ] Salut.Je cherche à inserer les lignes d'appel d'une animation flash dans un fichier .JS pour pouvoir ensuite lancer l'animation sur plusieurs page et animation flash [ par nico606 ] Slt g un problème g une animation flash sur mon mon site mais je n'ai pas le logiciel flash.Alors si vous l'avez je vous envoie mon fichier en fete je pbm avec window.open [ par matoo ] bonjour,j'ai une animation flash contenant des boutons, appelant des popup.swf à l'aide d'un : getURL("javascript:popup('anim1.swf','popup',',left equation du second degre [ par ouaton ] SALUT!j'aimerais resoudre une equation du second degré du type Ax²+Bx+C=0 en java ou html.on entre A,B et C et afficher dans Sje n'arrive pas a le fai lien html / flash ? [ par pistoff ] Voila mon problème:j'ai une animation flash qui commence dans une premiere page html... et j'aimerais qu'en passant sur une deuxieme page html la meme Passer des variables dans <param> ? [ par WhiteMagus ] Salut.Je fais un site en Flash, mais j'aimerai que l'animation se repoitionne avec une animation au centre de la page si celle-ci est redimensionnée. Class Defilement auto d'images avec animation [ par MeTh ] Je suis sur d'etre pret du but et je suis &#233;galement convaincu que ce script peut servir &#224; bcp de personne. Ceci ma premi&#232;re tentative lien 2 effets [ par chaps29 ] bonjour, je souhaiterais faire un lien avec une double action qui necessiterait du javascript je m'explique c'est pour modifier un element dans une b


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mars 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,981 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales