L'effet d'une page réaliste tournant sur JS

Je présente à votre attention - l'une des options possibles pour mettre en œuvre une astuce plutôt drôle pour créer l'effet d'un tournage de page réaliste. Démonstration



et documentation de
Github

J'ai longtemps mis en place un effet similaire, de retour à l'université et à Delphi. Cela s'est avéré digne, même si j'ai passé beaucoup de temps à l'époque. Maintenant - pendant la période d'auto-isolement, il est devenu intéressant d'implémenter quelque chose de similaire sur JS, pour PC et appareils mobiles.

Franchement, je ne suis pas sûr de l'applicabilité pratique de cet effet, et je pense que dans la plupart des cas - il n'y a rien de mieux qu'un simple changement d'images sans aucune animation. Mais il est tout à fait possible d'utiliser, disons sur les sites de restaurants, pour publier un menu (mais surtout - qui serait dupliqué par un lien ensuite!)

Tout est écrit en Typescript. Aucune bibliothèque tierce n'a été utilisée. Il n'y a pas de dépendances.

Fonctionnalités clés de la bibliothèque


  • Fonctionne à la fois avec des images simples, avec un rendu sur canevas et avec des blocs html - à l'aide de transformations CSS
  • Système de configuration assez flexible et API simple
  • Prend en charge les appareils mobiles
  • Changement d'orientation automatique entre le mode portrait et le mode paysage

Le code a été écrit avec un œil uniquement sur ES6 +, et le système modulaire est également ES6. La prise en charge du navigateur est en moyenne à 90% basée sur caniuse.com.

Installation


L'installation est possible à partir de npm:

npm install page-flip

Vous pouvez également télécharger les fichiers collectés à partir du référentiel.

L'option d'initialisation de la bibliothèque de base peut ressembler à ceci:

<div id="book">
    <div class="my-page">
        Page one
    </div>
    <div class="my-page">
        Page two
    </div>
    <div class="my-page">
        Page three
    </div>
    <div class="my-page">
        Page four
    </div>
</div>

import {PageFlip} from 'page-flip';
const pageFlip = new PageFlip(document.getElementById('book'),
    {
        width: 400, // required parameter - base page width
        height: 600  // required parameter - base page height
    }
);

pageFlip.loadFromHTML(document.querySelectorAll('.my-page'));

Une description et des spécifications plus détaillées de l'API peuvent être trouvées sur le lien ci-dessus.
Je veux parler de certains des problèmes et des nuances que j'ai rencontrés pendant le développement.

Calculs


La première chose à dire est un modèle mathématique. En principe, tous les calculs sont assez triviaux, mais cela m'a pris beaucoup de temps.

La tâche principale qui doit être résolue est de déterminer l'angle de transformation du tournage de page. Regardons l'image suivante: Le



point «A» indique le point de contact actuel dans le livre. Sur la base de la position de ce point - il est nécessaire d'effectuer d'autres calculs.

Pour déterminer l'angle - il est nécessaire de calculer deux valeurs - la distance du point A aux bords supérieur et droit du livre. Dans l'image ci-dessous, ils sont indiqués respectivement par T et L.



G est la diagonale de l'angle, peut être calculée par le théorème de Pythagore.

Par conséquent, pour calculer la rotation de l'image, vous pouvez utiliser la formule suivante: angle = - 2 * acos (L / G), et surtout, n'oubliez pas que le point de transformation dans ce cas est le coin supérieur gauche de la page.

Après avoir calculé l'angle - la partie la plus longue reste - c'est le calcul de la visibilité de la page. Ce qui devrait être apparemment nécessaire de quitter, et le reste, respectivement - pour couper.

Tout d'abord, vous devez trouver les points d'intersection de la page à retourner avec les bordures du livre. Dans les figures, elles sont indiquées par les points B et C.



J'ai fait cela de la manière la plus simple et la plus simple - sur le front. Il a construit les équations des droites par deux points, puis a recherché leur point d'intersection.

Après avoir trouvé tous les points d'intersection, nous déterminons les sommets de la zone de visibilité - et à ces points, nous rognons déjà la page à retourner.



Fondamentalement, tous les calculs se résument à deux choses:

  • calcul de l'angle de transformation
  • calcul de la visibilité des pages

L'ombrage est déjà basé sur des calculs effectués précédemment.

Passons maintenant à certains points que nous avons dû affronter lors de la mise en œuvre.

L'algorithme général est assez simple et se résume au tournage et au recadrage des pages.

Dans le cas de la toile et des images simples, tout est assez simple. Après avoir effectué les calculs, des méthodes de contexte de canevas 2d telles que la traduction, la rotation et le découpage sont utilisées.
Avec des blocs html un peu plus compliqués. Et s'il n'y a pas de problème avec la rotation - grâce aux transformations CSS, alors avec le recadrage tout s'est avéré un peu pire.

En conséquence, la façon la plus simple était d'utiliser les propriétés clip-path et css de la figure - polygone. Mais avant de définir les sommets des polygones pour le recadrage, il est nécessaire de transformer les coordonnées des points du canevas "global" - en coordonnées locales, par rapport à l'élément html. Ceci est résolu par l'application inverse de la matrice de rotation, avec un décalage par rapport à la position de l'élément.

Un autre problème était la mise à l'échelle et le positionnement automatique du livre. J'ai essayé de résoudre ce problème avec l'objet de configuration, qui est transmis lors de la création. Mais au final, il y avait pas mal de paramètres, et cela s'est avéré pas très pratique et pas évident.

J'ai d'abord utilisé Webpack pour l'assemblage, mais j'ai finalement décidé d'essayer rollup.js et j'ai été très agréablement surpris par le code final. Webpack demeure, car il gère l'assemblage à la volée plusieurs fois plus rapidement, et il est plus pratique lors du développement.

Je serai heureux d'entendre des commentaires et des suggestions pour le développement futur de la bibliothèque.

All Articles