Comment créer un plug-in de découpage d'image jQuery à partir de zéro - Partie I

Les applications Web doivent fournir des solutions faciles à utiliser pour le téléchargement et la manipulation de contenu riche. Ce processus peut créer des difficultés pour certains utilisateurs ayant des compétences minimales en matière de retouche photo. Le rognage est l'une des techniques de manipulation de photos les plus utilisées. Ce didacticiel pas à pas couvrira l'ensemble du processus de développement d'un plug-in de rognage d'images pour la bibliothèque JavaScript jQuery..


Étape 1. Configuration de l'espace de travail

Premièrement, nous allons configurer notre espace de travail de projet pour ce tutoriel. Commencez par créer une hiérarchie de répertoires et de fichiers vides nommés comme dans l'exemple ci-dessous:

Ensuite, vous devrez télécharger la bibliothèque JavaScript jQuery et la placer à l’intérieur du / ressources / js / dossier. L'image utilisée dans ce tutoriel doit être nommée exemple.jpg et placé à l'intérieur du / ressources / images / dossier. Vous pouvez utiliser cette image (merci à gsso-stock), fourni avec les fichiers source de ce tutoriel, ou un des vôtres. Et le dernier fichier est le contour.gif fichier, qui doit être placé à l'intérieur du / resources / js / imageCrop / dossier.


Étape 2. Création de la page de test

Pour tester notre plug-in, nous devrons l'attacher à une image. Avant de commencer à travailler dessus, nous allons créer une simple page contenant cette image..

Le HTML

Ouvrez le index.html déposer dans votre éditeur de texte préféré et écrire le code suivant.

     Plug-in de recadrage d'image jQuery       

Plug-in de recadrage d'image jQuery

Plug-in de recadrage d'image jQuery

Il n'y a rien d'extraordinaire ici: juste du code HTML simple. Nous avons chargé une feuille de style pour la page, jQuery, nos fichiers de plug-in (actuellement vides) et placé une image dans le document..

Le CSS

Maintenant modifier style.css Comme montré ci-dessus.

 * marge: 0; contour: 0; rembourrage: 0;  body background-color: #ededed; couleur: # 646464; font-family: 'Verdana', 'Geneva', sans-serif; taille de police: 12px; text-shadow: 0 1px 0 #ffffff;  h1 font-size: 24px; poids de police: normal; marge: 0 0 10px 0;  div # wrapper margin: 25px 25px 25px 25px;  div.image-decorator -moz-border-radius: 5px 5px 5px 5px; -moz-box-shadow: 0 0 6px # c8c8c8; -webkit-border-radius: 5px 5px 5px 5px; -webkit-box-shadow: 0 0 6px # c8c8c8; couleur de fond: #ffffff; bordure: 1px solide # c8c8c8; border-radius: 5px 5px 5px 5px; box-shadow: 0 0 6px # c8c8c8; affichage: inline-block; hauteur: 360px; remplissage: 5px 5px 5px 5px; largeur: 480px; 

Nous avons personnalisé l'aspect de notre page en modifiant la couleur d'arrière-plan et en ajoutant un style de base au titre et à l'image..


Étape 3. Écriture d'un plug-in jQuery de base

Commençons par créer un plug-in jQuery de base.

"Découvrez comment écrire votre propre plug-in via cet article. Il décrit les bases, les meilleures pratiques et les pièges courants à surveiller lorsque vous commencez à écrire votre plug-in."

Ouvrir /resources/js/imageCrop/jquery.imagecrop.js et ajoutez le code suivant.

 // toujours envelopper un plug-in '(function ($) // le plug-in va ici) (jQuery);' (function ($) $ .imageCrop = fonction (object, options personnalisées) ; $ .fn.imageCrop = fonction (options personnalisées) // Itérer sur chaque objet this.each (fonction () var currentObject = this, image = new Image (); // et attache une imageCrop quand l'objet est chargé image.onload = function () $ .imageCrop (currentObject, customOptions);; // Réinitialise le src car les images en cache ne se déclenchent parfois pas image .src = currentObject.src;); // À moins que le plug-in ne renvoie une valeur intrinsèque, demandez toujours à la fonction // de renvoyer le mot-clé 'this' pour conserver la chaîne - restituer this;;) (jQuery);

Nous venons d'étendre jQuery en ajoutant une nouvelle propriété de fonction à la jQuery.fn objet. Maintenant, nous avons un plug-in très basique qui itère sur chaque objet et attache imageCrop quand l'objet est chargé. Notez que les images en cache ne se déclenchent pas charge parfois, nous réinitialisons le src attribut pour résoudre ce problème.


