🇫🇷 L'art de faire un Zoom en Web
Tags: javascript, beginners, programming, french
Published: 2024-03-15 13:02:10

Dans une application d’édition (photo, vidéo, schéma …), il y a toujours un moyen de zoomer et de dézoomer et il est facile de se dire que c’est une fonctionnalité rapide à implémenter. Puis on le fait et on se rend compte de sa complexité.

Je vais donc expliquer quelles sont les conditions pour qu’un zoom soit réussi et 2 façons de l’implémenter, avec leurs avantages et leurs inconvénients.

On ne va pas trop parler maths, ne vous inquiétez pas.

![math focus people](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/64byd6dzaf3tkb9zluu4.gif)

## Qu’est ce qu’un zoom réussi ?
Il y a 3 conditions pour qu’un zoom soit fonctionnel et intuitif pour l’utilisateur: 
- Les objets sur lesquels on zoom doivent grossir ou rapetisser selon l’action voulue et toutes les actions doivent être réversibles.
- Pour que le feeling du zoom soit réussi et que l’utilisateur ne se perde pas lors d’un zoom, il faut que le zoom prenne en compte la position de la souris.
- La modification de la distance entre les objets doit être proportionnel au ratio de zoom.

Et si on prend des schémas, en prenant en exemple d’un éditeur (le rectangle noir représentant la page afficher):

![zoom schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2nko9jyd6ze0rb3rhpr5.png)

![unzoom schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ywz5sp6ypa9jpn3pklob.png)

Les lignes pointillées vertes représentent les lignes de fuite des objets, prenant pour centre le curseur de la souris. Ces lignes ne doivent pas être modifiées avec le zoom, mais seulement avec la position des objets et de la souris.

Lors d’une modification du zoom, tous les objets doivent se déplacer le long de ces lignes pour rendre le zoom fluide et compréhensible.

## Comment on fait ça ?

Premièrement, il faut choisir si on prend un ratio de zoom constant ou un step de zoom constant. Le ratio est le zoom fait par rapport au précédent et le step est la différence entre 2 zooms.
- ratio de 50% : 100% ⇒ 150% ⇒ 225% ⇒ 337.5
- step de 50% : 100% ⇒ 150% ⇒ 200% ⇒ 250%

Il n’y a pas de différence d’implémentation entre les deux, c’est juste un choix d’UX.

Pour l’implémentation, je vais présenter deux solutions avec leurs avantages et leurs inconvénients et je vous laisse faire votre choix en fonction de votre besoin.

![schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/reszf3drpcqiosmk94w0.png)

## Utiliser les règles CSS

Avec les propriétés CSS ‘scale’ et ‘translate’, il est possible de créer un effet de zoom très facilement.

Le but est de faire notre page comme elle doit être, puis de la grossir globalement du facteur voulu (par exemple 50%) et enfin de déplacer la page en fonction de la position de la souris.

Pour le zoom on obtient ceci :

![schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rfzlxmse7rsnkeqkvonf.png)

Le rectangle rouge représente la page sur laquelle on veut zoomer, contenant les rectangles jaunes.

Le rectangle noir représente la vue que l’utilisateur a (l’écran de l’utilisateur), sur le schéma de gauche les rectangles noir et rouge sont confondus.

Après le zoom, la page est scaled de 150% (ici) et translated d’une certaine valeur en x et y.

La translation est de : -rmx sur x et -rmy sur y avec:

- r le ratio de zoom (ici 50%)

- (mx;my) la position de la souris sur l’écran

Et pour le dézoom :

![schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ai2x2rugl38ewtmboayn.png)

Dans ce cas la translation est de r*mx et r*my.

Pour plusieurs zooms, si le ratio est constant (par exemple chaque zoom est un grossissement de 50%) alors le scale se multiplie avec le précédent, par contre si le step est constant (100% ⇒ 150% ⇒ 200% ⇒ 250% …) alors le scale s’additionne avec le précédent. **Dans tous les cas la translation s’additionne avec la précédente.**

L’implémentation en CSS est facile puisqu’il ne faut pas gérer chaque élément de notre page un par un, tout sera géré en une seule fois.

Cependant, il y a des problèmes avec cette implémentation :
- Complexité de la gestion de la position de la souris par rapport aux éléments
- Très peu modulable

Pour résoudre ces problèmes, il y a une autre implémentation possible.

## Bouger nos éléments

Si on ne veut pas faire du CSS, il est possible de faire bouger les objets le long des lignes de fuite qu’on a vues précédemment.

Pour cela, on va modifier la taille et la position des objets.

La taille c’est facile, on multiplie juste la taille actuelle par le zoom effectué pour obtenir la nouvelle taille.

**Par contre la position, c’est un autre problème.**

Les objets doivent suivre la ligne définie par la position de la souris, et la position de leur centre. Ces lignes définissent l’orientation du vecteur de déplacement de chaque objet.


![vecteur schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/873lard3qjii74w5saon.png)

La norme de ces vecteurs dépend de leur distance avec la souris.

Le vecteur de déplacement est donc défini comme suit :
- r*(x-mx)+mx
- r* (y-my)+my

Avec r le ratio de zoom, (x;y) la position de l’objet à déplacer et (mx;my) la position de la souris.

On obtient ceci :

![schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j2u9r0e3vno5me2nbito.png)

Cette méthode est plus complexe d’implémentation mais permet de gérer entièrement la position et la taille des objets. Elle permet aussi de pouvoir connaitre facilement la position de la souris par rapport aux objets. De plus, comme tous les objets connaissent leur taille affichée, il n’est pas nécessaire de connaitre le ratio de zoom actuel pour l’obtenir et l’utiliser (pour d’autres fonctionnalités par exemple).

## Conclusion

Le zoom n’est donc pas une fonctionnalité si simple à implémenter et les problèmes rencontrés dépendent du choix de l’implémentation, que l’on peut résumer comme ceci :

|  | Implémentation 1 : CSS | Implémentation 2 : Gestion des Objet 1 à 1 |
| --- | --- | --- |
| Avantages | Simple d’implémentation & Gestion de toute la page en une seule fois | Modularité complète & Interactions utilisateur plus simple |
| Inconvénients | Peu Modulable & Interactions utilisateur plus complexe | Complexité d’implémentation & Gestion de chaque propriété peut devenir fastidieux |

J’ai proposé 2 choix d’implémentations mais il en existe surement d’autres avec chacun des avantages et inconvénients. J’ai une préférence pour la 2ème implémentation malgré sa complexité pour sa modularité.

Il faut cependant bien connaitre les contraintes pour faire un choix pertinent, ni trop complexe ni trop contraignant.