0
votes

Comment afficher une image aléatoire à partir d'un tableau d'images dans TYPO3 Fluid Template?

J'ai une image de champ avec un tableau d'objets image.

L'utilisateur peut télécharger des images dans ce champ.

Dans le modèle fluide, cela ressemble à:

<f:if condition="{field.image}">
    <f:then>
        <f:for each="{field.image}" as="image" iteration="iterator">
            <f:image src="file:{image.properties.uid}" alt="" class="img-fluid" width="1250c" height="600c" />
        </f:for>
    </f:then>
</f:if>

Dans le cas où trois photos seraient téléchargées, toutes seront affichées. Mais je n'ai besoin de montrer qu'une seule image aléatoire à cet endroit. Comment puis-je le faire?


3 commentaires

{field.image} est une collection (tableau si je me souviens bien). Créez un ViewHelper personnalisé pour sélectionner une image au hasard. La logique de VH devrait être assez simple.


Notez que l'approche avec ViewHelper personnalisé sera mise en cache afin d'afficher la même image jusqu'à la prochaine suppression du cache. Vous pouvez de toute façon créer un ViewHelper qui retournera ie. tableau d'images possibles en tant qu'objet JSON afin que vous puissiez en sélectionner une au hasard sans clering cache.


Peut-être que cela aide: typo3-probleme.de/2019/09/12 / ...


4 Réponses :


0
votes

Comme mentionné dans mon commentaire, vous pouvez créer votre propre ViewHelper, de toute façon, la solution de contournement rapide consiste à utiliser jQuery uniquement dans le code. Tout d'abord, masquez toutes les images par défaut, puis affichez-en une au hasard.

<f:if condition="{field.image}">
    <f:then>
        <f:for each="{field.image}" as="image" iteration="iterator">
            <f:image src="file:{image.properties.uid}" alt="" class="img-fluid random-image" style="display: none" width="1250c" height="600c" />
        </f:for>
        <script>

            $("img").not(":visible").each(function () {
                $(this).data("src", this.src);
                this.src = "";
            });

            shuffle($(".random-image")).slice(0, 1).each(function () {
                $(this).attr('src', $(this).data('src')).show();
            });

            // shuffle function thanks to Jon: 
            // https://stackoverflow.com/a/11186765/1066240
            function shuffle(array) {
                let m = array.length, t, i;
                while (m) {
                    i = Math.floor(Math.random() * m--);
                    t = array[m];
                    array[m] = array[i];
                    array[i] = t;
                }
                return array;
            }
        </script>
</f:if>

Notez que cette approche doit être considérée comme un sale-hack et peut être mieux faite c'est-à-dire pour éviter de charger des images qui ne seront jamais affichées (sur cette page, actualisez). gardez également à l'esprit que vous pouvez afficher 3 images aléatoires à l'aide de la slice(0, 3) , cependant, vous devez vous assurer que vous avez au moins 3 images.


0 commentaires

0
votes

Merci pour vos commentaires et réponses mais cette solution n'est pas bonne pour mon cas à cause du cache.

La solution jQuery n'est pas non plus bonne pour moi car toutes les images doivent être chargées en premier. Il peut y avoir 10 images d'arrière-plan avec 200 ko et au lieu de charger seulement 200 ko, 2 Mo ont été chargés pour afficher une seule image. Il peut également y avoir un problème avec le cache du navigateur.

J'ai trouvé une autre solution sans propre problème ViewHelper, jQuery et cache.

Le voici:

<f:if condition="{field.image}">
    <f:then>
        {f:count(subject: field.image) -> f:variable(name: 'maximage')}
        {v:random.number(minimum: 1, maximum: maximage) -> f:variable(name: 'randomimage')}
        <f:for each="{field.image}" as="image" iteration="iterator">
            <f:if condition="{iterator.cycle} == {randomimage}">
                <f:image src="file:{image.properties.uid}" alt="" class="img-fluid" width="1250c" height="600c" />
            </f:if>
        </f:for>
    </f:then>
</f:if>

Explication:

{f: count (subject: field.image) -> f: variable (name: 'maximage')} - obtenir la taille de la collection d'images et la mettre dans le nouveau maximage de la variable.

{v: random.number (minimum: 1, maximum: maximage) -> f: variable (name: 'randomimage')} - obtenir le nombre aléatoire entre 1 et maximage et le mettre dans la nouvelle variable randomimage .