Étape 4. Ajout d'options personnalisables

En tenant compte des options de personnalisation, un plug-in est beaucoup plus flexible pour l'utilisateur.

 $ .imageCrop = function (object, customOptions) // Plutôt que de requérir une longue quantité d'arguments, passez les // options du plug-in dans un littéral d'objet pouvant être étendu sur les // valeurs par défaut du plug-in var defaultOptions =  allowMove: true, allowResize: true, allowSelect: true, minSelect: [0, 0], contourOpacity: 0.5, overlayOpacity: 0.5, selectionPosition: [0, 0], selectionWidth: 0, selectionHeight: 0; // Définir les options par défaut var options = defaultOptions; // Et les fusionner avec les options personnalisées setOptions (customOptions); ; 

Nous avons défini un tableau avec les options par défaut, puis les avons fusionnées avec les options personnalisées en appelant le setOptions une fonction. Allons plus loin et écrivons le corps de cette fonction.

? // Fusionner les options en cours avec la fonction d’option personnalisée setOptions (customOptions) options = $ .extend (options, customOptions); ; 

le $ .extend () la fonction fusionne le contenu de deux objets ou plus dans le premier objet.

Les options

La liste suivante décrit chaque option du plug-in..

  • allowMove - Spécifie si la sélection peut être déplacée (la valeur par défaut est vrai).
  • permettreResize - Spécifie si la sélection peut être redimensionnée (la valeur par défaut est vrai).
  • allowSelect - Spécifie si l'utilisateur peut effectuer une nouvelle sélection (la valeur par défaut est vrai).
  • minSelect - La taille minimale de la zone pour enregistrer une nouvelle sélection (la valeur par défaut est [0, 0]).
  • contourOpacité - L’opacité du contour (la valeur par défaut est 0.5).
  • superpositionOpacité - L’opacité de superposition (la valeur par défaut est 0.5).
  • selectionPosition - La position de sélection (la valeur par défaut est [0, 0]).
  • selectionWidth - La largeur de la sélection (la valeur par défaut est 0).
  • sélectionHauteur - La hauteur de sélection (la valeur par défaut est 0).

Étape 5. Configuration des couches

A cette étape, nous allons modifier le DOM pour nous préparer à la prochaine étape: l'interface du plug-in.

Tout d'abord, nous allons initialiser la couche d'image.

? // Initialise la couche d'image var $ image = $ (object); 

Maintenant initialisez un titulaire d'image.

? // Initialise un titulaire d'image var $ holder = $ ('
') .css (position:' relative ') .width ($ image.width ()) .height ($ image.height ()); // Enroule le titulaire autour de l'image $ image.wrap ($ titulaire) .css (position: 'absolute');

Comme vous pouvez le constater, le calque de support a la même taille que l’image et une position relative. Ensuite, nous appelons le .emballage() fonction pour placer l'image à l'intérieur du support.

Au-dessus de l'image sera le calque de superposition.

? // Initialise un calque de superposition et le place au-dessus de l'image var $ overlay = $ ('
') .css (opacity: options.overlayOpacity, position:' absolute ') .width ($ image.width ()) .height ($ image.height ()) .insertAfter ($ image);

Ce calque a la même taille que l’image, mais a également reçu un positionnement absolu. Nous obtenons la valeur pour l'opacité du options.overlayOpacity et laissez jQuery l'appliquer. Cet élément a également un identifiant, nous pouvons donc modifier ses propriétés via la feuille de style du plug-in. En bas, nous appelons le .insertAfter () méthode pour placer le calque de superposition juste après l'image.

La couche suivante est la couche de déclenchement; nous le placerons après la couche de recouvrement, comme nous l'avons fait avec les précédents.

? // Initialise un calque de déclenchement et le place au-dessus du calque de recouvrement var $ trigger = $ ('
') .css (backgroundColor:' # 000000 ', opacité: 0, position:' absolu ') .width ($ image.width ()) .height ($ image.height ()) .insertAfter ($ superposition) ;

La couleur de fond n'a pas vraiment d'importance mais elle doit être différente de celle transparente (qui est par défaut). Cette couche est invisible pour l'utilisateur, mais elle gérera certains événements..

Nous allons placer la couche de contour au-dessus de la couche de déclenchement.

