Afspeelbediening voor webanimaties in Chrome 39

Eerder dit jaar introduceerde Chrome 36 de element.animate-methode als onderdeel van de bredere Web Animations-specificatie . Dit maakt efficiënte, native animaties mogelijk die direct geschreven zijn, waardoor ontwikkelaars de keuze hebben om hun animaties en overgangen te bouwen met de voor hen meest geschikte aanpak.

Ter herinnering: hier is hoe je een wolk over het scherm kunt animeren, met een callback wanneer je klaar bent:

var player = cloud.animate([
    {transform: 'translateX(' + start + 'px)'},
    {transform: 'translateX(' + end + 'px)'}
], 5000);
player.onfinish = function() {
    console.info('Cloud moved across the screen!');
    startRaining(cloud);
};

Dit alleen al is ongelooflijk eenvoudig en zeker de moeite waard om te overwegen als onderdeel van je toolbox wanneer je animaties of overgangen bouwt. In Chrome 39 zijn er echter afspeelbedieningsfuncties toegevoegd aan het AnimationPlayer object dat wordt geretourneerd door element.animate . Voorheen kon je, nadat een animatie was gemaakt, alleen cancel() aanroepen of naar de finish-gebeurtenis luisteren.

Deze toevoegingen aan het afspelen vergroten de mogelijkheden van webanimaties: ze worden een algemeen hulpmiddel, in plaats van dat ze voorschrijven wat betreft overgangen (dat wil zeggen, 'vaste' of vooraf gedefinieerde animaties).

Pauzeren, terugspoelen of afspeelsnelheid wijzigen

Laten we beginnen met het bijwerken van het bovenstaande voorbeeld om de animatie te pauzeren als er op de wolk wordt geklikt:

cloud.addEventListener('mousedown', function() {
    player.pause();
});

U kunt ook de eigenschap playbackRate wijzigen:

function changeWindSpeed() {
    player.playbackRate *= (Math.random() * 2.0);
}

Je kunt ook de reverse() methode aanroepen, wat normaal gesproken gelijk staat aan het inverteren van de huidige playbackRate (vermenigvuldigen met -1). Er zijn echter een paar speciale gevallen:

  • Als de verandering die door de reverse() methode wordt veroorzaakt, ertoe zou leiden dat de lopende animatie effectief wordt beëindigd, wordt de currentTime ook omgekeerd. Als bijvoorbeeld een geheel nieuwe animatie wordt omgekeerd, wordt de hele animatie achterwaarts afgespeeld.

  • Als de speler wordt gepauzeerd, wordt de animatie afgespeeld.

De speler schrobben

Een AnimationPlayer staat nu toe dat de currentTime wordt aangepast terwijl een animatie wordt afgespeeld. Normaal gesproken neemt deze waarde in de loop van de tijd toe (of af, als de playbackRate negatief is). Dit kan de positie van een animatie extern regelen, bijvoorbeeld via gebruikersinteractie. Dit wordt vaak scrubben genoemd.

Als uw HTML-pagina bijvoorbeeld de lucht voorstelt en u wilt met een sleepbeweging de positie van een op dat moment afgespeelde wolk wijzigen, kunt u een aantal handlers aan het document toevoegen:

var startEvent, startEventTime;
document.addEventListener('touchstart', function(event) {
    startEvent = event;
    startEventTime = players.currentTime;
    player.pause();
});
document.addEventListener('touchmove', function(event) {
    if (!startEvent) return;
    var delta = startEvent.touches[0].screenX -
        event.changedTouches[0].screenX;
    player.currentTime = startEventTime + delta;
});

Terwijl u over het document sleept, wordt de currentTime aangepast aan de afstand tot uw oorspronkelijke gebeurtenis. U kunt de animatie ook hervatten wanneer het gebaar eindigt:

document.addEventListener('touchend', function(event) {
    startEvent = null;
    player.play();
});

Dit zou zelfs gecombineerd kunnen worden met omkeergedrag, afhankelijk van waar de muis van de pagina wordt gehaald ( gecombineerde demo ).

In plaats van een AnimationPlayer te scrubben als reactie op een gebruikersinteractie, kan de currentTime ook worden gebruikt om de voortgang of status weer te geven: bijvoorbeeld om de status van een download weer te geven.

Het nut hiervan is dat een AnimationPlayer een waarde kan instellen en de onderliggende native implementatie de voortgangsvisualisatie laat verzorgen. In het geval van een download kan de duur van een animatie worden ingesteld op de totale downloadgrootte en de currentTime op de momenteel gedownloade grootte ( demo ).

UI-overgangen en gebaren

Mobiele platforms zijn al lang het domein van veelgebruikte gebaren: slepen, schuiven, gooien en dergelijke. Deze gebaren hebben vaak een gemeenschappelijk thema: een versleepbaar UI-onderdeel, zoals de "trek om te vernieuwen"-functie van een lijstweergave of een zijbalk die aan de linkerkant van het scherm wordt weergegeven.

Met webanimaties is een vergelijkbaar effect heel gemakkelijk te repliceren op het web - op desktop of mobiel. Bijvoorbeeld, wanneer een gebaar dat currentTime bestuurt het volgende voltooit:

var steps = [ /* animation steps */ ];
var duration = 1000;
var player = target.animate(steps, duration);
player.pause();
configureStartMoveListeners(player);

var setpoints = [0, 500, 1000];
document.addEventListener('touchend', function(event) {
    var srcTime = player.currentTime;
    var dstTime = findNearest(setpoints, srcTime);
    var driftDuration = dstTime - srcTime;

    if (!driftDuration) {
    runCallback(dstTime);
    return;
    }

    var driftPlayer = target.animate(steps, {
    duration: duration,
    iterationStart: Math.min(srcTime, dstTime) / duration,
    iterations: Math.abs(driftDuration) / duration,
    playbackRate: Math.sign(driftDuration)
    });
    driftPlayer.onfinish = function() { runCallback(dstTime); };
    player.currentTime = dstTime;
});

Dit creëert een extra animatie die een 'drift' uitvoert. Deze speelt zich af tussen de plek waar het gebaar werd uitgevoerd en het doel dat we kennen.

Dit werkt omdat animaties een prioriteit hebben op basis van de volgorde waarin ze zijn gemaakt: in dit geval krijgt driftPlayer voorrang op de speler. Zodra driftPlayer klaar is, verdwijnen de animatie en de bijbehorende effecten. De uiteindelijke tijd komt echter overeen met de huidige tijd van de onderliggende speler, zodat je gebruikersinterface consistent blijft.

Tot slot, als je van kittens houdt, is er een demo-webapplicatie die deze gebaren demonstreert. Deze is geschikt voor mobiele apparaten en maakt gebruik van polyfill voor achterwaartse compatibiliteit, dus probeer hem eens op je mobiele apparaat!

Ga heen en element.animeer

De element.animate -methode is momenteel echt geweldig, of je hem nu gebruikt voor simpele animaties of de geretourneerde AnimationPlayer op andere manieren wilt benutten.

Deze twee functies worden ook volledig ondersteund in andere moderne browsers via een lichtgewicht polyfill . Deze polyfill voert ook functiedetectie uit, dus naarmate browserleveranciers de specificatie implementeren, zal deze functie in de loop van de tijd alleen maar sneller en beter worden.

De Web Animations-specificatie zal ook blijven evolueren. Als je geïnteresseerd bent in het uitproberen van aankomende functies, zijn deze nu ook beschikbaar in een meer gedetailleerde polyfill: web-animations-next .