Pour offrir une expérience visuelle enrichie dans les applications rapides (Quick Apps), il est possible de simuler un effet de zoom localisé sur une image sans recourir à des composants natifs dédiés. Cette approche repose sur la combinaison dynamique de propriétés CSS — notamment background-image, background-size et background-position — couplée à la gestion précise des événements tactiles.
Principe technique
L’effet de zoom est obtenu en affichant l’image source comme arrière-plan d’un conteneur fixe, puis en ajustant sa taille (background-size) pour agrandir le contenu, tout en déplaçant visuellement la zone visible via background-position. La position cible du zoom est calculée en temps réel à partir des coordonnées tactiles relatives à l’élément image.
Gestion des coordonnées tactiles
Lors d’un glissement sur l’image, l’événement ontouchmove fournit les décalages offsetX et offsetY. Ces valeurs sont inversées et limitées aux dimensions du conteneur afin d’éviter les débordements. Le code suivant illustre une version refactorisée avec une logique plus robuste et des noms de variables explicites :
handleTouchMove(event) {
this.isZoomActive = true;
const touch = event.changedTouches[0];
const { offsetX, offsetY } = touch;
// Contraintes de déplacement : maintenir la vue dans les limites
const maxX = this.containerWidth - this.zoomedWidth;
const maxY = this.containerHeight - this.zoomedHeight;
this.backgroundOffsetX = Math.max(maxX, Math.min(0, -offsetX));
this.backgroundOffsetY = Math.max(maxY, Math.min(0, -offsetY));
}
Structure HTML et styles
Le rendu repose sur deux éléments distincts : un <image> déclenchant les interactions, et un <div> servant de fenêtre de zoom. Ce dernier utilise un fond personnalisé dont les propriétés évoluent dynamiquement :
<template>
<div class="app-root">
<text class="header">Zoom tactile sur image</text>
<image
class="source-image"
src="/assets/photo.jpg"
ontouchmove="handleTouchMove"
ontouchend="handleTouchEnd"
/>
<div
class="zoom-view"
show="{{isZoomActive}}"
style="background-position: {{backgroundOffsetX}}px {{backgroundOffsetY}}px;"
></div>
</div>
</template>
<style>
.app-root { flex-direction: column; align-items: center; padding: 20px; }
.header { font-size: 48px; margin-bottom: 30px; }
.source-image { width: 500px; height: 500px; }
.zoom-view {
width: 500px;
height: 500px;
background-image: url(/assets/photo.jpg);
background-size: 1000px 1000px;
background-repeat: no-repeat;
margin-top: 20px;
border: 2px solid #007DFF;
}
</style>
<script>
module.exports = {
data: {
isZoomActive: false,
backgroundOffsetX: 0,
backgroundOffsetY: 0,
containerWidth: 500,
containerHeight: 500,
zoomedWidth: 1000,
zoomedHeight: 1000
},
handleTouchMove(event) {
this.isZoomActive = true;
const touch = event.changedTouches[0];
const { offsetX, offsetY } = touch;
const maxX = this.containerWidth - this.zoomedWidth;
const maxY = this.containerHeight - this.zoomedHeight;
this.backgroundOffsetX = Math.max(maxX, Math.min(0, -offsetX));
this.backgroundOffsetY = Math.max(maxY, Math.min(0, -offsetY));
},
handleTouchEnd() {
this.isZoomActive = false;
}
};
</script>
Cette implémentation garantit un contrôle fluide du point de zoom, avec des limites naturelles empêchant le déplacement hors cadre. Le facteur d’agrandissement est enttièrement configurbale via background-size, permettant d’ajuster la résolution apparente selon les besoins.