? // Initialise un calque de contour et le place au-dessus du calque de déclenchement var $ outline = $ ('
') .css (opacity: options.outlineOpacity, position:' absolute ') .insertAfter ($ trigger);

Et enfin la dernière couche.

? // Initialise un calque de sélection et le place au-dessus du calque hiérarchique var $ selection = $ ('
') .css (background:' url ('+ $ image.attr (' src ') +') no-repeat ', position:' absolute ') .insertAfter ($ contour);

le .attr () La méthode retourne la valeur d'un attribut spécifié. Nous l'avons utilisé pour obtenir l'image src et la définir comme arrière-plan du calque de sélection.

Positionnement absolu à l'intérieur du positionnement relatif

Vous le savez peut-être déjà, mais un élément avec un positionnement relatif vous donne le contrôle pour positionner absolument les éléments à l'intérieur de celui-ci. C’est pourquoi la couche support a une position relative et tous ses enfants une position absolue..

Une excellente explication de cette astuce est couverte dans cet article.


Étape 6. Mise à jour de l'interface

Tout d'abord, nous allons initialiser certaines variables.

? // Initialisation des variables globales var selectionExists, selectionOffset = [0, 0], selectionOrigin = [0, 0]; 

le sélectionExiste nous informera si une sélection existe. le sélectionOffset contiendra le décalage par rapport à l'origine de l'image, et le sélectionOrigine indiquera l'origine de la sélection. Les choses seront beaucoup plus claires après quelques étapes.

Les conditions suivantes sont requises si la sélection existe lorsque le plug-in est chargé..

? // Vérifiez si la taille de la sélection est supérieure au minimum accepté // et définissez l'existence de la sélection en conséquence si (options.selectionWidth> options.minSelect [0] && options.selectionHeight> options.minSelect [1]) selectionExists = true; sinon selectionExists = false; 

Ensuite, nous appellerons le updateInterface () fonction pour la première fois pour initialiser l'interface.

? // Appelez la fonction 'updateInterface' pour la première fois pour // initialiser l'interface du plug-in updateInterface (); 

Nous écrirons le corps de cette fonction sous peu. En ce moment, prenons soin de notre premier événement.

? if (options.allowSelect) // Lier un gestionnaire d'événements à l'événement 'mousedown' du calque déclencheur $ trigger.mousedown (setSelection); 

Nous appelons .souris vers le bas() si options.allowSelect est vrai. Cela liera un gestionnaire d’événements à la souris vers le bas événement de la couche de déclenchement. Ainsi, si un utilisateur clique sur l'image, le setSelection () sera invoqué.

? // Obtient le décalage actuel d'un élément function getElementOffset (objet) var offset = $ (objet) .offset (); return [offset.left, offset.top]; ; // Récupère la position actuelle de la souris par rapport à la position de l'image. GetMousePosition (event) var imageOffset = getElementOffset ($ image); var x = event.pageX - imageOffset [0], y = event.pageY - imageOffset [1]; x = (x < 0) ? 0 : (x > $ image.width ())? $ image.width (): x; y = (y < 0) ? 0 : (y > $ image.height ())? $ image.height (): y; retourne [x, y]; ; 

La première fonction, getElementOffset (), renvoie les coordonnées gauche et supérieure de l'objet spécifié par rapport au document. Nous avons récupéré cette valeur en appelant le .décalage() méthode. La deuxième fonction, getMousePosition (), renvoie la position actuelle de la souris, mais par rapport à la position de l'image. Nous allons donc travailler avec des valeurs comprises uniquement entre 0 et la largeur / hauteur de l'image sur l'axe des x / y, respectivement..

Ecrivons une fonction pour mettre à jour nos couches.

? // Mise à jour de la fonction de couche de superposition updateOverlayLayer () $ overlay.css (display: selectionExists? 'Block': 'none'); ; 

Cette fonction vérifie la valeur du sélectionExiste variable, et détermine si le calque de superposition doit être affiché ou non.

? // Met à jour la fonction de couche déclencheur updateTriggerLayer () $ trigger.css (curseur: options.allowSelect? 'Réticule': 'default'); ; 

le updateTriggerLayer () la fonction change le curseur en réticule ou défaut, en fonction de la options.allowSelect valeur.

Ensuite, nous écrirons le updateSelection () une fonction. Il mettra à jour non seulement la couche de sélection, mais également la couche de contour.

? // Met à jour la fonction de sélection updateSelection () // Met à jour la couche de contour $ outline.css (curseur: 'default', affichage: selectionExists? 'Block': 'none', gauche: options.selectionPosition [0], en haut : options.selectionPosition [1]) .width (options.selectionWidth) .height (options.selectionHeight); // Met à jour le calque de sélection $ selection.css (backgroundPosition: (- options.selectionPosition [0] - 1) + + px '+ (- options.selectionPosition [1] - 1) +' px ', curseur: options. allowMove? 'move': 'default', display: selectionExists? 'block': 'none', gauche: options.selectionPosition [0] + 1, en haut: options.selectionPosition [1] + 1) .width ((options .selectionWidth - 2> 0)? (options.selectionWidth - 2): 0) .height ((options.selectionHeight - 2> 0)? (options.selectionHeight - 2): 0); ; 

Tout d’abord, cette fonction définit les propriétés du calque de contour: le curseur, l’affichage, la taille et sa position. Ensuite vient la couche de sélection; la nouvelle valeur de la position de fond fera que les images se chevauchent de manière transparente.

Maintenant, nous avons besoin d’une fonction pour mettre à jour le curseur en cas de besoin. Par exemple, lorsque nous faisons une sélection, nous voulons que le curseur reste un réticule peu importe de quelle couche nous sommes sur.

? // met à jour le type de curseur function updateCursor (cursorType) $ trigger.css (cursor: cursorType); $ outline.css (cursor: cursorType); $ selection.css (curseur: type de curseur); ; 

Oui, c'est aussi simple que ça en a l'air. Il suffit de changer le type de curseur à celui spécifié!

Et maintenant, la dernière fonction de cette étape; nous en avons besoin pour mettre à jour l'interface du plug-in dans différentes situations - lors de la sélection, du redimensionnement, de la libération de la sélection et même lors de l'initialisation du plug-in.

? // met à jour la fonction d'interface du plug-in updateInterface (sender) switch (sender) case 'setSelection': updateOverlayLayer (); updateSelection (); Pause; case 'resizeSelection': updateSelection (); updateCursor ('réticule'); Pause; défaut: updateTriggerLayer (); updateOverlayLayer (); updateSelection (); ; 

Comme vous pouvez le voir, le updateInterface () fonction filtre certains cas et appelle les fonctions nécessaires que nous venons d'écrire.


Étape 7. Définition de la sélection

Jusqu'à présent, nous nous sommes occupés des options de personnalisation et de l'interface, mais rien ne concernait la manière dont l'utilisateur interagissait avec le plug-in. Écrivons une fonction qui définit une nouvelle sélection lorsque l'utilisateur clique sur l'image.

? // Définition d'une nouvelle fonction de sélection setSelection (event) // Empêche l'action par défaut de l'événement event.preventDefault (); // Empêche la notification de l'événement event.stopPropagation (); // Lier un gestionnaire d'événements aux événements 'mousemove' et 'mouseup' $ (document) .mousemove (resizeSelection) .mouseup (releaseSelection); // Notifier qu'une sélection existe selectionExists = true; // Réinitialiser la taille de la sélection options.selectionWidth = 0; options.selectionHeight = 0; // Récupère l'origine de la sélection selectionOrigin = getMousePosition (event); // Et définit sa position options.selectionPosition [0] = selectionOrigin [0]; options.selectionPosition [1] = selectionOrigin [1]; // Met à jour uniquement les éléments nécessaires de l'interface du plug-in // en spécifiant l'expéditeur de l'appel actuel updateInterface ('setSelection'); ; 

Premièrement le setSélection fonction appelle deux méthodes: event.preventDefault () et event.stopPropagation (). Cela empêche l'action par défaut et les gestionnaires parents d'être informés de l'événement. le .mousemove () méthode lie un gestionnaire d’événements à la déplacer la souris un événement. Cela appellera le resizeSelection () fonctionne chaque fois que l'utilisateur déplace le pointeur de la souris. Pour notifier qu'une nouvelle sélection est en cours, le sélectionExiste variable est faite vrai et la taille de la sélection est définie sur 0. Nous obtenons ensuite l’origine de la sélection en appelant notre fonction précédemment écrite., getMousePosition (), et passer sa valeur à la options.selectionPosition. Enfin, nous appelons le updateInterface () fonction de mise à jour de l'interface du plug-in en fonction des modifications apportées.


Étape 8. Redimensionner la sélection

Dans l'étape précédente, nous avons écrit une fonction permettant de définir une nouvelle sélection. Écrivons maintenant une fonction pour redimensionner cette sélection.

