/_plugins_/image_responsive – SPIP-ZONE

/image_responsive

  • Grosse nouveauté sur mon #plugin #SPIP image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    Le filtre image_responsive est désormais capable de fabriquer les versions WebP des images, en plus des versions usuelles. Ce qui fait que, si on visite le site avec un navigateur qui comprend WebP, ce sont les versions WebP des images que l’on charge, sinon les versions habituelles (JPEG en général). Et c’est tout automatique (autant pour le reste, le plugin est particulièrement utile si on fait des configurations précises avec une belle gestion des media queries, autant pour le WebP tout se fait tout seul…).

    Pour activer cela, il faut définir une nouvelle constante dans mes_options.php :

    define("_IMAGE_WEBP", true);

    Attention : en cas de mise à jour du plugin, il faut également modifier le .htaccess lié à image_responsive pour prendre en compte les nouveaux appels d’images.

    En gros, par rapport au Jpeg (qualité 80%) généré par SPIP, ça semble me générer des images deux fois plus légères.

    Attention : j’en suis aux premiers tests. Faudrait pas que ça te pète ton site…

    Notez qu’il faut que votre version de PHP soit capable de fabriquer des images en WebP. Ça me semble le cas désormais à peu près partout.

    Notez encore que ce n’est pas anecdotique : d’après CanIUse, le WebP est désormais affiché par 80% des navigateurs.

    • Mise à jour à l’instant (version 7.7.5) qui corrige le fait que, sur certains serveurs, les images WebP sont mal formées à cause d’un bug de PHP (nan mais vraiment, on est en 2019, et PHP continue à être livré avec des bugs grossiers dans les traitements d’images…) :
      https://bugs.php.net/bug.php?id=66590

      Si tu as eu des problèmes avec la version précédente, et que donc ton dossier de cache /local est pourri de fichiers WebP corrompus, voici un petit script pour faire le ménage (à la racine du site donc) :

      <?php

      function getDirContents($dir, &$results = array()){
         $files = scandir($dir);

         foreach($files as $key => $value){
             $path = realpath($dir.DIRECTORY_SEPARATOR.$value);
             if(!is_dir($path)) {
                 $results[] = $path;
             } else if($value != "." && $value != "..") {
                 getDirContents($path, $results);
                 $results[] = $path;
             }
         }

         return $results;
      }


      $liste = getDirContents("local/cache-responsive");

      foreach ($liste as $l) {
              if (preg_match("/webp$/", $l)) {
                      echo "<li>$l";
                      unlink($l);
              }
      }
    • Autre bug je pense : sur les serveurs qui déconnent (ci-dessus), je n’arrive pas, en plus, à fabriquer de WebP avec couche de transparence (c’est-à-dire en travaillant à partir de PNG transparent). Mais ça fonctionne sur un serveur qui n’a pas le bug précédent. (Pfff, vraiment… je veux dire : personne n’a testé la fonctionnalité de base quand ils l’ont implémentée complètement buguée ?).

    • M’enfin sinon, sur un serveur en PHP 7, ça fonctionne très bien, j’ai désormais plusieurs sites qui tournent avec. Avec un serveur PHP 5, ça tourne aussi très bien, à l’exception des PNG semi-transparents qu’on passerait par image_responsive (c’est pas le plus fréquent).

  • Mise à jour importante sur mon #plugin #SPIP image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    – il y avait un bug sur le choix des images hors media-queries, avec risque de ne pas respecter le choix de tailles prédéterminés (et donc de fabriquer beaucoup trop d’images en cache)
    – surtout : je viens (enfin) d’ajouter le timestamp aux adresses des fichiers, ce qui devrait résoudre pas mal des problèmes de cache rencontrés par les utilisateurs.

    • Bonjour
      Je cherche à comprendre pourquoi (et surtout si c’est normal) avec background_responsive il y a dans le code html de la page 4 appels d’images (avec 1 px de différence) pour chaque taille (je comprends pour 1 et 2 mais pas i et p).
      EX :
      \"960\" :{\"i\" :{\"1\" :\"local\\/cache-responsive\\/cache-960\\/d32c7d34962d8ea6f4fa0a9b008cdf7c.jpg ?1529623009\",\"2\" :\"local\\/cache-responsive\\/cache-960\\/d32c7d34962d8ea6f4fa0a9b008cdf7cd32c7d34962d8ea6f4fa0a9b008cdf7c-2.jpg ?1529623010\"},\"p\" :{\"1\" :\"local\\/cache-responsive\\/cache-960\\/5e9c6d2f4211f48525892e5f9f166dc6.jpg ?1529623011\",\"2\" :\"local\\/cache-responsive\\/cache-960\\/5e9c6d2f4211f48525892e5f9f166dc65e9c6d2f4211f48525892e5f9f166dc6-2.jpg ?1529623012\"}

      Merci

  • J’ai ajouté un gros paragraphe consacré à « Image adaptative, recadrage et direction artistique » dans ma documentation du #plugin #SPIP image_responsive :
    http://www.paris-beyrouth.org/Plugin-SPIP-Image-responsive

    Ça explique les critères de recadrage que l’on peut utiliser directement dans le filtre image_responsive, comme ceci :

    [(#LOGO_ARTICLE_NORMAL|image_responsive{
            0/480/800/1280/1920/480/800/1280/1920,
            0, 0,
            (max-width: 480px) and (orientation:portrait)/(min-width:481px) and (max-width: 800px) and (orientation:portrait)/(min-width:801px) and (max-width:1280px) and (orientation:portrait)/(min-width:1281px) and (orientation:portrait)/
            (max-width: 480px)/(min-width:481px) and (max-width: 800px)/(min-width:801px) and (max-width:1280px)/,
            4x5/4x5/4x5/4x5/3x2/3x2/3x2/3x2
            })]

    (lequel code fabrique une bonne grosse balise picture en HTML5, extrêmement efficace au niveau de l’affichage, puisque l’image est préchargée, et l’affichage est instantané quand on revient sur une page déjà affichée).

    Pour le plugin lui-même :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

  • Pas mal de boulot pour faire évoluer Flip-Zone (#SPIP, #HTML5, #responsive…) :
    http://www.flip-zone.com

    Le premier but est de faire une page d’accueil avec un immense image, façon « plein écran » (particulièrement spectaculaire sur une grande tablette…) :

    Il y a plusieurs aspects techniques intéressants, ici.

    (1) D’abord ce n’est pas réellement plein écran, comme j’ai pu le faire sur certains sites : c’est simplement qu’il y a deux proportions d’images. Une version horizontale si l’écran est horizontal, et une version verticale si l’écran est vertical.

    Quand j’essaie de réellement « remplir » l’écran lui-même, il y a plusieurs problèmes :
    A. Ça me fait des maquettes aux proportions aberrantes, avec ces gens sur PC aux écrans très horizontaux, la barre de menu au dessus, et des saloperies qui font qu’au final, on doit calculer une maquette en 1365x300 pixels…
    B. Techniquement, l’image qui s’affiche là-dedans à des dimensions inconnues, et donc je ne peux pas choisir l’image par feuille de style, mais en attendant que Javascript démarre après le rendu du DOM. Donc pas de <picture>, ce qui est très problématique désormais.

    Du coup, cette version propose différentes tailles d’images, de résolutions (écran Retina), et de proportions (horizontal, vertical) en fonction sur support, et dont les dimensions sont directement connues avant même l’affichage de la page ; donc accessibles en CSS et media queries, donc nativement avec la balise <picture>. La grande image de Une est donc directement gérée par une seule balise dans un gros <picture>. C’est donc fait avec mon #plugin Image responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    La grosse particularité de cette page, c’est d’avoir un effet de profondeur, avec le mannequin qui se « détache » du fond, avec en dessous le logo Flip-Zone qui apparaît. Certes j’ai bien un PNG dans l’espace privé avec le mannequin détouré, mais ce n’est surtout pas ce que j’affiche sur le site public (avec des images de cette taille, un tel PNG ferait un fichier monstrueux). Ce que j’affiche, c’est exactement le JPEG déjà utilisé « en dessous », mais avec un masque de détourage qui est une image en niveaux de gris (calculée rapidement en PHP à partir de la couche alpha du fichier PNG). Et pour réussir à afficher une image JPEG avec un masque de détourage dans le HTML, je fais un petit montage en SVG. (De fait, au lieu d’utiliser un JPEG de fond plus un gros PNG par dessus, j’utilise le JPEG de fond, je réutilise le même fichier JPEG par dessus, en le détourant avec un JPEG en niveaux de gris de taille réduite.)

    Ce qui amène à une autre difficulté : il faut que cette <image> dans le SVG soit elle-même responsive (la même que le <picture> de l’image de fond), ce qui n’est pas possible directement (même avec des CSS, je n’ai pas réussi à contrôler l’image qui s’affiche à cet endroit). Solution : je fais le <image> du SVG avec rien.gif et j’y insère en Javascript le résultat de ce qui s’affiche dans le <picture>. De cette façon c’est la <picture> nativement responsive qui gère le choix du bon fichier. J’ai abordé ça ici :
    http://seenthis.net/messages/479467
    Et la méthode pour aller chercher le currentSrc de l’image responsive :
    http://seenthis.net/messages/470853

    Même topo, en fait, pour l’image du masque de détourage en niveau de gris, c’est récupéré d’un <picture> (que je cache). Astuce ici : l’image du masque est deux fois plus petite que l’image affichée, parce que je n’ai pas besoin d’être ultra-précis à cet endroit.

    Et la dernière difficulté avec ce SVG, c’est que je ne peux pas changer dynamiquement ses proportions (fixées par la viewBox). Solution pour l’instant : il y a deux SVG dans la page à cet endroit : une avec les proportions horizontales et une avec les proportions verticales, et leur affichage est contrôlé par média queries. En dehors du « texte » des balises du SVG surnuméraire, ça ne pèse pas plus lourd, puisque de toute façon c’est le même contenu (tiré des <picture> ailleurs dans la page) qui y est inséré dynamiquement), la seule différence étant la viewBox « en dur » des deux SVG…

    (2) Auparavant l’aspect responsive des menus supérieurs était géré de deux façons :
    – sur un écran pas trop étroit (petite tablette), les derniers éléments à droite (ceux qui « dépassent » de l’écran) étaient placés dans un petit menu déroulant ;
    – sur tout petit écran, remplacement par un menu hamburger et une navigation « cachée » dans un slider à gauche de l’écran.

    C’est désormais remplacé par un menu horizontal qui dépasse (si nécessaire) de l’écran, et qu’on peut scroller automatiquement horizontalement. On verra bien si c’est efficace.

    Ah, un gain notable : comme je n’ai plus de gestion d’un menu « hors page » avec décalage complet de la page « vers la gauche », je n’ai plus besoin de placer toute la partie scrollable de la page dans un élément spécifique (en scroll:auto) alors que le body n’était plus scrollable. Mine de rien, ça provoquait parfois des bugs d’affichage lors du scroll (notamment sur pages longues, notamment sur Safari). Là je reviens à un très traditionnel scroll sur le <body> de la page, et je n’ai plus ces bugs bizarres au scroll.

    (3) Dans la précédente version de la page d’accueil, le but était d’avoir une page très courte. Mais ça ne semble plus trop la mode (les magazines font des pages d’accueil à scroll quasi-infini), et surtout parce qu’on veut mettre en avant le fait qu’il y a des articles désormais (en anglais essentiellement), le choix est désormais inverse, avec une page très longue.

    En revanche, calculs amusants (dans les boucles SPIP) pour alterner les articles (un article de temps en temps) et les collections de photos (parfois plusieurs par jour). Et essayer de conserver une certaine construction logique pour les photos (par Couture/Prêt à porter/Mariage…, et par saisons…).

    Pour le poids, une possibilité était de charger la longue page (sous la grande image) en "ajaxload" (on charge la page avec juste le haut, et dans un deuxième temps on lance le chargement du bas de page). En pratique ça donne des résultats très désagréables, notamment quand on fait « back » vers la page d’accueil (on perd le positionnement dans la longue page). De la même façon, mon plugin d’images responsives permet de les gérer en lazy load, mais ça ne me semble plus utile : ça bloque le preloader et ça fait un effet désagréable quand on revient sur la page déjà en cache.

    En pratique, j’ai l’impression que les navigateurs récents se débrouillent très bien tous seuls pour gérer les chargements et la mémoire si on utilise directement la balise <picture>.

    Faudra voir à l’usage.

    (4) La construction de la liste essaie de grouper les collections de photos de manière logique, notamment par saisons (genre : « Printemps-été Automne-hiver 2016-2017 ») :

    Cette partie a un peu les mêmes principes que le haut de page : effet de « transparence » sur une partie détourée d’une image, géré via un morceau de SVG qui évite de balancer un PNG ; et slider horizontal automatique pour le responsive.

    Ah, je n’ai pas évoqué comment faire des liens qui s’affichent « en dessous », mais tout de même cliquables (et qui apparaissent au survol ou au clic). Et ça se gère directement en CSS sans Javascript. C’est un vieux truc que j’utilise depuis longtemps : il y a en réalité deux fois le même contenu, parfaitement superposés (par exemple l’ensemble des vignettes, ou le menu de navigation supérieur…). Et la version du dessus est masquée, et n’apparaît qu’au survol (ou au clic). L’« astuce » importante est que l’élément est masqué uniquement en avec opacity:0, et devient visible avec opacity:1 ; si on jour avec display, ça ne fonctionne plus correctement en tactile, puisque le premier clic sera intercepté pour faire le changement d’affichage (alors que le changement d’opacité se fait sans désactiver le touch).

    (4) Des petits effets de pseudo 3D :


    Au survol de certains éléments (les liens vers les vidéos), il y a un effet de surgissement 3D avec une petite animation. Ce qui est marrant, c’est qu’il n’y a rigoureusement aucun Javascript pour gérer ça, c’est purement CSS.

    J’aurais pu systématiser ces effets, mais ça oblige tout de même à recourir à mon « truc » de masque de détourage en SVG, un peu lourd, puisqu’il faut tout de même une seconde image (le masque en niveau de gris) pour chaque. Et puis graphiquement ça aurait un peu tourné au cirque, et j’essayais plutôt d’introduire de la variété dans cette longue liste.

    (5) Ça devrait fonctionner presque entièrement sans Javascript et directement au chargement de la page en CSS, y compris les diverses petites animations de survol. Avec les progrès des navigateurs, à l’affichage ultra-fluide, les pré-loaders, etc., c’est devenu très important d’avoir la page entièrement construite dès le premier affichage, sans calculs Javascript. L’effet de « fluidité » est vraiment important. (Tu me diras que ça a toujours été important, mais a. on ne pouvait pas toujours faire autrement, b. les progrès de fluidité d’affichage des navigateurs rendent les pages « pas très fluides » vraiment perceptibles).

    (6) Un peu partout (notamment en énorme sur le haut de page), j’ai le logo Flip-Zone qui apparaît et qui change de couleur en fonction de l’environnement. Auparavant je faisais autant de fichiers graphiques (PNG) que nécessaire. Maintenant c’est du SVG directement intégré dans le DOM, et colorisé par feuille de style. C’est une astuce que j’utilise de plus en plus fréquemment (ça permet notamment de changer la couleur d’une icone non seulement en fonction du contexte, mais tout bêtement au survol d’un lien hypertexte).

    (7) Sinon, ce n’est pas totalement nouveau, mais les pages des « articles longs » sont pas mal (encore une fois, c’est du SPIP), notamment avec ses images installées sur une même ligne, plus large que la colonne de texte, et positionnées de manière responsive :
    http://www.flip-zone.com/Caftan-silhouettes
    Celle-ci est plus marrante, parce que l’effet de « lignes » fonctionne avec un mélange d’images et de vidéos, et l’image finale en fond d’écran (tout en bas de page) :
    http://www.flip-zone.com/Nicolas-Jebran-5957

  • Important pour les amateurs de #HTML5 : avec les récentes mises à jour iOS 9.3 et OSX 10.11.4, les nouvelles versions de Safari comprennent enfin la balise <picture> qui permet de gérer des images #responsive (c’est-à-dire qu’on ne charge pas la même image selon les dimensions ou l’orientation de l’écran).

    C’est important parce que c’est le dernier gros navigateur à adopter cette balise, et c’est d’autant plus important, c’est que si on s’enquiquine à faire des images adaptées à l’affichage sur smartphone, évidement Safari pour iOS est l’un des principaux concernés.

    Et pour rappel, pour gérer ça automatiquement dans #SPIP, j’ai mon chouette plugin image responsive :
    http://seenthis.net/sites/328805
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

  • Nouvelle fonction rigolote dans mon #plugin #SPIP image_responsive 7.0 :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    Il y a désormais un filtre image_responsive_svg (qui fonctionne en gros comme image_responsive, avec pour l’instant seulement les variables $img, $tailles, $lazy et $vertical.

    Le but est de résoudre mon souci avec l’utilisation des images JPG à l’intérieur d’un <svg> : là les images sont appelées avec :

    <image xlink:href>

    au lieu de l’habituel <img src> du HTML.

    Importantes différences cependant avec le filtre image_responsive :
    – on ne peut pas définir de mediaqueries pour chaque dimension, parce que je n’ai pas (encore ?) trouvé de méthode pour afficher directement les bons fichiers via des CSS (et encore moins, évidemment, une balaise <picture>) ; c’est le point qui m’embête le plus ;
    – on ne peut pas définir des redimensionnement spécifiques pour chaque taille d’image, parce que j’ai l’impression qu’il est difficile changer les proportions d’un SVG.

    (Bon, et pis franchement franchement : je crois que je vais la seule personne sur la planète à utiliser cette fonction, alors bon…)

  • Nouveauté dans mon #plugin #SPIP image_responsive (version 6.6.0) :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    Le filtre background_responsive accepte une troisième variable, $align (top, bottom, left, right) pour forcer le centrage de l’image ; avec la valeur focus, le plugin effectue le recadrage et le positionnement en fonction du « centre d’intérêt de l’image » déterminé par le plugin « centre_image ».

    Exemple d’utilisation :

    [(#LOGO_ARTICLE_NORMAL|background_responsive{480/800/1280/1920, 0, focus})]
  • Modif du filtre #SPIP |image_proportions, pour améliorer le comportement lié aux plugins image_responsive et centre_image (la modif est dans le #plugin image_responsive) :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/centre_image

    Dans la version précédente, on pouvait recadrer et zoomer dans une image en fonction du centre d’intérêt de l’image (détectée automatiquement ou corrigée manuellement dans l’espace privé). À l’usage, je me suis rendu compte que du coup, le centre d’intérêt qui est rarement au centre de l’image, se retrouvait au centre de l’image retaillée. Par exemple, si on a un portrait, le centre d’intérêt est entre les yeux ; si on recadre/zoome, on se retrouve avec les yeux au centre de l’image, du vide au-dessus des cheveux et le menton coupé.

    Le comportement dorénavant, avec le critère focus, est plus malin : si les yeux du portrait sont par exemple dans le tiers haut de l’image d’origine, avec le recadrage ils seront encore dans le tiers haut de l’image résultante (c’est l’idée, mais c’est pondéré sinon c’est exagéré). L’effet est bien meilleur, et les images plus dynamiques.

    Si on veut recadrer avec le comportement précédent, il faut utiliser le critère focus-center.

    Voici une boucle pour tester avec les images d’un article :

    <BOUCLE_documents(DOCUMENTS){0,10}{par hasard}{id_article}>
            [(#FICHIER|image_proportions{1,1,focus,2}|image_reduire{200})]
            [(#FICHIER|image_proportions{1,1,focus-center,2}|image_reduire{200})]
    </BOUCLE_documents>

    Et une copie d’écran :

    On voit que les portraits avec le nouveau réglage (image de gauche de chaque paire) sont plus dynamiques et plus « naturels » que le recadrage avec le script précédent (image de droite, avec le nouveau critère focus-center).

    • Bonjour
      Je viens d’avoir un comportement étrange avec le filtre image_proportions (peut être aussi que je l’utilise mal :
      [(#FICHIER|image_proportions{16,9}
      |image_responsive{360/480/600/800}
      |inserer_attribut{alt,[(#_contenu_article:TITRE|attribut_html|couper{80})]})]
      Contexte : utilisation dans un formulaire d’upload, tout se passe bien avec des images avec largeur inférieure à 3600px. De 3700 à 4000, la page article est vide. Au delà de 4000px, page blanche.
      J’ai fais beaucoup de tests (largeur/poids) et ce n’est pas une question de poids.
      Quand erreur, le fichier error_log : [29-Dec-2015 17:38:22 America/New_York] PHP Fatal error : Allowed memory size of 125829120 bytes exhausted (tried to allocate 30798801 bytes) in /home/gwadloup/public_html/plugins-dist/filtres_images/filtres/images_transforme.php on line 301

      Quand j’enlève image_proportions{16,9}, tout fonctionne bien.
      J’utilise aussi le plugin géodiversité.

      Bonne année
      Cécile

    • comme suggéré sur irc, tu peux appliquer un filtre |image_reduire{1500} avant ce filtre-ci ; c’est moins gourmand en mémoire que image_proportions, donc ça devrait passer (et visiblement ça passe).

  • Seenthis, j’ai une question (avec application à #SPIP). Est-ce qu’il existe une méthode recommandée pour indiquer, dans le code HTML, les ressources liées à la page, sans pour autant entraîner le navigateur ou le preloadeur à charger des ressources inutiles ?

    Le besoin auquel je veux répondre, c’est la possibilité d’aspirer/dupliquer un site Web sans avoir des fichiers qui manquent une fois hors ligne. En effet, j’ai régulièrement des ressources chargées dynamiquement (ne serait-ce que mes images responsive), qui ne sont pas récupérées de manière transparente par une aspiration de la page.

    Pour l’instant, je m’en sors « à la main » en ajoutant des :

    <link href… rel="a_telecharger">

    dans mes pages. Ça permet de récupérer tout ce dont j’aurai besoin hors-ligne (ou potentiellement besoin, puisque je suis en responsive, avec souvent des éléments chargés ou non).

    Mais je n’ai pas systématisé ça sur mes sites en production (et notamment pas dans les plugins qui génèrent ces pages), parce que je ne veux pas que Google m’aspire des fichiers que je ne veux pas « fabriquer » ou « utiliser » rien que pour lui (par exemple, les images responsive jamais utilisées, je préfère qu’elles ne soient pas générées pour rien), parce que je ne veux pas que navigateurs les chargent (ni les pré-chargent) alors qu’ils ne vont pas les utiliser…

    Et en gros, s’il y a une méthode connue et/ou recommandée, voir à quel point c’est une pratique à documenter/généraliser dans SPIP, pour avoir des sites qu’on peut aspirer/sauvegarder/dupliquer en statique à coup sûr.

    Note : si on va par là (et j’aimerais bien que ce soit au moins une option), il y a aussi les problèmes de noms de fichiers. Il faut que certains plugins fonctionnent systématiquement en URL « .html », et pas en interminables variables PHP (par exemple, j’utilise des choses comme {ajaxload=html}), et/ou éviter d’ajouter la date à la fin des fichiers (CSS/logos) parce que ça me pète mon aspiration…

    • Autre question liée, est-ce que je peux mettre un <link> à l’intérieur d’un <a>, du genre :

      <a href="truc.html">Le contenu usuel du lien
          <link href="maressource.jpg" rel="resource"
      </a>

      Parce que dans de nombreux cas, la fonction qui fabrique les ressources (et donc les potentiels <link> à ajouter pour les aspirer) ne sait pas si ce qu’elle va produire se trouve à l’intérieur d’une ancre (je pense évidemment aux images responsive, dont le fonctionnement est totalement indifférent au fait d’être à l’intérieur d’un lien hypertexte).

    • Bon, je me lance avec une mise à jour assez conséquence de mon #plugin #SPIP image_responsive :
      http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

      On peut activer un define dans mes_options.php :

      define("_SPIP_LIER_RESSOURCES", true);

      (noter le choix d’un nom lié à SPIP et non au plugin, histoire de le réutiliser).

      Avec cette option, le plugin ajoute au code HTML généré une ribambelle de liens (qui n’affichent rien) de cette forme :

      <link href="truc.jpg" rel="attachment" property="url">

      (je suppose qu’on peut trouver mieux, mais comme pas trop de réponses à la question ci-dessus… et au moins avec ça le validateur-go-home arrête de m’engueuler).

      De cette façon, quand on aspire la page, on aspire aussi toutes les ressources qui seront nécessaire pour travailler en local.

      Avec image_responsive, évidemment, ça ne peut fonctionner que quand on définit une ou plusieurs tailles autorisées (ce qui est de toute façon un bon principe à la base).

  • Introduction d’un système de précalcul dans mon #plugin #SPIP image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    On peut ajouter dans mes_options.php :

    define("_IMAGE_RESPONSIVE_CALCULER", true);

    Dans ce cas, à chaque fois qu’on a utilisé image_responsive en indiquant des tailles prédéterminées, le plugin va fabriquer les images responsive précalculées en /local/cache-responsive. Depuis le début, le plugin ne précalcule pas les images, mais se contente de retourner vers un script /action/image_responsive.php qui fabrique/cache/sert les images à la volée.

    Avantage du pré-calcul :
    – si utilisé sur tout le site, on pourra décider de désactiver le script action, et ainsi éviter de se faire remplir le cache local par un crawler qui déciderait de demander toutes les tailles (de 1 à 1000 par exemple) de toutes les images du site…
    – le gros avantage immédiat c’est de servir des fichiers image directement depuis Apache, et non plus des scripts PHP qui expédient des images ; je pense que ça allège le serveur, et que c’est sans doute plus rapide si on n’est pas derrière Varnish – mais j’ignore absolument dans quelles proportions.

    Inconvénients du pré-calcul :
    – toutes les tailles autorisées d’image sont immédiatement fabriquées ; une fois que toutes les pages du site sont calculées, on atteint illico la taille max utilisée par les images responsive (sans le pré-calcul, seules les images réellement réclamées par des visiteurs sont fabriquées). Sur un gros site avec beaucoup d’images, cette taille est potentiellement phénoménale…
    – les pages du site sont beaucoup plus lourdes à calculer la première fois, puisqu’il faut précalculer toutes les tailles de toutes les images (principe des filtres graphiques). Sur un site très graphique, ça peut être très important.

  • Je continue avec mon #plugin #SPIP image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    Dans la variable des proportions d’image, il est désormais possible d’utiliser des valeurs en pourcentage. Par exemple : 71%x0 va recadrer l’image à 71% de sa largeur, en conservant sa hauteur.

    |image_responsive{
            588/840/1280/1920,
            0,
            0,
            (max-width: 420px)/(min-width:421px) and (max-width: 700px)/(min-width:701px) and (max-width:1280px)/,
            71%x0/83%x0/0x0/0x0
    }
  • Grosse améliation de mon #plugin #SPIP image_responsive : il intègre désormais la gestion de la direction artistique, avec prise en compte (si l’on a envie) du centre d’intérêt automatique de l’image (avec le plugin centre_image :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    Il y a maintenant une variable supplémentaire (optionnelle), qui doit d’utiliser avec les valeurs de mediaqueries de la variable précédente. Par exemple :

    [(#FICHIER|image_responsive{
            600/800/1400,
            0,
            0,
            /(min-width:801px) and (max-width:1000px)/(min-width: 1001px),
            1x1xfocusx2 / 3x4xtop / 4x2
    })]

    Ici on a donc :
    – soit une image de 600 pixels de large, 800 pixels de large ou 1400 pixels de large
    – pas de lazyload (0)
    – pas d’alignement vertical (0)
    – l’image de 800 est utilisée pour les écrans de 801 à 1000 pixels de large, l’image de 1400 pixels pour les écrans de plus de 1001 pixels (OK, c’est pas dément comme choix…)

    La nouvelle variable contient 3 valeurs séparées par des / (avec ou sans espaces), qui correspondent aux valeurs de mediaqueries précédentes. Chaque valeur est de ce type :
    largeurxhauteurxalignementxzoom

    Les valeurs alignement et zoom sont optionnelles. Ces quatre valeurs correspondent aux variables de la fonction image_proportions :

    Du coup :
    – 1x1xfocusx2, image retaillée au carré (1x1), avec centrage sur le point d’intérêt (focus), et zoom de valeur 2 ; utilisé par défaut ;
    – 3x4xtop, image taillée en quatre tiers verticalement, découpe sur le haut de l’aime, et pas de zoom ; utilisé pour les écrans de 801 à 1000 pixels ;
    – 4x2, image deux fois plus large que haute, recadrage au centre par défaut, pas de zoom ; utilisé pour les écrans de plus de 1001 pixels de large.

    Par ailleurs, ici on a indiqué 3 valeurs correspondant aux 3 media queries. Mais on peut aussi n’utiliser qu’une seule valeur de recadrage, qui sera alors systématiquement utilisée pour toutes les tailles (et cela fonctionnera aussi, dans cas, même si on n’utilise pas les mediaqueries).

    Plusieurs intérêts :
    – pouvoir utiliser des formats d’images différents selon les tailles d’affichage, et/ou orientations d’écran,
    – affiner ces recadrage en utilisant le centre d’intérêt automatique de l’image,
    – pouvoir zoomer dans l’image selon la taille d’affichage, éventuellement en centrant sur le point d’intérêt de l’image.

  • Évolutions de mon #plugin #SPIP image_responsive
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    – v5.1 : transparent pour l’utilisateur (sauf bug…), lorsqu’on utilise les fonctionnalités avancées qui fabriquent un srcset ou des <picture><source>, ce n’est plus mon javascript perso qui va gérer les remplacements d’images, mais le polyfill picturefill.js, plus puissant. (C’est en préparation à l’automatisation de l’ajout de la « direction artistique », qui demandera à utiliser les <source> au lieu d’un simple remplacement d’image proportionnelle ;

    – v5.2 : ça devient carrément marrant : ajout d’une quatrième variable à image_proportions, qui indique un niveau de zoom. Par exemple :

    [(#FICHIER|image_proportions{200,200,focus,2})]

    si cette valeur (ici : 2) est supérieure à 1 (en pratique : 1.2, 1.5…), alors le recadrage se fera en zoomant à l’intérieur de l’image. Si on a indiqué comme ici « focus », alors on zoome vers le centre d’intérêt de l’image
    (on n’est pas obligé de faire ça sur « focus », ça fonctionne aussi avec les autres types de recadrage).

    • Pour tester :

      <html>
      <body>

      <BOUCLE_documents(DOCUMENTS){0,10}{par hasard}{inverse}{extension=jpg}>
      <div>
              <div style="position: relative; display: inline-block;">
              [(#FICHIER|image_reduire{200})]
             
                      <div style="position: absolute; margin-left: -7px; margin-top: -7px; left: [(#FICHIER|centre_image_x|mult{100})]%; top: [(#FICHIER|centre_image_y|mult{100})]%">
                      <img src="[(#CHEMIN{imgs/croix.png})]">
                      </div>
             
              </div>
              [(#FICHIER|image_proportions{0,0,focus,2}|image_reduire{200})]
              [(#FICHIER|image_proportions{200,200,focus,2}|image_reduire{200})]
              [(#FICHIER|image_proportions{200,200,center, 2}|image_reduire{200})]
      </div>
      </BOUCLE_documents>

      </body>
      </html>
    • (Il faut donc maintenant que j’intègre tout ça directement dans la fonction |image_responsive. Ensuite il faudra bien qu’on ait une fonction pour corriger les centres d’intérêt des images, parce qu’avec le zoom, les erreurs deviennent bien plus pénibles.)

  • Tu n’auras plus d’excuse pour ne pas l’utiliser : je viens de pondre une (énorme) documentation pour mon #plugin #SPIP image_responsive :
    http://www.paris-beyrouth.org/tutoriaux-spip/article/plugin-spip-image-responsive

    Plugin que tu trouveras là :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive
    et dans tous les bons repositories de plugins SPIP :
    http://plugins.spip.net/image_responsive.html

  • Super amélioration de mon #plugin pour #SPIP, image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    Cette fois, j’introduis la possibilité de fabriquer le code <picture><source> complet pour complètement gérer les images responsive nativement (pour l’instant, dans Chrome).

    L’idée, c’est l’introduction d’un quatrième paramètre dans ma fonction, ce qui permet de définir les media queries correspondant à chaque taille d’image.

    Par exemple :

    [(#LOGO_ARTICLE_NORMAL
            |image_responsive{
                    0/50/100/200,
                    0,
                    0,
                    (max-width:470px)/(max-width:1009px)/
            }
    )]

    La première variable (0/50/100/200) est la liste des tailles d’images autorisées :
    – 0 n’est pas une taille d’image, ça signifie simplement qu’au chargement de la page, le <img> se fera sur rien.gif
    – ensuite on autorise des images de 50 pixels, 100 pixels, 200 pixels (donc trois tailles).

    Si on n’indique rien d’autre, on a le fonctionnement habituel du plugin : une fois la page chargée, un javascript calcule la taille de l’endroit qui contient cette image, et en fonction va appeler l’image à la bonne taille (et éventuellement en haute définition si écran haute déf.)

    La seconde variable permettrait de forcer le chargement en « lazy load ». Comme la valeur est zéro (par défaut), ce mode est désactivé. Si on avait forcé la valeur à 1, alors l’image ne serait chargée que si elle visible à l’écran (ou bientôt visible en scrollant). Ça permet, si on a envie, de ne pas charger des images qui seraient bien plus loin en bas de page. Ici, il est important de laisser à zéro, parce qu’on veut un code complet qui se charge dès avant le lancement de la page (voir en préchargement).

    La troisième variable est à zéro (par défaut). Si on met à un, alors on indique qu’on veut que les calculs se fassent sur la hauteur du conteneur, et non sur la largeur. Ici il faut laisser à zéro, je n’ai pas encore adapté mon code pour qu’il fonctionne avec les images alignées verticalement.

    La quatrième variable est la nouvelle : si on décide de l’utiliser, alors on va permettre au plugin de fabriquer le code complet qui fait fonctionner les images responsive directement en HTML5. C’est alors bien plus rapide à l’affichage, et le pré-chargement fonctionne sur ces images.

    Le code généré est le suivant :

    <picture style='padding:0;padding-bottom:63.5593220339%' class='conteneur_image_responsive_h'>
            <source media='(max-width:470px)'
                    srcset='
                            index.php?action=image_responsive&amp;img=IMG/arton5.jpg&amp;taille=50 1x,
                            index.php?action=image_responsive&amp;img=IMG/arton5.jpg&amp;taille=50&amp;dpr=2 2x
                    '>
            <source media='(max-width:1009px)'
                    srcset='
                            index.php?action=image_responsive&amp;img=IMG/arton5.jpg&amp;taille=100 1x,
                            index.php?action=image_responsive&amp;img=IMG/arton5.jpg&amp;taille=100&amp;dpr=2 2x
                    '>
            <source
                    srcset='
                            index.php?action=image_responsive&amp;img=IMG/arton5.jpg&amp;taille=200 1x,
                            index.php?action=image_responsive&amp;img=IMG/arton5.jpg&amp;taille=200&amp;dpr=2 2x
                    '>
            <img class='image_responsive' alt="" src='https://seenthis.net/rien.gif' data-src='IMG/arton5.jpg' data-l='2832' data-h='1800' data-tailles='[\&#034;50\&#034;,\&#034;100\&#034;,\&#034;200\&#034;]' />
    </picture>

    Le principe de cette variable est de contenir autant de mediaqueries qu’il y a de tailles autorisées dans la première variable, en les séparant par des slash (comme pour les tailles de la première variable). Pour rappel : le 0 ne compte pas comme une taille autorisée.

    Ici, on avait les tailles autorisées : 0/50/100/200. On a donc trois tailles autorisées. Dans les medias queries, il nous faut donc définir trois valeurs correspondant à ces tailles d’images autorisées :
    (max-width:470px)/(max-width:1009px)/

    Ce qui signifie :
    – utiliser l’image de largeur 50 dans le cas (max-width:470px)
    – utiliser celle de largeur 100 dans le cas (max-width:1009px)
    – utiliser l’image de largeur 200 dans les autres cas (par défaut donc).

    Noter le slash final, qui permet de voir qu’il y a bien une troisième valeur attendue (valeur vide).

    Le plugin fabrique donc les <source> correspondant à ces tailles, en indiquant à chaque fois l’image en définition 1x et l’image en haut définition (2x).

    Sur les navigateurs qui comprennent ça (Chrome), ça fonctionne très bien : les images sont chargées bien plus rapidement (puisqu’on n’attend plus le chargement de la page, des JS et des CSS avant de lancer le chargement des images), et le preloader est censé prendre en compte ces informations. (Et si on désactive Javascript : ça fonctionne parfaitement sur ces navigateurs…)

    Actuellement caniuse.com donne 40% des visiteurs compatibles (essentiellement : Chrome – donc c’est déjà pas rien) mais la prochaine version de Firefox va l’avoir, et vu que c’est Chrome c’est webkit, je ne vois pas pourquoi Safari traînerait encore longtemps. De toute façon, c’est un enrichissement progressif : si le navigateur ne pige pas, le plugin fonctionnera comme auparavant uniquement en Javascript. (Dommage quand même que ça ne fonctionne pas sur Safari mobile, quand même.)

  • Nouvelle version (4.0) de mon #plugin pour #SPIP, image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    Cette fois, je viens d’introduire un srcset dans l’image.

    Attention, pour l’instant, ça n’est pris en compte que si on n’a indiqué qu’une seule dimension pour l’image, par exemple :

    [(#LOGO_ARTICLE_NORMAL|image_responsive{200})]

    Dans ce cas, le logo est chargé en largeur de 200, avec un srcset pour le 1x et le 2x, c’est-à-dire qu’on a une image de taille unique, mais en simple ou double résolution (et, comme toujours avec mon plugin, la double résolution se fait avec une compression JPEG bien plus important).

    L’intérêt est, ici, que le preloader du navigateur fonctionne bien sur ce type d’images, et on n’attend plus le javascript pour charger la bonne image. Le javascript est tout de même là, parce que ce n’est pas encore compris par tous les navigateurs (50% d’adoption tout de même, notamment Safari et Chrome, prépondérants sur supports mobiles, qui représentent l’essentiel des écrans haute déf.) ; mais sur les navigateurs qui comprennent srcset, le javascript n’est plus utile dans ces cas-là.

    À terme, j’aimerais bien parvenir à passer toutes les options en srcset et picture/media, générés directement depuis mon plugin, mais pour l’instant je n’ai pas réellement de solution idéale. Un des écueils, c’est que dans mon principe, l’image haute définition ne doit pas être simplement l’image deux fois plus grande (sinon on a un JPEG deux fois plus lourd, alors qu’on est sur support mobile…), mais une version très compressée. Et il faudrait de plus introduire des mediaqueries dans l’appel de la fonction, et du coup on perd énormément de l’intérêt du truc.

  • Évolution de mon #plugin #SPIP image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    J’ai ajouté, dans la page « Admin / Vider le cache » un troisième pavé, permettant de gérer plus finement les images générées pour les besoins du responsive.

    Exemple sur un site avec des milliers d’images :

    L’idée, c’est d’essayer de faire la différence entre les images utilisées souvent (conserver le cache) et les images utilisées moins souvent (qu’on peut donc virer en priorité si on a besoin). Par approximation, je me base sur l’âge de dernier accès au fichier (fileatime() de PHP).

  • Évolution de mon #plugin #SPIP image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    Nouvelle fonction : background_responsive() (mêmes variables que image_responsive(), sauf l’option « vertical »). À installer par exemple dans un div, pour fabriquer une image de background, en mode « cover », chargée de manière responsive évidemment.

    <div class="interieur"[(#IMG_FOND|background_responsive{320/600/1280/1920, 1})]>

    Bien noter que ça ne fabrique pas, pour le coup, une <img>, mais un style="background" (et tout le tralala pour que ça tourne en responsive et en lazyload). Il faut donc l’intégrer à l’intérieur d’une balise (ici un div) pour que ça fonctionne. C’est d’ailleurs pour cela que ce n’est pas une fonction image_…, puisque ça ne donne pas un fichier image en sortie.

    Je croyais ne pas avoir trop besoin de gérer les images en background en responsive, puisque je m’en sors très bien d’habitude en utilisant une véritable image (responsive, donc) et son positionnement (voir mon petit remplir_image) :
    http://seenthis.net/messages/264068

    Mais on a obligatoirement besoin de background si on veut pouvoir passer des images en position:fixed réellement par rapport au viewport, pour les effets de parallax (tenter de faire la même chose avec des décalages verticaux lors du scroll, ça donne des animations qui sautent et qui collent mal à la tête).

    Sinon, par la suite, il faudrait uniformiser l’insertion de data-lazy et data-responsive dans le code de image_responsive (ici je ne peux pas ajouter de classe, parce que je suis déjà dans un div que je ne fabrique pas, contrairement au img).

    • Nouvel ajout : dans background-responsive, j’utilise deux images – une horizontale et une verticale (l’une étant calculée automatiquement à partir de l’autre) – que je stocke dans data-portrait-src et data-italien-src. De cette façon, au moment du choix de l’image en javascript, selon la taille d’affichage du conteneur (idéalement, ici, l’écran), ça va donc utiliser l’image qui a le moins de pertes.

      L’idée, c’est que si je prends une image horizontale, et que j’affichage ça pour « remplir » un écran vertical, j’étais obligé d’expédier une image faisant quasiment deux fois la taille de l’écran, avec la droite et la gauche de l’image en dehors de l’écran. Là, je limite beaucoup le problème. (Je pense que ça devient d’autant pertinent qu’on utilise ici de grandes images, potentiellement en double définition.)

  • J’ai un bug énorme dans la fonction imageconvolution de PHP en version 5.5.9 et 5.5.10, et qui n’a pas l’air documentée :
    http://php.net/manual/en/function.imageconvolution.php

    la troisième variable de la fonction, le divisor, ne semble plus fonctionner que si sa valeur est 1.

    J’ai donc modifié la fonction image_reduire_net de mon #plugin #SPIP image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive
    – je recalcule la matrice pour que sa somme soit égale à 1 ;
    – au passage, la fonction est passée dans un fichier séparé, ce qui permet de l’appeler en dehors du fichier d’action.

    Je n’ai rigoureusement rien trouvé à ce sujet, sauf un bug signalé dans un Git, comme quoi son renforcement en 5.5.9 devenait un blur. Chez moi, comme j’ai des valeurs différentes, ça me brûlait mes vignettes.

    (Bon, soit c’est mon MAMP qui est bugué, soit c’est le problème classique avec les fonctions graphiques : personne dans le libre ne les utilise jamais.)

  • Par ailleurs, modif dans image_responsive :
    http://zone.spip.org/trac/spip-zone/browser/_plugins_/image_responsive

    J’introduis un script jquery.smartresize.jsdestiné à déclencher « intelligemment » les scripts au redimensionnement de l’écran (le .resize() de jQuery ayant des comportements non constants).

    Je ne suis pas certain que ce soit une bonne idée de mettre ça là, peut-être qu’une lib serait plus adaptée, peut-être qu’il y a déjà quelque chose dans SPIP (dans jquery-ui peut-être) ? Bon, en tout cas ça ne change rigoureusement rien au comportement du plugin, sauf si on a déjà par ailleurs un smartresize du même nom.