Maison  >  Article  >  interface Web  >  Zoom avant, zoom arrière sur un point collant dans la toile

Zoom avant, zoom arrière sur un point collant dans la toile

WBOY
WBOYoriginal
2024-07-18 05:56:57786parcourir

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émo

Démonstration

Coder étape par étape

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 :

Image description
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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn