JQuery a rendu facile le recours au JavaScriptLangage de scripting orienté objet dans les applications web. Un ensemble de pratiques courantes, auparavant assez techniques, sont désormais accessibles, même aux débutants : faire des requêtes Ajax, accéder à des éléments du DOM en utilisant des sélecteurs CSSFeuilles de style qui permettent de mettre en forme des pages web., binder des actions sur des événements…
JQuery a aussi facilité le développement d’éléments plus complexes comme des champs d’autocomplétion, des fenêtres de dialogue ou des color pickers. Pour ces fonctionnalités plus complexes, il existe un grand nombre de plugins. Mais ces plugins sont souvent difficiles à intégrer et se veulent très génériques alors que l’on a souvent un besoin très précis (et que l’on souhaite limiter la quantité de JavaScript par souci évident de performance). Or certaines fonctionnalités pour lesquelles un grand nombre de plugins existent ne sont en fait pas très complexes à implémenter soi-même. Ici, nous allons voir comment on peut développer facilement et en peu de lignes un zoom.
Le but est de créer à partir d’une simple image dans le DOM une div qui présente une zone agrandie de cette image, de telle sorte que l’on puisse se déplacer sur l’image zoomée simplement en bougeant la souris.
De nombreuses présentations sont possibles : un zoom qui se déplace par dessus l’image, ou bien situé sur le côté, ou bien qui remplace l’image… un zoom carré, rond… Dans tous les cas le principe est le même, il sera donc facile de lui donner l’apparence que l’on veut et de le positionner où on veut.
Ici, nous allons réaliser un zoom rond qui suivra le curseur de la souris dès lors qu’elle sera au-dessus de l’image de départ. Les étapes sont donc :
Les versions 2.x de JQuery sont plus légères mais présentent le fâcheux inconvénient de ne pas être compatible avec les versions d’Internet Explorer antérieures à 9. Or IE 8 représente encore 5% de part de marché en février 2014, pourcentage d’internautes dont nous ne voulons pas nous priver. Pensez bien en revanche lorsque vous téléchargez la dernière version 1.x sur le site de JQuery à prendre le format .min.js, qui est compressé.
Le but est d’obtenir à partir d’une image un agrandissement de cette image contenu dans une div. La « partie div » de la méthode ne pose pas de problème, la partie image un peu plus. Deux cas de figure se présentent :
Nous allons nous positionner dans ce dernier cas : il suffira de quelques modifications pour mettre en place une des deux autre possibilités. Imaginons que les images sur lesquelles on souhaite mettre en place notre zoom portent la classe CSS « zoomable ». On peut donc imaginer un code tel que :
$(’img.zoomable’).each(function(){
var zoombox=$(’
<div id="’ + $(this).attr(’id’) + ’zoombox" class="zoombox" >
</div>’).insertAfter($(this));
$(this).clone().attr(’id’, $(this).attr(’id’) + ’zoom’).attr(’width’, $(this).attr(’width’)*2).appendTo(zoombox);
});
Ici, on sélectionne toutes les images à zoomer, puis on boucle sur le résultat : pour chaque image trouvée, on crée une div qu’on met juste après l’image originale, et on copie l’image dans la div. On paramètre la largeur de la copie à deux fois celle de l’originale. De plus, la div et l’image copiée ont chacune un id dérivé de celui de l’image source, de façon à pouvoir y accéder à partir de l’image source.
Maintenant que nous avons construit la structure HTMLHTML (HyperText Markup Language) est un langage permettant de décrire le découpage d'une page web. de notre zoom, il faut faire en sorte de l’afficher seulement lorsque la souris passe au-dessus, et de le positionner pour qu’il suive celle-ci. Les événements qu’il faut intercepter sont donc :
Si l’on continue à partir du code précédent, on peut donc écrire le code suivant :
$(’img.zoomable’).each(function(){
var zoombox=$(’
<div id="’ + $(this).attr(’id’) + ’zoombox" class="zoombox" >
</div>’).insertAfter($(this));
$(this).clone().attr(’id’, $(this).attr(’id’) + ’zoom’).attr(’width’, $(this).attr(’width’)*2).appendTo(zoombox); bindZoom($(this)); });
function bindZoom(img) {
img.bind(’mouseenter mouseover’, function(e){
$(’#’ + img.attr(’id’) + ’zoombox’).css(’display’,’block’);
positionZoom(e,img);
});
img.bind(’mouseleave’, function(e){
$(’#’ + img.attr(’id’) + ’zoombox’).css(’display’,’none’);
});
img.bind(’mousemove’, function(e){
positionZoom(e,img);
});
}
Ici, pour chaque image zoomable, on crée le zoom comme vu précédemment, puis on appelle une fonction qui regroupe les bindings. Dans cette fonction, on retrouve les 3 événements annoncés :
Le positionnement du zoom fait toujours appel à une fonction positionZoom que nous allons voir à présent.
Cette partie peut apparaître comme la plus compliquée, mais ne l’est pas tant que ça : il s’agit simplement de se déplacer dans un repère orthonormé en deux dimensions. Il faut donc calculer une position x et une position y. Deux options se présentent :
Nous allons retenir cette deuxième proposition. On peut donc obtenir le code suivant :
function positionZoom(e,img) {
var offset=img.offset();
var zoombox=$(’#’ + img.attr(’id’) + ’zoombox’);
zoombox.css(’left’, (e.pageX-offset.left+30)+’px’);
zoombox.css(’top’, (e.pageY-offset.top-75)+’px’);
var zoom=$(’#’ + img.attr(’id’) + ’zoom’);
zoom.css(’left’, ((e.pageX-offset.left-37.5)*-2)+’px’);
zoom.css(’top’, ((e.pageY-offset.top-37.5)*-2)+’px’);
}
Ici, on récupère l’offset de l’image par rapport à la page. Puis on positionne la boîte en lui donnant un x qui l’offset de la souris par rapport à la page moins celui de l’image, ce qui nous donne l’offset de la souris par rapport à l’image. De plus, on décale la boîte de 30px vers la gauche pour la détacher du curseur de la souris, et de 75px vers le haut pour la centrer verticalement par rapport au curseur (on a une boîte de 150px de côté).
Pour positionner l’image zoomée, c’est un peu plus complexe. D’abord le mouvement est inversé : si je bouge ma souris vers la droite, alors je dois décaler mon image zoomée vers la gauche. Pourquoi ? Dans un cas, la zone ciblée bouge avec ma souris. Dans l’autre, la zone ciblée est fixe : c’est le centre de ma boîte. Donc pour que le centre de ma boîte coïncide avec un point plus à droite sur l’image, je dois déplacer mon image vers la gauche. Même raisonnement pour l’approche verticale.
Ensuite, il faut tenir compte du changement d’échelle : lorsque je me déplace de 100px sur mon image originale, je dois décaler mon zoom de 100 fois mon ratio, ici 100*2px. De plus, mon zoom ne fait pas la taille d’un px, et j’ai fait en sorte que le point ciblé par mon curseur corresponde au centre de mon zoom, et non pas au coin supérieur gauche. Je dois donc en tenir compte dans mon calcul d’offset.
Au final, on soustrait l’offset de l’image à celui de la page comme précédemment, et l’on soustrait encore la taille de la boîte divisée par le ratio. Ici j’ai une boîte de 150px et un ratio de 2 : je soustrais 37,5px. J’obtiens une position relative du curseur sur l’image originale. Pour avoir l’offset final sur le zoom, je multiplie par le ratio, et j’inverse le signe (ou je multiplie par -1) pour tenir compte du mouvement inversé que j’ai expliqué précédemment. Et le tour est joué !
Le style sur un composant de ce genre n’est pas uniquement décoratif. Il permet également le positionnement absolu ou relatif des éléments les uns par rapport aux autres. Ici, nous nous contenterons de ce qui est nécessaire à la réalisation du zoom et de la mise en forme de la boîte de zoom.
Nous allons considérer que nous travaillons sur le code HTML suivant :
<img id="monimage" class="zoomable" src="monimage.jpg" alt="" width="512" />
</div>
Nous avons ici quelque chose de simpliste : une image dans une div. La div permettra de servir de repère pour le positionnement relatif du zoom. Je propose le code CSS suivant :
div#container {
position: relative;
width: 1000px;
margin: auto;
}
img.zoomable{
cursor: crosshair;
}
div[id$="zoombox"] {
position: absolute;
overflow: hidden;
height: 150px;
width: 150px;
border: 2px solid #E5E5E5;
background-color: #FFFFFF;
box-shadow: 1px 1px 12px #999999;
border-radius: 75px;
-moz-border-radius: 75px;
-webkit-border-radius: 75px;
}
img[id$="zoom"] {
position: absolute;
}
Il y a quatre groupes de propriétés CSS :
Il ne reste qu’à assembler tous ces éléments pour mettre en oeuvre notre zoom.
Voici un petit code presque auto-suffisant pour afficher notre zoom. Il faut toutefois :
css width= 512″
), ou bien modifiez la width de façon à ce qu’elle soit la moitié de la taille réelle.<div id="container">
<img id="monimage" src="monimage.jpg" width="512" class="zoomable" />
</div>
La longueur de cet article peut faire penser que la tâche est plus ardue que le titre ne le laisse supposer, mais c’est en définitive effectivement assez simple.
Pour aller plus loin, il y a mille façons d’améliorer et/ou de personnaliser ce zoom :
Découvrez la planche #44 !
Découvrez la planche #55 !
Si vous aussi vous avez fait le choix d’AngularJS pour un de vos projets, vous êtes au bon endroit ! AngularJS ne sera bientôt plus qu’un lointain souvenir… et pour cause, Google a fait le choix d’arrêter le framework.