Animator.js: bibliothèque d’animation JavaScript


Original: http://berniesumption.com/software/animator/

Animator.js était une bibliothèque que j’ai écrit en 2006 pour gérer l’animation sur les pages Web. Pour un temps, il était tout à fait en avance sur la courbe: C’était la première bibliothèque de vedette CSS morphing – la capacité de faire la transition en douceur entre deux styles définis comme des classes CSS.

Le monde du JavaScript a évolué beaucoup depuis. Animator.js a été intégré dans la plupart des grands frameworks JavaScript, soit par portage directement le code (Animator.js est publié sous une licence BSD qui permet aux gens de le faire) ou en empruntant les techniques. Animator.js a atteint son but, et la plupart des gens seront mieux servis par un framework JavaScript à usage général: Je recommande jQuery.

Je garde cette page vous ici pour un intérêt historique, et parce Animator.js peut encore être d’intérêt pour les gens qui veulent une petite bibliothèque rapide qui fait l’animation et rien d’autre.

Merci à Tim Stone, Kaspar Fischer, Clint Priest et d’autres développeurs qui ont contribué informations et caractéristiques.

Contexte et motivation

J’ai enlevé cette section car il contenait des critiques d’autres bibliothèques JavaScript qui était vrai en 2006, mais pas aujourd’hui. J’ai aussi l’occasion de disserter sur le sujet de l’héritage orienté objet, qui était un sujet j’ai exploré plus en détail dans l’article héritage est mauvais et doit être détruit – Bernie Sumption 2010
Une meilleure façon d’animer

Un animateur est un objet qui génère une série de nombres compris entre zéro et un. Zéro représente le début de l’animation, une fin.

Check this out:

// This object controls the progress of the animation
ex1 = new Animator()
// the Animator's subjects define its behaviour
ex1.addSubject(updateButton);
function updateButton(value) {
    var button = document.getElementById("ex1Button");
    button.innerHTML = "Progress: " + Math.round(value * 100) + "%";
}
// now click below: each click to the button calls ex1.toggle()

Maintenant cliquez ci-dessous: chaque cliquez sur les appels de bouton ex1.toggle ()

L’animateur ci-dessus a été laissé avec les options par défaut, voici un exemple qui utilise plus de configuration:

ex2 = new Animator({
    duration: 1200,
    interval: 400,
    onComplete: function() {
        document.getElementById("ex2Target").innerHTML += "Bing! ";
    }
})
ex2.addSubject(updateButton);
function updateButton(value) {
    document.getElementById("ex2Target").innerHTML += " Badda ";
}

Animation styles des éléments

