Cet article fait partie d'une série de sur la construction d'un exemple d'application – un blog de galerie multi-images – pour l'analyse comparative des performances et les optimisations. (Voir le repo ici.)
 Nous avons construit un exemple d'application – un blog de galerie multi-images – pour l'analyse comparative des performances et les optimisations. À ce stade, notre application   diffuse la même image quelle que soit la résolution et la taille de l'écran dans laquelle elle est exposée. Dans ce tutoriel de redimensionnement d'image, nous allons le modifier pour servir une version redimensionnée en fonction de la taille d'affichage. 19659003] Objectif 
  Cette amélioration comporte deux étapes:   Comme  cet article  ] explique, les images dans le web moderne sont incroyablement complexes. Au lieu de juste   Une combinaison des tailles   Comme nos images sont des photos et que nous voulons toujours qu'elles soient dans leur position DOM spécifiée par défaut en remplissant le maximum de leur conteneur parent, nous n'avons pas besoin de   Le premier emplacement où l'on rencontre des images est   Passons à ceci:   Maintenant, toutes nos URL d'images auront 
 Responsive Images? 
 srcset   et   est nécessaire dans un scénario où vous doutez que si vous utilisez la même image pour une taille d'écran plus petite, le sujet principal de l'image peut devenir trop petit. Vous souhaitez afficher une image différente (plus centrée sur le sujet principal) dans une taille d'écran différente, mais vous voulez toujours afficher des éléments distincts de la même image en fonction du ratio pixel / périphérique, et souhaitez personnaliser la hauteur et la largeur de l'image  image  (ce qui nous permet définir une source alternative pour une résolution différente ou un support de navigateur – comme essayer de rendre SVG, puis PNG si SVG n'est pas supporté) ou  tailles  (ce qui nous permet de définir la portion de fenêtre qu'une image doit occuper). Nous pouvons sortir avec  srcset qui charge une version de taille différente de la même image en fonction de la taille de l'écran.  Ajout de srcset 
 ] home-galleries-lazy-load.html.twig le modèle partiel qui affiche la liste des galeries de l'écran d'accueil. 
   public function getImageUrl (Image $ image, $ size = null)
{
  return $ this-> router-> generate ('image.serve', [
      'id' => $image->getId() . (($size) ? '--' . $size : "http://www.sitepoint.com/"),
  ]RouterInterface :: ABSOLUTE_URL);
}
 - x  comme suffixe, où  x  est leur taille. C'est la modification que nous appliquerons à notre tag  img sous la forme de  srcset . Changeons le à: 
  
 Ça ne va pas Si notre fenêtre d'affichage est large, cela demandera des images en taille réelle, malgré le fait qu'elles soient des vignettes, donc au lieu de  srcset il est préférable d'utiliser une petite taille de vignette fixe ici: [19659025] {{gallery.name}} "
       class = "gallery__leading-image card-img-top ">
Nous avons maintenant des miniatures à la demande, mais qui sont mises en cache et récupérées lorsqu'elles sont déjà générées.
 Cherchons les autres  srcset  
 Dans  templates / gallery / single-gallery.html.twig nous appliquons le même correctif que précédemment.Nous avons affaire à des vignettes, alors rétrécissons le fichier en ajoutant la taille paramètre dans notre  getImageUrl  filtre: 
 Et maintenant pour l'implémentation  srcset enfin! 
Les différentes vues d'images sont rendues avec une fenêtre modale JavaScript en bas de la même vue de single-gallery:
 {% block javascripts %}
    {{ parent() }}
    
