Le zoom avant et arrière avec stick point est un cas d'utilisation régulier que nous rencontrons sur les outils de conception ou de construction tels que Figma. Dans ce blog, je présenterai un algorithme de base pour le gérer par javascript, HTML et CSS.
Démonstration
1. Créer un conteneur et un élément évolutif
<div id="app"> <div class="parent"> <div class="scalable-child"></div> </div> </div>
.scalable-child { width: 300px; height: 300px; position: relative; top: 0; left: 0; pointer-events: none; transform-origin: left top; background-image: url('https://cdn4.vectorstock.com/i/1000x1000/17/58/caro-pattern-background-vector-2261758.jpg'); background-size: contain; } .parent { position: relative; background-color: white; width: 100vw; height: 100vh; }
Dans cet exemple, j'utilise un div comme élément évolutif avec la classe « scalable-child » et son conteneur est un div avec la classe « parent ».
A noter pour certains biens :
En haut, à gauche : 0 est la position par défaut
Pointer-event : aucun, car nous ajouterons un événement au parent, si pointer-event !== none, l'algorithme échouera.
Transformation-origine : en haut à gauche, qui fait les coordonnées de l'origine pour calculer la position
2. Ajouter un écouteur d'événement de roue
const parent = document.querySelector('.parent'); const child = document.querySelector('.scalable-child');
parent.addEventListener('wheel', wheelEventHandler, { passive: false, capture: true, });
Nous utiliserons WheelEvent pour gérer le zoom avant, le zoom arrière et le déplacement de l'enfant
Remarque : cet exemple illustre uniquement le trackpad. Vous devez également gérer les événements pour les raccourcis clavier tels que (Ctrl +, Ctr -) ou la souris.
let left = 0; let top = 0; let scale = 1; const wheelEventHandler = (e) => { e.preventDefault(); // Handle zoom with touch pad and hot key. const isZooming = e.ctrlKey || e.metaKey; let newValues = {}; if (isZooming) { newValues = calculateOnZooming(e, scale, left, top); } else { newValues = calculateOnMoving(e, scale, left, top); } left = newValues.newLeft; top = newValues.newTop; scale = newValues.newScale; Object.assign(child.style, { transform: `scale(${scale})`, left: `${left}px`, top: `${top}px`, }); };
Tout d'abord, nous avons la variable isZooming pour vérifier si vous effectuez un zoom ou un déplacement de l'élément enfant.
Ensuite, nous calculons la nouvelle position et l'échelle de l'élément enfant. La gauche, le haut et l'échelle sont utilisés comme variables tempérées.
Et il est temps de concentrer l'algorithme sur 2 fonctions de calcul :
3. Calculer sur Zoom
const calculateOnZooming = (e, oldScale, oldLeft, oldTop) => { let newScale = oldScale - e.deltaY * oldScale * 0.01; newScale = Math.max(newScale, 0.1); const newLeft = oldLeft - (e.offsetX - oldLeft) * (newScale / scale - 1); const newTop = oldTop - (e.offsetY - oldTop) * (newScale / scale - 1); return { newScale, newLeft, newTop, }; };
Lors du zoom, wheelEvent renverra le deltaY sous forme de rapport d'échelle et nous pourrons l'utiliser pour calculer newScale
deltaY> 0 => zoom arrière
deltaY < 0 => zoomer
Le detalScale = e.deltaY * oldScale * 0,01 pour contrôler la vitesse de mise à l'échelle
Voyons l'image ci-dessous pour mieux comprendre comment calculer les variables newLeft et newTop :
Commencez à zoomer sur l'enfant lorsque la souris est au point A. A ce moment-là, nous pouvons obtenir quelques valeurs :
e.offsetX : distance entre la souris et le bord gauche du parent
e.offsetY : distance entre la souris et le bord supérieur du parent
gauche : valeur de style gauche de l'enfant actuel
haut : la meilleure valeur de style de l'enfant actuel
L'enfant est mis à l'échelle d'un rapport d'échelle à un rapport d'échelle, et le point A passe à A'.
Donc, pour rendre un point collant (avec le parent), nous devons calculer deltaX et deltaY puis déplacer l'enfant avec exactement px.
détalX = x' - x
= x * (échelle' / échelle) - x
= x * (échelle' / échelle - 1)
= (e.offsetX - gauche) * (échelle' / échelle - 1)
detalY = y' - y
= y * (échelle' / échelle) - y
= y * (échelle' / échelle - 1)
= (e.offsetY - top) * (scale' / scale - 1)
newLeft = gauche - detalX
nouveauTop = haut - détailY
4. Calculer en cas de déménagement
const calculateOnMoving = (e, oldScale, oldLeft, oldTop) => { return { newLeft: oldLeft - e.deltaX * 2, newTop: oldTop - e.deltaY * 2, newScale: oldScale, }; };
En cas de déplacement, nous devons calculer uniquement les valeurs newLeft et newTop. Et nous *2 chaque valeur delta pour augmenter également la vitesse.
C’est tout ce que nous devons gérer. J'espère que c'est utile. Merci d'avoir regardé !
Vous pouvez consulter le code source complet ici.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!