Forums Développement Multimédia

Aller au contenu

- - - - -

controler une animation css via js

javascript css

9 réponses à ce sujet

#1 paodao

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 7073 messages

Posté 18 October 2018 - 14:48 PM

bonjour

je cherche a controller une animation css (keyframe) via js (un peu comme un lecteur video)

j'y arrive très bien en utilisant des animation-delay negatif pointant sur la frame que je souhaite

le problème est que cela ne fonctionne pas sur ios

je cheche donc soit une solution pour que cela fonctionne sur ios soit un autre moyen de pouvoir aller ou je veux dans l'animation

merci

#2 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7001 messages

Posté 18 October 2018 - 17:11 PM

Hello,

Tu veux pouvoir aller à la frame que tu veux dans l'anim quelle que soit l'état de l'anim (c'est à dire même entre deux frames) ou à une frame prédéfinie (50%, 75%, ...) ?

Pour l'instant la solution que je vois là tout de suite en te lisant serait de créer l'anim complète, puis la même découpée en petites anims indépendantes, et simplement changer la classe de ton élément via JS pour pointer vers la sous anim concernée et enchaîner (par exemple via un tableau en JS).

Je vais regarder ce qui plante sur IOS car je ne vois pas trop pourquoi ça bloquerai.

Je suppose que tu as déjà regardé ici : https://developer.ap...hKeyframes.html
section "controling with javascript".

#3 paodao

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 7073 messages

Posté 19 October 2018 - 09:43 AM

salut Monsieur Spi et merci de ta réponse

la solution de découper en plein de sous classe, j'ay ai pensé, mais je trouve cela trop lourd, surtout que je n'ai le probleme que sur ios

l'idée est de pouvoir controller la frame ou se trouve une animation keyframe via javascript.