{% endblock%}
 Il y a un appel  append  qui ajoute l'élément  img  dans le corps du modal, donc c'est là que notre attribut  srcset  doit aller. Mais puisque nos URL d'image sont générées dynamiquement, nous ne pouvons pas vraiment appeler le filtre Twig depuis le script  . Une alternative consiste à ajouter le  srcset  dans les vignettes, puis l'utiliser dans le JS en le copiant à partir des éléments du pouce, mais cela ne ferait pas que charger les images en arrière-plan des vignettes ( parce que notre viewport est large), mais il appelle aussi le filtre 4 fois pour chaque vignette, ralentissant les choses. Au lieu de cela, créons un nouveau filtre Twig dans  src / Twig / ImageRendererExtension.php  qui générera l'attribut complet  srcset  pour chaque image. 
 public function getImageSrcset (Image $ image)
{
    $ id = $ image-> getId ();
    $ sizes = [1120, 720, 400];
    $ string = "http://www.sitepoint.com/";
    foreach ($ tailles comme taille $) {
        $ string. = $ this-> router-> generate ('image.serve', [
            'id' => $image->getId() . '--' . $size,
        ]RouterInterface :: ABSOLUTE_URL). "http://www.sitepoint.com/". $ size.'w, ';
    }
    $ string = trim ($ chaîne, ',');
    retourne html_entity_decode ($ string);
}
Il ne faut pas oublier d'enregistrer ce filtre:
 public function getFilters ()
{
    retour [
        new Twig_SimpleFilter('getImageUrl', [$this, 'getImageUrl']),
        nouveau Twig_SimpleFilter ('getImageSrcset', [$this, 'getImageSrcset']),
    ]
}
 Nous devons ajouter ces valeurs dans un attribut personnalisé, que nous appellerons  data-srcset  sur chaque vignette individuelle: 
  Chaque vignette individuelle possède maintenant un attribut  data-srcset  avec les valeurs  srcset  requises, mais cela ne se déclenche pas car il s'agit d'un attribut personnalisé, données à utiliser plus tard. 
 
La dernière étape consiste à mettre à jour le JS pour en tirer parti:
 {% block javascripts%}
    {{ parent() }}
    
{% endblock%}
Ajout de Glide
Glide est une librairie qui fait ce que l'on veut: un redimensionnement d'image à la demande. Installez-le.
 composer require league / glide
 Ensuite, enregistrons-le dans l'application. Nous faisons cela en ajoutant un nouveau service dans  src / Services  avec le contenu suivant: 
  server = $ server = Glide  ServerFactory :: create ([
            'source' => $fm->getUploadsDirectory(),
            'cache' => $fm->getUploadsDirectory().'/cache',
        ]);
    }
    fonction publique getGlide ()
    {
        return $ this-> serveur;
    }
}
 Le service consomme le service FileManager déjà déclaré qui est auto-injecté en raison de la nouvelle approche de câblage automatique de Symfony. Nous déclarons les chemins d'entrée et de sortie comme le  uploads  dir, donnons au répertoire de sortie un suffixe  cache  et ajoutons une méthode pour renvoyer le serveur. Le serveur est fondamentalement l'instance de Glide qui fait le redimensionnement et sert une image redimensionnée. 
 Nous devons rendre publique la méthode  getUploadsDirectory  dans  FileManager  public, comme elle est actuellement  ] private : 
 public function getUploadsDirectory ()
{
    return $ this-> path;
}
 Enfin, modifions la méthode  serveImageAction  de ImageController pour qu'elle ressemble à ceci: 
 / **
 * @Route ("/ image / {id} / raw", name = "image.serve")
 * /
function public serveImageAction (Demande $ request, $ id, GlideServer $ glide)
{
    $ idFragments = explode ('-', $ id);
    $ id = $ idFragments [0];
    $ size = $ idFragments [1]? nul;
    $ image = $ this-> em-> getRepository (Image :: classe) -> find ($ id);
    if (vide ($ image)) {
        throw new NotFoundHttpException ('Image non trouvée');
    }
    $ fullPath = $ this-> fileManager-> getFilePath ($ image-> getFilename ());
    if (taille $) {
        $ info = pathinfo ($ fullPath);
        $ file = $ info ['filename']. '.' . $ info ['extension'];
        $ newfile = $ info ['filename']. '-'. $ taille. '.' . $ info ['extension'];
        $ fullPathNew = str_replace ($ fichier, $ nouveau fichier, $ fullPath);
        if (file_exists ($ fullPath) &&! fichier_exists ($ fullPathNew)) {
            $ fullPath = $ fullPathNew;
            $ img = $ glide-> getGlide () -> getImageAsBase64 ($ fichier,
                ['w' => $size]);
            $ ifp = fopen ($ fullPath, 'wb');
            $ data = explode (',', $ img);
            fwrite ($ ifp, base64_decode ($ data [1]));
            fclose ($ ifp);
        }
    }
    $ response = new BinaryFileResponse ($ fullPath);
    $ response-> headers-> set ('Content-type',
        mime_content_type ($ fullPath));
    $ response-> headers-> set ('Content-Disposition',
        'attachement; filename = "http://www.sitepoint.com/". $ image-> getOriginalFilename (). "http://www.sitepoint.com/"; ');
    return $ response;
}
Cette méthode explose maintenant l'ID de l'image en double tiret, en séparant la taille de l'ID de l'image. Une fois que Doctrine récupère le chemin de fichier de l'image à partir de la base de données, la taille est attachée au nom de fichier si l'un d'eux a été transmis, sinon l'image d'origine est utilisée. Si cette image n'existe pas, elle est générée à partir du chemin d'origine et sauvegardée pour une utilisation ultérieure.
 À des fins de démonstration, nous allons ici plus loin et générons des fichiers manuellement en leur ajoutant la taille et en les sauvegardant dans le  télécharge le dossier . Il convient de noter que vous pouvez également utiliser la méthode  outputImage  de Glide pour sortir directement l'image, et qu'elle sera directement tirée du sous-dossier  cache sans l'enregistrer avec un suffixe dans le dossier principal  télécharger . Vous pouvez également utiliser la méthode  makeImage  pour créer l'image et laisser l'ancienne logique de récupération de l'image prendre le dessus. C'est l'approche que nous avons choisie ci-dessous: 
 / **
 * @Route ("/ image / {id} / raw", name = "image.serve")
 * /
