optimisation des images

This commit is contained in:
Valentin Le Moign 2025-01-23 02:52:00 +01:00
parent c11b90f235
commit aca6c6b011
15 changed files with 153 additions and 39 deletions

View File

@ -28,6 +28,7 @@
"drupal/geocoder": "^4.24",
"drupal/geofield": "^1.59",
"drupal/image_field_caption": "^2.0",
"drupal/jsonapi_image_styles": "^3.0",
"drupal/jsonapi_views": "^1.1",
"drupal/leaflet": "^10.2",
"drupal/leaflet_more_maps": "^2.2",

67
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "06879b846031f4f705cc93ea8f4f2f7d",
"content-hash": "17284db796caf7967cb47bae1feb4a43",
"packages": [
{
"name": "asm89/stack-cors",
@ -5634,6 +5634,71 @@
"source": "https://git.drupalcode.org/project/js_cookie"
}
},
{
"name": "drupal/jsonapi_image_styles",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://git.drupalcode.org/project/jsonapi_image_styles.git",
"reference": "3.0.2"
},
"dist": {
"type": "zip",
"url": "https://ftp.drupal.org/files/projects/jsonapi_image_styles-3.0.2.zip",
"reference": "3.0.2",
"shasum": "63d52eb96eb4b8df241ca9b1e1fbb06707ba8a6c"
},
"require": {
"drupal/core": "^9 || ^10 || ^11"
},
"require-dev": {
"drupal/coder": "^8.3",
"phpcompatibility/php-compatibility": "10.x-dev"
},
"type": "drupal-module",
"extra": {
"drupal": {
"version": "3.0.2",
"datestamp": "1727189318",
"security-coverage": {
"status": "covered",
"message": "Covered by Drupal's security advisory policy"
}
}
},
"notification-url": "https://packages.drupal.org/8/downloads",
"license": [
"GPL-2.0-or-later"
],
"authors": [
{
"name": "Alona O'neill",
"homepage": "https://www.drupal.org/u/alonaoneill"
},
{
"name": "Timo Kirkkala",
"homepage": "https://www.drupal.org/u/kirkkala"
},
{
"name": "Jeffrey Bertoen",
"homepage": "https://www.drupal.org/u/jefuri"
},
{
"name": "Chrsitopher C. Wells (wells)",
"homepage": "https://www.drupal.org/user/2452278",
"email": "drupal.org@chris-wells.net"
}
],
"description": "JSON:API Image Styles provides a means to expose image styles to JSON:API.",
"homepage": "https://www.drupal.org/project/jsonapi_image_styles",
"keywords": [
"Drupal"
],
"support": {
"source": "https://git.drupalcode.org/project/jsonapi_image_styles",
"issues": "https://www.drupal.org/project/issues/jsonapi_image_styles"
}
},
{
"name": "drupal/jsonapi_resources",
"version": "1.2.0",

View File

@ -30,7 +30,8 @@ import '../scss/main.scss'
initEdgeBuffer(L);
let mapSettings = settings.leaflet[Object.keys(settings.leaflet)[0]].map;
mapSettings.layers.layer.edgeBufferTiles = 8;
mapSettings.layers.layer.edgeBufferTiles = 1;
// mapSettings.settings.fadeAnimation = false;
$(context).on('leafletMapInit', function (e, settings, map, mapid, markers) {
const {

View File

@ -85,7 +85,12 @@ export const useContentStore = defineStore('content', {
const vignetteFetch = await this.fetchFromRelationships('field_vignette', rawContent.relationships);
if (vignetteFetch) {
this.content.vignette = {
url: vignetteFetch.attributes.uri.url,
url: {
original: vignetteFetch.attributes.uri.url,
small: vignetteFetch.attributes.image_style_uri.content_small,
medium: vignetteFetch.attributes.image_style_uri.content_medium,
large: vignetteFetch.attributes.image_style_uri.content_large,
},
alt: rawContent.relationships.field_vignette.data.meta.alt
};
}
@ -129,7 +134,13 @@ export const useContentStore = defineStore('content', {
const carteSensibleFetch = await this.fetchFromRelationships('field_image_carte', partie.relationships);
if (carteSensibleFetch) {
partieContent.carteSensible = {
url: carteSensibleFetch.attributes.uri.url,
url: {
original: carteSensibleFetch.attributes.uri.url,
small: carteSensibleFetch.attributes.image_style_uri.content_small,
medium: carteSensibleFetch.attributes.image_style_uri.content_medium,
large: carteSensibleFetch.attributes.image_style_uri.content_large,
xlarge: carteSensibleFetch.attributes.image_style_uri.content_x_large,
},
alt: partie.relationships.field_image_carte.data.meta.alt,
};
}
@ -152,13 +163,21 @@ export const useContentStore = defineStore('content', {
break;
case 'diaporama':
const diaporamaFetch = await this.fetchFromRelationships('field_diaporama', partie.relationships);
if (diaporamaFetch) {
partieContent.diaporama = [];
for (let [index, image] of diaporamaFetch.entries()) {
partieContent.diaporama.push({
url: image.attributes.uri.url,
url: {
original: image.attributes.uri.url,
small: image.attributes.image_style_uri.content_small,
medium: image.attributes.image_style_uri.content_medium,
large: image.attributes.image_style_uri.content_large,
},
alt: partie.relationships.field_diaporama.data[index].meta.alt,
});
console.log(partieContent.diaporama);
}
}
break;
@ -173,7 +192,12 @@ export const useContentStore = defineStore('content', {
const portraitFetch = await this.fetchFromRelationships('field_portrait', personne.relationships);
if (portraitFetch) {
partieContent.entretien.personnes.push({
portrait: portraitFetch.attributes.uri.url,
portrait: {
original: portraitFetch.attributes.uri.url,
small: portraitFetch.attributes.image_style_uri.content_small,
medium: portraitFetch.attributes.image_style_uri.content_medium,
large: portraitFetch.attributes.image_style_uri.content_large,
},
alt: personne.relationships.field_portrait.data.meta.alt,
description: personne.attributes.field_description,
});
@ -227,7 +251,12 @@ export const useContentStore = defineStore('content', {
weight: item.attributes.field_poid,
link_url: item.attributes.field_lien.uri ,
logo_alt: item.relationships.field_logo.data.meta.alt,
logo_url: logoFetch.data.data.attributes.uri.url,
logo_url: {
original: logoFetch.data.data.attributes.uri.url,
small: logoFetch.data.data.attributes.image_style_uri.content_small,
medium: logoFetch.data.data.attributes.image_style_uri.content_medium,
large: logoFetch.data.data.attributes.image_style_uri.content_large,
},
});
}
} else if (this.contentType === 'gouvernance') {
@ -241,7 +270,12 @@ export const useContentStore = defineStore('content', {
prenom: personne.attributes.field_prenom,
description: personne.attributes.field_description,
photo_meta: personne.relationships.field_portrait.data?.meta.alt,
photo_url: portraitFetch.data.data?.attributes.uri.url,
photo_url: portraitFetch.data.data ? {
original: portraitFetch.data.data.attributes.uri.url,
small: portraitFetch.data.data.attributes.image_style_uri.content_small,
medium: portraitFetch.data.data.attributes.image_style_uri.content_medium,
large: portraitFetch.data.data.attributes.image_style_uri.content_large,
} : null
});
}
multiItemPageArray.push({
@ -285,7 +319,12 @@ export const useContentStore = defineStore('content', {
end: this.getCleanDate(relatedEtapeData.attributes.field_dates.end_value),
},
vignette: {
url: vignetteFetch.data.data.attributes.uri.url,
url: {
original: vignetteFetch.data.data.attributes.uri.url,
small: vignetteFetch.data.data.attributes.image_style_uri.content_small,
medium: vignetteFetch.data.data.attributes.image_style_uri.content_medium,
large: vignetteFetch.data.data.attributes.image_style_uri.content_large,
},
alt: relatedEtapeData.relationships.field_vignette.data.meta.alt,
},
}

View File

@ -75,12 +75,12 @@ export const useLayoutStore = defineStore('layout', {
menuTitle.classList.remove('open');
menuBurger.classList.remove('open');
menuH2.classList.remove('open');
setTimeout(() => {
if (this.isHamburgerMenuOpen) {
menuContainer.style.display = 'none';
}
}, 300);
this.isHamburgerMenuOpen = false;
if (this.isHamburgerMenuOpen) {
setTimeout(() => {
menuContainer.style.display = 'none';
}, 300);
this.isHamburgerMenuOpen = false;
}
}
});
},

View File

@ -12,7 +12,7 @@ export function setupMapStore(mapStore, map, settings) {
}
// not working
// kept to maybe rework on it later
// may or may not rework on it later
export async function preloadEtapesTiles(mapStore, map) {
function waitForEvent(el, eventName) {
return new Promise((resolve) => {

View File

@ -14,7 +14,7 @@
</div>
<div v-for="personne in equipe.personnes" class="personne">
<figure>
<img v-if="personne.photo_url" :src="personne.photo_url" :alt="personne.photo_alt">
<img v-if="personne.photo_url" :src="personne.photo_url.small" :alt="personne.photo_alt">
</figure>
<div class="name"><p v-html="personne.prenom + ' ' + personne.nom"></p></div>
<div class="description"><p v-html="personne.description" style="white-space: pre-wrap;"></p></div>

View File

@ -17,7 +17,7 @@
<div class="date">Du {{ content.previous.dates.start.d }} {{ content.previous.dates.start.m }}<br>au {{ content.previous.dates.end.d }} {{ content.previous.dates.end.m }} {{ content.previous.dates.end.y }}</div>
</div>
<div class="vignette">
<img :src="content.previous.vignette.url" :alt="content.previous.vignette.alt">
<img :src="content.previous.vignette.url.small" :alt="content.previous.vignette.alt">
</div>
</div>
</div>
@ -33,7 +33,7 @@
<div class="date">Du {{ content.next.dates.start.d }} {{ content.next.dates.start.m }}<br>au {{ content.next.dates.end.d }} {{ content.next.dates.end.m }} {{ content.next.dates.end.y }}</div>
</div>
<div class="vignette">
<img :src="content.next.vignette.url" :alt="content.next.vignette.alt">
<img :src="content.next.vignette.url.small" :alt="content.next.vignette.alt">
</div>
</div>
</div>

View File

@ -1,7 +1,7 @@
<template>
<header :class="{ 'not-etape': contentType !== 'etape' }">
<div class="cover">
<img v-if="content.vignette" :src="content.vignette.url" :alt="content.vignette.alt">
<img v-if="content.vignette" :src="content.vignette.url.medium" :alt="content.vignette.alt">
</div>
<div v-if="contentType === 'etape' && content.dates" class="cartouche" :style="{ backgroundColor: couleur }">
<p>Étape n°{{content.etape_number}}</p>

View File

@ -6,7 +6,7 @@
<div v-for="partenaire in [...content.partenaires].sort((a, b) => a.weight - b.weight)" class="partenaire">
<figure>
<a :href="partenaire.link_url" target="_blank">
<img :src="partenaire.logo_url" :alt="partenaire.logo_alt">
<img :src="partenaire.logo_url.small" :alt="partenaire.logo_alt">
</a>
</figure>
<div class="title"><p v-html="partenaire.title"></p></div>

View File

@ -1,9 +1,9 @@
<template>
<figure class="sensible-map">
<vue-image-zoomer
:regular="partie.carteSensible.url"
:zoom="partie.carteSensible.url"
:zoom-amount="3.5"
:regular="partie.carteSensible.url.large"
:zoom="partie.carteSensible.url.xlarge"
:zoom-amount="2.5"
alt="Carte sensible du territoire"
hover-message="Survolez pour zoomer dans la carte"
/>

View File

@ -7,11 +7,12 @@
:navigation="true"
:pagination="true"
:injectStyles="[`.swiper-button-next, .swiper-button-prev { z-index: 11; }`]"
@swiperresize="(e) => resizeSwiper(e.target)"
>
<swiper-slide v-for="image in partie.diaporama" style="width: 100%">
<figure>
<img
:src="image.url"
:src="image.url.medium"
:alt="image.alt"
@click="handleImageClick">
<figcaption class="caption">{{ image.alt }}</figcaption>
@ -56,15 +57,25 @@ const handleImageClick = (event) => {
if (isSwiper) {
const swiperEl = img.closest('swiper-container');
swiperEl.querySelectorAll('swiper-slide').forEach((slide) => {
const image = slide.querySelector('img');
const altText = slide.querySelector('figcaption')?.textContent || '';
swiperMedia.push({ src: image.getAttribute('src'), alt: altText });
const img = slide.querySelector('img');
const altText = slide.querySelector('figcaption')?.textContent || '';
Object.values(props.partie.diaporama).forEach((image) => {
if (image.url.medium === img.src) {
swiperMedia.push({ src: largeImgUrl, alt: altText });
}
});
});
}
openImageModale(img.src, img.alt, swiperMedia);
}
};
function resizeSwiper(swiper) {
swiper.style.height = 'auto';
swiper.style.height = `calc(${swiper.offsetHeight}px + 2rem)`;
}
onMounted(() => {
document.documentElement.style.setProperty('--etape-couleur', props.couleur);
});
@ -87,10 +98,6 @@ swiper-slide figure:not(.popup-figure) {
padding-bottom: 3rem;
}
swiper-slide figure:not(.popup-figure) figcaption {
text-align: center;
}
swiper-slide img:not(.popup-img) { /* cf main.scss */
max-height: 35vh;
cursor: pointer;

View File

@ -8,7 +8,7 @@
<div class="personnes">
<div v-for="personne in partie.entretien.personnes" class="personne">
<figure>
<img :src="personne.portrait" :alt="personne.alt">
<img :src="personne.portrait.small" :alt="personne.alt">
</figure>
<div class="description"><p v-html="personne.description"></p></div>
</div>

View File

@ -1082,6 +1082,7 @@ body{
width: 100%;
}
> figcaption {
line-height: 1.5;
padding-bottom: 2rem;
}
}

View File

@ -1350,9 +1350,9 @@
}
},
"node_modules/swiper": {
"version": "11.1.14",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-11.1.14.tgz",
"integrity": "sha512-VbQLQXC04io6AoAjIUWuZwW4MSYozkcP9KjLdrsG/00Q/yiwvhz9RQyt0nHXV10hi9NVnDNy1/wv7Dzq1lkOCQ==",
"version": "11.2.1",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-11.2.1.tgz",
"integrity": "sha512-62G69+iQRIfUqTmJkWpZDcX891Ra8O9050ckt1/JI2H+0483g+gq0m7gINecDqMtDh2zt5dK+uzBRxGhGOOvQA==",
"funding": [
{
"type": "patreon",
@ -1472,9 +1472,9 @@
}
},
"node_modules/vue-image-zoomer": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/vue-image-zoomer/-/vue-image-zoomer-2.4.1.tgz",
"integrity": "sha512-n0icSuYf51MgNakZ331j4pShIpgzVjSd25leVtiiMWEgwjNshDgAkvggfvj0slTD/CEqjNXuijZAN55me6CEWw==",
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/vue-image-zoomer/-/vue-image-zoomer-2.4.4.tgz",
"integrity": "sha512-hCDgBEitR/8m4/yDcgTWi5elR40Si2TATaYcpSh0395NpQ1LoHCFXizeXxp2MoYHzO3BpO3T4Q8+SNco/UITlg==",
"license": "MIT",
"dependencies": {
"vue": "^3.2.25"