La plupart du temps vous souhaitez animer un ou plusieurs de propriétés de style d’un élément. Il existe essentiellement trois types de valeur CSS – ceux qui s’adaptent numérique (comme 10px), ceux qui s’adaptent avec une valeur de couleur RVB (comme # RRGGBB), et ceux qui ne s’adaptent pas (comme gras / italique). Animator propose trois classes d’utilitaires pour chacun de ces types de propriétés, et entre eux ils peuvent animer tout style CSS.

// animate margin-left from 0 to 100 px
ex3 = new Animator().addSubject(
    new NumericalStyleSubject(
        "ex3Button",
        "margin-left",
        0,
        100));

Animator.js: bibliothèque d’animation JavaScript

// animate background-color from white to black
ex4 = new Animator().addSubject(
    new ColorStyleSubject(
        "ex4Button",
        "background-color",
        "#FFFFFF",
        "#F4C"));

// animate background-color from white to black
ex4 = new Animator().addSubject(
    new ColorStyleSubject(
        "ex4Button",
        "background-color",
        "#FFFFFF",
        "#F4C"));

// animating both - note how calls to addSubject() can be chained:
ex5 = new Animator()
    .addSubject(
        new NumericalStyleSubject(
            "ex5Button",
            "margin-left",
            0,
            100))
    .addSubject(
        new ColorStyleSubject(
            "ex5Button",
            "background-color",
            "#FFFFFF",
            "#F4C"))
    .addSubject(
        new DiscreteStyleSubject(
            "ex5Button", "font-weight",
            "normal",
            "bold",
            0.5));
// also, check out the last subject, which causes font-weight to
//switch from normal to bold half way through the animation

Si vous avez déjà utilisé moofx ou scriptaculous alors vous pensez probablement que c’est très verbeux, et vous auriez raison. Animator a une killer feature qui supprime la verbosité, mais avant d’en arriver là, voici quelques autres choses que vous pouvez faire:

Des effets plus complexes

Que faire si vous avez un certain nombre d’éléments que vous souhaitez animer de la même manière? Dans ce cas, passez un tableau d’éléments dans le constructeur de la réserve. Il n’y a pas moyen d’ajouter et supprimer des éléments d’une réserve après qu’il a été construit – si vous voulez faire cela, utiliser une réserve pour chaque élément et utiliser ADDSUBJECT () et removeSubject () sur l’animateur.

// Applying the same effect to different elements is easy
ex6 = new Animator().addSubject(
    new NumericalStyleSubject(
        ["dot1", "dot2", "dot3"],
        "margin-right",
        10,
        50));

Dans les exemples précédents, chaque sujet a fait référence à un même élément. Cela ne doit pas être le cas:

// applying different effects to different elements is possible
ex7 = new Animator()
    .addSubject(
        new ColorStyleSubject(
            "ex5ButtonA",
            "background-color",
            "#FF9",
            "#9F9"))
    .addSubject(
        new NumericalStyleSubject(
            "ex5ButtonB",
            "padding",
            "5px",
            "15px"));

Opacité reçoit un traitement spécial. Depuis IE ne supporte pas le style standard “opacité” de CSS, NumericalStyleSubject le convertit en un filtre approprié.

ex8 = new Animator().addSubject(
    new NumericalStyleSubject(
        "ex8Button",
        "opacity",
        1,
        0.25));

Contrôle de l’animation

Lorsque vous cliquez sur un bouton de l’échantillon dans cet article, vous appelez toggle () sur un objet d’animation. Il ya un peu plus de fonctions de contrôle:

  • play () joue l’animation du début à la fin
  • stop () arrête l’animation à sa position actuelle
  • reverse () joue l’animation en sens inverse
  • seekTo (pos) joue l’animation à partir de son poste actuel
  • seekFromTo (de, à)

play ()                 0%
Arrêtez ()
reverse ()
seekTo (0,5)
seekFromTo (0,25, 0,75)

L’avantage d’utiliser seekTo () est qu’il wil éviter des changements brusques dans l’état lorsqu’il est appelé à mi-chemin à travers une animation:
ce div utilise play () et inverser passage de la souris et mouseout
ce div utilise seekTo (1) et seekTo (0) passage de la souris et mouseout

transitions

Une transition est une fonction qui prend un état (un nombre compris entre 0 et 1) et renvoie un autre nombre compris entre 0 et 1. Ceci peut être utilisé pour simuler l’accélération, la décélération et des effets plus complexes. Vous pouvez passer à une transition au constructeur d’un objet Animator utilisant la propriété de transition habilement nommé.
L’objet Animator.tx fournit quelques transitions prêtes à l’emploi:

  • Animator.tx.easeInOut est la transition par défaut, et crée un effet lisse
  • Animator.tx.linear maintient un taux constant de l’animation
  • Animator.tx.easeIn commence doucement, devient plus rapide
  • Animator.tx.strongEaseIn version de ce qui précède exagérée
  • Animator.tx.easeOut commence rapidement, devient plus lent
  • Animator.tx.strongEaseOut version exagérée de ce qui précède
  • Animator.tx.elastic aller un peu au-delà du point de cible, puis être tiré en arrière
  • Animator.tx.veryElastic comme ci-dessus, mais avec un autre passage
  • Animator.tx.bouncy Frappez le point cible, puis rebondir
  • Animator.tx.veryBouncy comme ci-dessus, mais avec un supplément de 2 rebonds

Parfois, vous voulez peaufiner les transitions ci-dessus. Si vous regardez le code source où l’objet Animator.tx est créé, vous verrez que les fonctions ci-dessus sont tous fabriqués par quatre fonctions de l’usine:

Animator.makeEaseIn ()


// make a transition that gradually accelerates. pass in 1 for smooth
// gravitational acceleration, higher values for an exaggerated effect
ex9 = new Animator({
    transition: Animator.makeEaseIn(3),
    duration: 1000
});
ex9.addSubject(
    new NumericalStyleSubject(
        "ex9Button",
        "margin-left",
        0,
        200));

Animator.makeElastic ()

// make a transition that, like an object with momentum being
// attracted to a target point, goes past the target then returns
ex10 = new Animator({
    transition: Animator.makeElastic(3),
    duration: 2000
});
ex10.addSubject(
    new NumericalStyleSubject(
        "ex10Button",
        "margin-left",
        0,
        200));

Animator.makeBounce ()

// make a transition that, like a ball falling to floor, reaches
// the target and bounces back again
ex11 = new Animator({
    transition: Animator.makeBounce(3),
    duration: 2000
});
ex11.addSubject(
    new NumericalStyleSubject(
        "ex11Button",
        "margin-left",
        0,
        200));

Animator.makeADSR ()

Une attaque Decay Sustain enveloppe de sortie est une technique que j’ai été élevé de la production de musique. Il est très utile pour les animations qui commencent et se terminent à la même valeur.

// This example shows you what an ADSR envelope looks like, but is
// otherwise useless the first three arguments are the boundary
// points of the 4 phases. The last is the sustain level.
// All should be between 0 and 1.
ex12 = new Animator({
    transition: Animator.makeADSR(0.25, 0.5, 0.75, 0.5),
    duration: 2000
});
ex12.addSubject(
    new NumericalStyleSubject(
        "ex12Button",
        'margin-left',
        0,
        400));

Une utilisation pratique de l’ADSR est de maintenir une animation dans un certain état pendant un certain temps, comme dans cet exemple de fondu jaune

// This yellow fade is emphasised by holding it at full yellow
// for the first half of the animation
ex13= new Animator({
    transition: Animator.makeADSR(0, 0, 0.5, 1),
    duration: 1500
});
ex13.addSubject(
    new ColorStyleSubject(
        "ex13Button",
        "background-color",
        "#FFFFFF",
        "#FFFF00"));

Les fonctions personnalisées

Bien sûr, vous pouvez écrire vos propres fonctions qui font toute sorte de transition:

function setupEx14() {
    var wobbles = parseInt(prompt(
        "Enter a number of wobbles (try between 1 and 5)", ""));
    if (!wobbles) {
        alert("Sorry, I didn't understand that, have 2 wobbles.");
        wobbles = 2;
    }
    // do some kind of crazy trigonometric stuff. I don't even
    // know what it all means, I just went crazy with the Math
    // functions
    ex14Tx = function(pos) {
        return ((-Math.cos(pos*Math.PI*((1+(2*wobbles))*pos))/2) + 0.5);
    }
    ex14 = new Animator({
        transition: ex14Tx,
        duration: 2000
    });
    ex14.addSubject(
        new NumericalStyleSubject(
            "ex14Button",
            "margin-left",
            0,
            100));
    ex14.play();
};

La fonction de tueur

Je voulais expliquer comment fonctionne Animator sous le capot avant, j’ai révélé cette fonctionnalité.

Comme je disais avant, c’est tout un peu verbeux pour le moment, et la plupart du code dans les exemples ci-dessus est juste passe-partout. Nous avons besoin d’une sorte de langage qui nous permet de définir le style que nous voulons animer un objet vers. Oh, attends une seconde, nous avons déjà un: CSS. Un style CSS contient toutes les informations nécessaires pour définir un état d’animation:

ex15 = new Animator().addSubject(
    new CSSStyleSubject(
        "ex15Button",
        "width: 10em; background-color: rgb(256, 256, 256); font-style: normal",
        "width: 40em; background-color: #F39; font-style: italic"));
// note how you can use any unit, not just 'px'.

CSSStyleSubject est un wrapper autour des trois autres sujets. Il analyse deux ensembles de règles CSS et pour chaque déclaration de propriété, crée un NumericalStyleSubject si elle ressemble à un certain nombre, ou un ColorStyleSubject si elle ressemble à une couleur, ou un DiscreteStyleSubject autrement. DiscreteStyleSubjects sont créés avec un seuil de 0,5, en d’autres termes les changements de style de la normale en italique à la moitié de l’animation.

Idéalement, vous pouvez également passer dans les noms de classe CSS à la place de jeux de règles:

ex16 = new Animator().addSubject(new CSSStyleSubject(
    "ex16Button",
    "small white",
    "big blue bendy"));
// the classes small, big, white, blue and bendy are
// defined in this page's source.

Lorsque vous créez des animations de classes CSS, il est facile de perdre la trace de ce que votre objet animateur fait. La méthode Animator.inspect () renvoie une chaîne qui décrit l’animateur:

C’est très bien, mais nous pouvons encore retirer un peu plus de cochonneries. La plupart du temps, l’élément que vous souhaitez animer seront déjà dans son style initial. Si c’est le cas, vous pouvez omettre l’un des ensembles de règles et l’état initial ne pourra être déduite du style actuel éléments. Il utilise getComputedStyle (ou Element.currentStyle dans IE) afin reflète le style réel de l’élément après l’application des règles CSS dans les feuilles de style.

ex17 = new Animator().addSubject(
    new CSSStyleSubject(
        "ex17Button",
        "width: 300px; background-color: #F39"));

Enfin, il ya une dernière peu de sucre syntaxique pour le rendre facile d’appliquer des effets. La fonction Animator.apply (élément, modèle, options) est un wrapper autour de la création d’un seul CSSStyleSubject. Le deuxième argument est le style à s’estomper à la troisième est un ensemble facultatif de paramètres du constructeur de l’objet Animator. Si vous souhaitez spécifier le plein de et de styles, passer dans un tableau à deux de l’article comme second paramètre.

ex18 = Animator.apply("ex18Button", "greenish"); // ta da!

Oh allez, une caractéristique plus …

À la demande générale … Plusieurs personnes ont demandé un moyen facile de chaîne plusieurs animations ensemble. AnimatorChain est un objet qui se comporte un peu comme un animateur, mais s’enroule plusieurs autres objets d’animateur et les amène à jouer dans l’ordre.

var animators = [];
for (var i=0; i<3; i++) {
    animators[i] = Animator.apply("ex18blob-" + i), "blobEnd";
}
ex19 = new AnimatorChain(animators);
// the AnimatorChain object has toggle(), play(), reverse()
// and seekTo(state) functions just like Animator objects,
// so you can often use them where code expects an Animator

Comments are closed.