<f: for each = "{field.image}" as = "image" iteration = "iterator"> - démarre la boucle normale pour field.images

<f: if condition = "{iterator.cycle} == {randomimage}"> - condition pour afficher l'image - ne l'afficher que si l'itérateur actuel {iterator.cycle} est égal à l '{randomimage}.

Ont testé dans Typo3 8.7.20. J'espère que cela fonctionnera également dans Typo3 9.x et 10.x.


0 commentaires

0
votes

Puisque vous utilisez déjà la VHS:

Utilisez v:iterator.random - https://viewhelpers.fluidtypo3.org/fluidtypo3/vhs/5.0.1/Iterator/Random.html

Mais assurez-vous que vous êtes conscient du piège "le résultat est mis en cache" décrit par @biesior ci-dessus ( Comment afficher une image aléatoire à partir d'un tableau d'images dans TYPO3 Fluid Template? ).


0 commentaires

0
votes

J'ai fait une solution avec plusieurs avantages:

  • fonctionne avec le cache
  • toutes les images entièrement réactives
  • charger une seule image

Je génère toutes les balises mais les enveloppe dans un commentaire HTML. Le navigateur ne charge pas les images.

(function ($) {
    $.fn.rand = function () {
        return this.eq(Math.floor(Math.random() * this.length));
    };
})(jQuery);


// Get random image
var stageImageDiv = $(this).find('.stage-image');
$(stageImageDiv).children().rand().replaceWith(function () {
    var string = $(this).html();
    return string.replace(/<!--/g, '').replace(/-->/g, '');
});

UNE

Ensuite, supprimez au hasard le commentaire HTML d'un et le navigateur les charge.

<div class="stage-image has-content">
    <div class="stage-image-item">
        <!-- <img src="/storage/hochschule/upload/150902-4654.jpg" srcset="/storage/_processed_/3/e/csm_150902-4654_8eaf6a0880.jpg 764w,/storage/_processed_/3/e/csm_150902-4654_d0f788b245.jpg 1084w,/storage/hochschule/upload/150902-4654.jpg 1170w,"  sizes="(max-width: 767px) 764px, (min-width: 768px) and (max-width: 991px) 1084px, (min-width: 992px) 1170px"  alt="" > -->
    </div>
    <div class="stage-image-item">
        <!-- <img src="/storage/hochschule/upload/151022-0041.jpg" srcset="/storage/_processed_/f/e/csm_151022-0041_d0b564fdb1.jpg 764w,/storage/_processed_/f/e/csm_151022-0041_b993bf6066.jpg 1084w,/storage/hochschule/upload/151022-0041.jpg 1170w,"  sizes="(max-width: 767px) 764px, (min-width: 768px) and (max-width: 991px) 1084px, (min-width: 992px) 1170px"  alt="" > -->
    </div>
    <div class="stage-image-item">
        <!-- <img src="/storage/hochschule/upload/151013-7145.jpg" srcset="/storage/_processed_/e/6/csm_151013-7145_42e2692215.jpg 764w,/storage/_processed_/e/6/csm_151013-7145_3ee771dee1.jpg 1084w,/storage/hochschule/upload/151013-7145.jpg 1170w,"  sizes="(max-width: 767px) 764px, (min-width: 768px) and (max-width: 991px) 1084px, (min-width: 992px) 1170px"  alt="" > -->
    </div>
    <div class="stage-image-item">
        <!-- <img src="/storage/hochschule/upload/151104-1433.jpg" srcset="/storage/_processed_/f/b/csm_151104-1433_7bf357e27a.jpg 764w,/storage/_processed_/f/b/csm_151104-1433_b7c9f24147.jpg 1084w,/storage/hochschule/upload/151104-1433.jpg 1170w,"  sizes="(max-width: 767px) 764px, (min-width: 768px) and (max-width: 991px) 1084px, (min-width: 992px) 1170px"  alt="" > -->
    </div>
    <div class="stage-image-item">
        <!-- <img src="/storage/hochschule/upload/150930-6077.jpg" srcset="/storage/_processed_/a/e/csm_150930-6077_d7a31d91e3.jpg 764w,/storage/_processed_/a/e/csm_150930-6077_87603957bf.jpg 1084w,/storage/hochschule/upload/150930-6077.jpg 1170w,"  sizes="(max-width: 767px) 764px, (min-width: 768px) and (max-width: 991px) 1084px, (min-width: 992px) 1170px"  alt="" > -->
    </div>
</div>


0 commentaires