function public serveImageAction (Demande $ request, $ id, GlideServer $ glide)
{
    $ idFragments = explode ('-', $ id);
    $ id = $ idFragments [0];
    $ size = $ idFragments [1]? nul;
    $ image = $ this-> em-> getRepository (Image :: classe) -> find ($ id);
    if (vide ($ image)) {
        throw new NotFoundHttpException ('Image non trouvée');
    }
    $ fullPath = $ this-> fileManager-> getFilePath ($ image-> getFilename ());
    if (taille $) {
        $ info = pathinfo ($ fullPath);
        $ file = $ info ['filename']. '.' . $ info ['extension'];
        $ cachePath = $ glide-> getGlide () -> makeImage ($ fichier, ['w' => $size]);
        $ fullPath = str_replace ($ fichier, '/ cache /'. $ cachePath, $ fullPath);
    }
    $ response = new BinaryFileResponse ($ fullPath);
    $ response-> headers-> set ('Content-type',
        mime_content_type ($ fullPath));
    $ response-> headers-> set ('Content-Disposition',
        'attachement; filename = "http://www.sitepoint.com/". $ image-> getOriginalFilename (). "http://www.sitepoint.com/"; ');
    return $ response;
}
Notre activité de redimensionnement d'image à la demande est opérationnelle. Tout ce que nous avons à faire est de tester les choses.
Test
 Dès que nous actualisons la page d'accueil, qui sera un peu plus lente, les images commenceront à être générées dans  var / uploads  ] dossier. Jetons un coup d'œil, sans faire défiler jusqu'à la deuxième page 
 
Effectivement, nous avons maintenant une minuscule version miniature de chaque image de la page d'accueil, et c'est l'image qui devient servi. Notez les petites tailles de fichier. Maintenant, accédons à une galerie et cliquons sur une image pour en obtenir une grande version
 
Oui, notre image a été générée à partir de l'original.
Qu'en est-il du mobile? Dans les navigateurs modernes, il est assez facile d'activer le mode mobile. Essayons d'ouvrir une image de la galerie en vue mobile et de vérifier le dossier de l'image par la suite.
 
Et si nous changeons d'orientation et vérifions le dossier?
 
 Succès, la taille mobile de notre image a été générée avec succès, et l'image en plein écran d'avant a été réutilisée car c'est la taille de notre écran «mobile» en mode paysage. À la demande  srcset  a été implémenté avec succès! 
L'application avec ces mises à niveau en place a été étiqueté comme cette version .
Conclusion
 Dans ce post, nous sommes allés à travers le processus d'optimisation des images pour la livraison dans un site photo-orienté. Nous avons gardé les vignettes à une taille fixe pour de meilleurs résultats, et avec des images en plein écran nous nous sommes concentrés sur l'implémentation de  srcset  - un ajout simple à tout site web moderne - en collaboration avec Glide, un package de redimensionnement d'image à la demande. 
Mais pendant que nous redimensionnons les images, ne serait-il pas intelligent de les optimiser automatiquement pour la qualité et la taille en supprimant les métadonnées? Et est-ce vraiment la meilleure option pour les redimensionner à la demande pendant que l'utilisateur attend ou y a-t-il une autre approche plus pratique? Découvrez dans la prochaine partie.
Source link
