Produce and use webp pictures with different sizes

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2020-12-11 15:27:04 +01:00
parent c8987df7af
commit 6a52ca0d91
15 changed files with 267 additions and 17 deletions

View File

@@ -1,6 +1,22 @@
<template>
<footer class="footer" ref="footer">
<img :src="`/img/pics/footer_${random}.jpg`" alt="" />
<picture>
<source
:srcset="`/img/pics/footer_${random}-1024w.webp 1x, /img/pics/footer_${random}-1920w.webp 2x`"
type="image/webp"
/>
<source
:srcset="`/img/pics/footer_${random}-1024w.jpg 1x, /img/pics/footer_${random}-1920w.jpg 2x`"
type="image/jpeg"
/>
<img
:src="`/img/pics/footer_${random}-1024w.jpg`"
alt=""
width="5234"
height="2189"
loading="lazy"
/>
</picture>
<ul>
<li>
<b-select

10
js/src/utils/support.ts Normal file
View File

@@ -0,0 +1,10 @@
export function supportsWebPFormat(): boolean {
const elem = document.createElement("canvas");
if (elem.getContext && elem.getContext("2d")) {
// was able or not to get WebP representation
return elem.toDataURL("image/webp").indexOf("data:image/webp") === 0;
}
// very old browser like IE 8, canvas not supported
return false;
}

View File