? // Redimensionne la fonction de sélection actuelle resizeSelection (event) // Empêche l'action par défaut de l'événement event.preventDefault (); // Empêche la notification de l'événement event.stopPropagation (); var mousePosition = getMousePosition (event); // Récupère la taille de la sélection options.selectionWidth = mousePosition [0] - selectionOrigin [0]; options.selectionHeight = mousePosition [1] - selectionOrigin [1]; si (options.selectionWidth < 0)  options.selectionWidth = Math.abs(options.selectionWidth); options.selectionPosition[0] = selectionOrigin[0] - options.selectionWidth;  else options.selectionPosition[0] = selectionOrigin[0]; if (options.selectionHeight < 0)  options.selectionHeight = Math.abs(options.selectionHeight); options.selectionPosition[1] = selectionOrigin[1] - options.selectionHeight;  else options.selectionPosition[1] = selectionOrigin[1]; // Update only the needed elements of the plug-in interface // by specifying the sender of the current call updateInterface('resizeSelection'); ; 

Pour redimensionner la sélection, nous devons récupérer la position actuelle de la souris. Comme la valeur renvoyée est relative à la taille de l'image, nous ne devons prendre en compte que les valeurs négatives. Il ne dépassera jamais les limites de l'image. Comme vous le savez, nous ne pouvons pas avoir une valeur négative pour le largeur ou la taille propriétés d'un élément. Pour résoudre ce problème, nous appelons Math.abs () pour obtenir la valeur absolue, puis nous repositionnons la sélection.


Étape 9. Libération de la sélection

Et maintenant la fonction finale:

? // Libère la fonction de sélection actuelle releaseSelection (event) // Empêche l'action par défaut de l'événement event.preventDefault (); // Empêche la notification de l'événement event.stopPropagation (); // Désassocie le gestionnaire d'événement à l'événement 'mousemove' $ (document) .unbind ('mousemove'); // Supprime le gestionnaire d'événements avec le 'mouseup' event $ (document) .unbind ('mouseup'); // met à jour la sélection origine selectionOrigin [0] = options.selectionPosition [0]; selectionOrigin [1] = options.selectionPosition [1]; // Vérifiez si la taille de la sélection est supérieure au minimum accepté // et définissez l'existence de la sélection en conséquence si (options.selectionWidth> options.minSelect [0] && options.selectionHeight> options.minSelect [1]) selectionExists = true; sinon selectionExists = false; // Met à jour uniquement les éléments nécessaires de l'interface du plug-in // en spécifiant l'expéditeur de l'appel en cours updateInterface ('releaseSelection'); ; 

Lorsque la sélection est validée, le releaseSelection () function supprime les gestionnaires d’événements précédemment attachés dans setSelection () fonction en appelant le .délier() méthode. Ensuite, il met à jour l'origine de la sélection et teste la taille minimale acceptée pour que la sélection existe.

Maintenant, nous sommes presque prêts. Fermez ce fichier et préparez-vous pour la prochaine étape.


Étape 10. Styliser le plug-in

Ouvrez le /resources/js/imageCrop/jquery.imagecrop.css feuille de style et ajoutez les lignes suivantes.

 div # image-recadrer-superposer background-color: #ffffff; débordement caché;  div # image-crop-outline background: #ffffff url ('outline.gif'); débordement caché; 

Il n'y a rien de compliqué ici; nous avons ajouté du style aux couches de superposition et de contour.


Étape 11. Test du résultat final

Pour tester notre plug-in, nous devons l'associer à une image. Faisons cela et éditer le index.html page.

Ouvrez le scénario étiquette?

  

? et écrivez le code JavaScript suivant.

 $ (document) .ready (function () $ ('img # example'). imageCrop (overlayOpacity: 0.25);); 

Nous avons attaché notre plug-in à l'élément image avec le Exemple id, et définir des options personnalisées. Nous avons utilisé le .prêt() méthode pour déterminer quand le DOM est complètement chargé.

Et c'est tout! Enregistrez le fichier et ouvrez votre navigateur pour le tester.


Et après

Nous disposons maintenant d’un plug-in de recadrage d’image de base qui nous permet de sélectionner une zone de l’image. Dans le prochain didacticiel, nous ajouterons davantage d'options de personnalisation, créerons un panneau de prévisualisation, créerons des scripts côté serveur pour rogner l'image? et beaucoup plus. J'espère que vous avez apprécié le temps passé ensemble et que vous avez trouvé ce tutoriel utile. Merci d'avoir lu!