Cela fonctionne tres bien en utilisant un animation-delay negatif (c'est dans la doc w3c)

ex:
sur un element je met le style suivant

  animation-name: plop;
  animation-duration: 1s;
  animation-play-state: paused;
  animation-fill-mode: forwards;
 

le animation-duration: 1s est important.
ensuite, en faisant varié le animation-delay en js (au scroll, dans un interval...) de 0s à -1s (oui en negatif) je peux placer la tete de lecture ou je veux

le souci est que ios kif pas trop. des que je change le animation-delay il met la tete de lecture sur la premiere image

par exemple, pour que cela fonctionne sur IE apres avoir changé le animation-delay je passe le display du body de block->none->block, sinon le truc n'est pas pris en compte

je pense qu'il doit y avoir une autre astuce du genre sur ios pour le forcer a prendre en compte le animation-delay

merci
a+

#4 paodao

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 7073 messages

Posté 19 October 2018 - 15:58 PM

salut
bon j'avance un peu
il faudrait que je trouve un moyen de forcer le redraw de la page, un peu comme je le fait deja avec IE (body: display none->block) (sauf que ce qui fonctionne sur IE ne fonctionne pas sur IOS)

#5 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7001 messages

Posté 19 October 2018 - 18:08 PM

Hello,

Je cherche encore mais j'ai pas mal de boulot donc je ne peux m'y coller que le soir.
Question : pourquoi ne pas faire toute l'anim en JS ?

Je sais que CSS3 est full hardware si tu active la 3D (voir ref sur developper.mozilla.org), mais si ça te bloque complètement pourquoi ne pas directement faire ton anim avec un Canvas (fond transparent et layer CSS) ou avec jQuery pour cibler le DOM ?
Après je ne connais pas la structure de ta page et si tu dois impérativement passer en CSS, mais ça serait sans doute une solution efficace.

En gros, ça peut m'aider à te trouver une solution détournée, elle doit faire quoi ton anim et être structurée comment (DOM ou indépendant genre SVG, Canvas, Video, ....) ?

#6 paodao

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 7073 messages

Posté 20 October 2018 - 16:26 PM

salut
l'idée est de pouvoir créer siplement une animation et la controller

avec le systeme que j'ai deja (qui fonctionne partout sauf sur ios) je fait une animation en keyframes
du coup l'animation est extrement simple a faire puisqu'il suffit de rajouter des etapes dans la keyframe avec les proprietes que l'on veux

Pour le faire en js il faudrait faire autant de dataset que de keyframe, puis regarder entre 2 keyframes quelles proprietes on touche pour aller calculer la bonne valeur entre les 2 puis les appliqué en JS (cela veux dire faire des parse sur les valeurs pour voir dans quelle unité on est et faire le bon calcul), c'est faisable, c'est juste ultra lourd, là ou c'est ultra simple en css

Cela ne me bloque pas, ce n'est pas pour un projet en particulier c'est vraiment pour avoir un truc perrein. Pour le moment sur le projet sur lequel je voulais l'utiliser je fait le calcul en js, mais le calcul reste exclusif a ce projet (pas une lib)

je commence a plus ou moins reussir a le faire marcher sur ios en jouant sur une alternance rapide de display none/block sur le body, par exemple cela focntionne bien sur ie, par contre cela a des effets de bord sur ios (clignotement, scroll non voulu...)

donc l'idée est de trouvé un moyen de declencher le reflow/repaint (l'un, l'autre, les 2... je sais pas) avec des effets de bord acceptable

Je n'utiliserai pas jQuery pour le faire, ceci dit si une techique existe avec, je veux bien la connaitre, je regarderai derriere comment il fonctionne

Voir le messageMonsieur Spi, le 19 October 2018 - 18:08 PM, dit :

En gros, ça peut m'aider à te trouver une solution détournée
c'est gentil mais pas la peine :-) , je sais trouver les moyens détournés. Mais quand je vois la puissance et la simplicité du truc (par rapport a du full js) je ne veux pas l'abandonner comme ca uniquement parce que ios ne rafraîchit pas le truc


merci
a+

#7 paodao

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 7073 messages

Posté 21 October 2018 - 10:41 AM

salut
je post un exemple simplifié de ce que je test (l'animation se joue au scroll sur la page)
la ligne qui compte c'est la ligne 66

                div1.style['animation-delay'] = -p + 's';
 
le problème est donc que cet animation-delay n'est pas pris en compte sur ios quand modifié via js

le fait de pouvoir jouer sur animation-delay permet de faire simplement des animations css complexe
s'il fallait le faire en full js il faudrait ajouter plein de dataset, et plein de calcul lourd en js pour les analyser et appliqué les bon styles au bon moment


<!doctype html>
<html lang="fr">
<head>
        <meta charset="utf-8">
        <title>Titre de la page</title>
        <style type="text/css">
        html,
        body {
                margin: 0;
                padding: 0;
        }
        .div1 {
                position: fixed;
                top: 0;
                left: 0;
                width: 100px;
                height: 100px;
                background-color: #ff0000;
                border: 1px solid #000000;
                box-sizing: border-box;
                animation: div1 1s paused forwards;
        }

        @keyframes div1 {
                0% {
                        left: 0%;
                        top: 0;
                }
                30% {
                        top: 10%;
                        transform: rotate(0deg);
                }
                50% {
                        top: 0%;
                }
                70% {
                        top: 10%;
                        transform: rotate(360deg);
                }
                100% {
                        transform: rotate(360deg);
                        top: 0;
                        left: calc(100% - 100px);
                }
        }
        .container1 {
                height: 300vh;
                border: 1px solid #000000;
                box-sizing: border-box;
        }
        </style>
        <script>
        window.addEventListener('load', init);
        var elt;
        var div1;
        function init() {
                elt = document.getElementById('container1');
                div1 = document.getElementById('div1');
                window.addEventListener('scroll', onScroll);
                onScroll();
        }
        function onScroll(e) {
                var p = window.pageYOffset / (elt.scrollHeight - window.innerHeight);
                if (p < 0) p = 0;
                if (p > 1) p = 1;
                div1.style['animation-delay'] = -p + 's';
        }
        </script>
</head>
<body>
        <div class="div1" id="div1">coucou</div>
        <div class="container1" id="container1"></div>
</body>
</html>
 

a+

Fichier(s) joint(s)

  • Fichier joint  index.html   1.63 Ko   3 téléchargement(s)


#8 paodao

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 7073 messages

Posté 22 October 2018 - 12:54 PM

salut
j'ai fini par trouver
le turc c'est d'enlever la classe qui joue l'animation, faire appel a une variable qui force le repaint et lui redonner la classe

<!doctype html>
<html lang="fr">

<head>
    <meta charset="utf-8">
    <title>Titre de la page</title>
    <style type="text/css">
    html,
    body {
        margin: 0;
        padding: 0;
    }

    .div1 {
        position: fixed;
        top: 0;
        left: 0;
        width: 100px;
        height: 100px;
        background-color: #ff0000;
        border: 1px solid #000000;
        box-sizing: border-box;
        animation-name: div1;
        animation-duration: 1s;
        animation-fill-mode: forwards;
        animation-delay: -0.5s;
        animation-play-state: paused        
    }


    .anim2{
        animation-name: div1;
        animation-duration: 1s;
        animation-fill-mode: forwards;
        animation-delay: -0.5s;
        animation-play-state: paused        
    }

    @keyframes div1 {
        0% {
            left: 0%;
            top: 0;
        }

        30% {
            top: 10%;
            transform: rotate(0deg);
        }

        50% {
            top: 0%;
        }

        70% {
            top: 10%;
            transform: rotate(360deg);
        }

        100% {
            transform: rotate(360deg);
            top: 0;
            left: 100%;
        }
    }

    .container1 {
        height: 300vh;
        border: 1px solid #000000;
        box-sizing: border-box;
    }
    </style>
    <script>
    window.addEventListener('load', init);
    var elt;
    var div1;

    function init() {
        elt = document.getElementById('container1');
        div1 = document.getElementById('div1');
        window.addEventListener('scroll', onScroll);
        onScroll();
    }


    function onScroll(e) {
        var p = window.pageYOffset / (elt.scrollHeight - window.innerHeight);
        if (p < 0) p = 0;
        if (p > 1) p = 1;
        div1.style['animation-delay'] = -p + 's';
        var classes = div1.className;
        div1.className = ''
        div1.offsetWidth;
        div1.className = classes;
    }
    </script>
</head>

<body>
    <div class="div1 anim" id="div1">coucou</div>
    <div class="container1" id="container1">
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
        coucou<br>
    </div>
</body>

</html>
 

merci
a+

#9 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7001 messages

Posté 22 October 2018 - 17:11 PM

Hello,

Merci du retour, très intéressant, j'ai la tête pleine pour aujourd'hui mais je vais me pencher là dessus, ça à l'air sympa et comme c'est pour "jouer", on va pouvoir faire plein de tests :D

#10 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7001 messages

Posté 23 October 2018 - 00:04 AM

Re,

J'ai jeté un œil, plutôt malin de jouer sur le delay négatif.

A ajouter dans le CSS :
animation-timing-function: linear;

Je me suis demandé un moment pourquoi ton calcul ne renvoyait pas une animation linéaire.
Image attachée: anim.jpg

Je me suis bêtement attaché au calcul du pourcentage (pourtant bon) alors que ça venait du comportement par défaut de l'anim CSS.




Répondre à ce sujet



  

1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)

authorised training centre

Centre de Formation Mediabox - Adobe et Apple Authorised Training Center.

Déclaré auprès de la Direction du Travail et de la Formation Professionnelle

Mediabox : SARL au capital de 62.000€ - Numéro d'activité : 11 75 44555 75 - SIRET : 49371646800035

MEDIABOX, 23, rue de Bruxelles, 75009 PARIS

FFP