@@ -101,7 +101,7 @@
>
<div class="columns is-vertical is-centered">
<div class="column is-three-quarters">
<div class="img-container" />
<div class="img-container" :class="{ webp: supportsWebPFormat }" />
<div class="content has-text-centered">
<p>
{{ $t("You didn't create or join any event yet.") }}
@@ -129,6 +129,7 @@
import { Component, Vue } from "vue-property-decorator";
import { ParticipantRole } from "@/types/enums";
import RouteName from "@/router/name";
import { supportsWebPFormat } from "@/utils/support";
import { IParticipant, Participant } from "../../types/participant.model";
import {
LOGGED_USER_PARTICIPATIONS,
@@ -211,6 +212,8 @@ export default class MyEvents extends Vue {
RouteName = RouteName;
supportsWebPFormat = supportsWebPFormat;
static monthlyParticipations(
participations: IParticipant[],
revertSort = false
@@ -355,7 +358,21 @@ section {
.not-found {
.img-container {
background-image: url("/img/pics/2020-10-06-mobilizon-illustration-B_creation-evenement.jpg");
background-image: url("/img/pics/event_creation-480w.jpg");
@media (min-resolution: 2dppx) {
& {
background-image: url("/img/pics/event_creation-1024w.jpg");
}
}
&.webp {
background-image: url("/img/pics/event_creation-480w.webp");
@media (min-resolution: 2dppx) {
& {
background-image: url("/img/pics/event_creation-1024w.webp");
}
}
}
max-width: 450px;
height: 300px;
box-shadow: 0 0 8px 8px white inset;

View File

@@ -46,7 +46,7 @@
>
<div class="columns is-vertical is-centered">
<div class="column is-three-quarters">
<div class="img-container" />
<div class="img-container" :class="{ webp: supportsWebPFormat }" />
<div class="content has-text-centered">
<p>
{{ $t("You are not part of any group.") }}
@@ -81,6 +81,7 @@ import { IGroup, usernameWithDomain } from "@/types/actor";
import { Route } from "vue-router";
import { IMember } from "@/types/actor/member.model";
import { MemberRole } from "@/types/enums";
import { supportsWebPFormat } from "@/utils/support";
import RouteName from "../../router/name";
@Component({
@@ -119,6 +120,8 @@ export default class MyGroups extends Vue {
limit = 10;
supportsWebPFormat = supportsWebPFormat;
acceptInvitation(member: IMember): Promise<Route> {
return this.$router.push({
name: RouteName.GROUP,
@@ -199,7 +202,22 @@ section {
.not-found {
.img-container {
background-image: url("/img/pics/2020-10-06-mobilizon-illustration-C_groupe.jpg");
background-image: url("/img/pics/group-480w.jpg");
@media (min-resolution: 2dppx) {
& {
background-image: url("/img/pics/group-1024w.jpg");
}
}
&.webp {
background-image: url("/img/pics/group-480w.webp");
@media (min-resolution: 2dppx) {
& {
background-image: url("/img/pics/group-1024w.webp");
}
}
}
max-width: 450px;
height: 300px;
box-shadow: 0 0 8px 8px white inset;

View File

@@ -2,6 +2,7 @@
<div id="homepage">
<section
class="hero"
:class="{ webp: supportsWebPFormat }"
v-if="config && (!currentUser.id || !currentActor.id)"
>
<div class="hero-body">
@@ -72,10 +73,59 @@
</div>
<div id="picture" v-if="config && (!currentUser.id || !currentActor.id)">
<div class="picture-container">
<img
src="/img/pics/2020-10-06-mobilizon-illustration-A_homepage.jpg"
alt=""
/>
<picture>
<source
media="(max-width: 799px)"
srcset="/img/pics/homepage-480w.webp"
type="image/webp"
/>
<source
media="(max-width: 799px)"
srcset="/img/pics/homepage-480w.jpg"
type="image/jpeg"
/>
<source
media="(max-width: 1024px)"
srcset="/img/pics/homepage-1024w.webp"
type="image/webp"
/>
<source
media="(max-width: 1024px)"
srcset="/img/pics/homepage-1024w.jpg"
type="image/jpeg"
/>
<source
media="(max-width: 1920px)"
srcset="/img/pics/homepage-1920w.webp"
type="image/webp"
/>
<source
media="(max-width: 1920px)"
srcset="/img/pics/homepage-1920w.jpg"
type="image/jpeg"
/>
<source
media="(min-width: 1921px)"
srcset="/img/pics/homepage.webp"
type="image/webp"
/>
<source
media="(min-width: 1921px)"
srcset="/img/pics/homepage.jpg"
type="image/jpeg"
/>
<img
src="/img/pics/homepage-1024w.jpg"
width="3840"
height="2719"
alt=""
loading="lazy"
/>
</picture>
</div>
<div class="container section">
<div class="columns">
@@ -221,6 +271,7 @@
import { Component, Vue, Watch } from "vue-property-decorator";
import { ParticipantRole } from "@/types/enums";
import { Paginate } from "@/types/paginate";
import { supportsWebPFormat } from "@/utils/support";
import { IParticipant, Participant } from "../types/participant.model";
import { FETCH_EVENTS } from "../graphql/event";
import EventListCard from "../components/Event/EventListCard.vue";
@@ -296,7 +347,10 @@ import Subtitle from "../components/Utils/Subtitle.vue";
},
})
export default class Home extends Vue {
events!: Paginate<IEvent>;
events: Paginate<IEvent> = {
elements: [],
total: 0,
};
locations = [];
@@ -316,6 +370,8 @@ export default class Home extends Vue {
currentUserParticipations: IParticipant[] = [];
supportsWebPFormat = supportsWebPFormat;
// get displayed_name() {
// return this.loggedPerson && this.loggedPerson.name === null
// ? this.loggedPerson.preferredUsername
@@ -531,7 +587,11 @@ section.hero {
height: 100%;
opacity: 0.3;
z-index: -1;
background: url("/img/pics/homepage_background.png");
background: url("/img/pics/homepage_background-1024w.png");
background-size: cover;
}
&.webp::before {
background-image: url("/img/pics/homepage_background-1024w.webp");
}
& > .hero-body {

View File

@@ -2,10 +2,24 @@
<section class="section container has-text-centered not-found">
<div class="columns is-vertical is-centered">
<div class="column is-half">
<img
src="/img/pics/2020-10-06-mobilizon-illustration-E_realisation.jpg"
alt=""
/>
<picture>
<source
srcset="/img/pics/error-480w.webp 1x, /img/pics/error-1024w.webp 2x"
type="image/webp"
/>
<source
srcset="/img/pics/error-480w.jpg 1x, /img/pics/error-1024w.jpg 2x"
type="image/jpeg"
/>
<img
:src="`/img/pics/error-480w.jpg`"
alt=""
width="2616"
height="1698"
loading="lazy"
/>
</picture>
<h1 class="title">
{{ $t("The page you're looking for doesn't exist.") }}
</h1>