Make WebP the default image format

This commit is contained in:
Andras Schmelczer 2022-09-22 09:06:51 +02:00
parent 890133d10e
commit 94faabca34
No known key found for this signature in database
GPG key ID: 0EA1BC97D0AB076E
23 changed files with 65 additions and 72 deletions

View file

@ -1,12 +1,15 @@
# Timeline
An easily configurable portfolio.
> An easy-to-configure portfolio.
> [Click for live version](https://schmelczer.dev)
[![Check, build and deploy to GitHub Pages](https://github.com/schmelczer/schmelczer.github.io/actions/workflows/lint-and-deploy.yaml/badge.svg)](https://github.com/schmelczer/schmelczer.github.io/actions/workflows/lint-and-deploy.yaml)
[Check out the live version.](https://schmelczer.dev)
## Configuration
- The actual content is in the [data](src/data) folder starting with [portfolio.ts](src/data/portfolio.ts)
- The actual content is in the [data](src/data) folder, starting with [portfolio.ts](src/data/portfolio.ts)
- The assets referenced should be located in [data/media](src/data/media)
## Build
@ -14,3 +17,8 @@ An easily configurable portfolio.
1. `npm install`
2. `npm run build`
3. You can find the results in the [dist](dist) folder
## Info
- All images are converted to `WebP` after being imported into any file.
> Except for the og-image, and SVGs.

8
custom.d.ts vendored
View file

@ -3,7 +3,7 @@ declare module '*.svg' {
export default content;
}
declare module '*.jpg?format=webp' {
declare module '*.jpg' {
import { ResponsiveImage } from 'src/types/responsive-image';
const content: ResponsiveImage;
export default content;
@ -15,12 +15,6 @@ declare module '*.png' {
export default content;
}
declare module '*.png?format=webp' {
import { ResponsiveImage } from 'src/types/responsive-image';
const content: ResponsiveImage;
export default content;
}
declare module '*.mp4' {
import { url } from 'src/types/url';
const content: url;

View file

@ -6,7 +6,7 @@ import { Main } from '../page/main/main';
import { PageElement } from '../page/page-element';
import { PageTimeline } from '../page/timeline/timeline';
import cvEnglish from './media/cv-andras-schmelczer.pdf';
import meWebP from './media/me.jpg?format=webp';
import me from './media/me.jpg';
import { adAstraTimelineElement } from './projects/ad-astra';
import { citySimulationTimelineElement } from './projects/city-simulation';
import { declaredTimelineElement } from './projects/declared';
@ -26,7 +26,7 @@ export const create = (): Array<PageElement> => [
new PageBackground(1, 1),
new PageHeader({
name: `András Schmelczer`,
imageWebP: meWebP,
image: me,
imageAltText: `a picture of me`,
about: [
`

View file

@ -1,6 +1,6 @@
import { Video } from '../../page/basics/video/video';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import adAstraWebP from '../media/ad_astra.jpg?format=webp';
import adAstra from '../media/ad_astra.jpg';
import adAstraMp4 from '../media/mp4/ad_astra.mp4';
import adAstraWebM from '../media/webm/ad_astra.webm';
import { GitHub } from '../shared';
@ -9,7 +9,7 @@ export const adAstraTimelineElement: TimelineElementParameters = {
title: `Gaming on an ATtiny85`,
date: `2020 spring`,
figure: new Video({
posterWebP: adAstraWebP,
poster: adAstra,
mp4: adAstraMp4,
webm: adAstraWebM,
}),

View file

@ -1,14 +1,14 @@
import { Video } from '../../page/basics/video/video';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import citySimulationMp4 from '../media/mp4/simulation.mp4';
import citySimulationPosterWebP from '../media/simulation.jpg?format=webp';
import citySimulationPoster from '../media/simulation.jpg';
import citySimulationWebM from '../media/webm/simulation.webm';
export const citySimulationTimelineElement: TimelineElementParameters = {
title: `City simulation`,
date: `2018 July - August`,
figure: new Video({
posterWebP: citySimulationPosterWebP,
poster: citySimulationPoster,
mp4: citySimulationMp4,
webm: citySimulationWebM,
}),

View file

@ -1,12 +1,12 @@
import { Image } from '../../page/basics/image/image.html';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import colourWebP from '../media/color.jpg?format=webp';
import colour from '../media/color.jpg';
export const colorsTimelineElement: TimelineElementParameters = {
title: `Photo colour grader`,
date: `2018 June`,
figure: Image({
imageWebP: colourWebP,
image: colour,
alt: `a picture of the app`,
container: true,
}),

View file

@ -1,13 +1,13 @@
import { Preview } from '../../page/basics/preview/preview';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import declaredWebP from '../media/decla-red.png?format=webp';
import declared from '../media/decla-red.png';
import bscThesis from '../media/sdf2d-andras-schmelczer.pdf';
import { GitHub, Open, Thesis } from '../shared';
export const declaredTimelineElement: TimelineElementParameters = {
title: `Multiplayer game`,
date: `2020 autumn`,
figure: new Preview(declaredWebP, 'https://decla.red', 'The website of the video game'),
figure: new Preview(declared, 'https://decla.red', 'The website of the video game'),
description: `
Using SDF-2D (my ray tracing graphics library), I created a conquest-style multiplayer browser game.
It even runs on mobiles.

View file

@ -1,6 +1,6 @@
import { Video } from '../../page/basics/video/video';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import forexPosterWebP from '../media/forex.jpg?format=webp';
import forexPoster from '../media/forex.jpg';
import forexMp4 from '../media/mp4/forex.mp4';
import forexWebM from '../media/webm/forex.webm';
@ -8,7 +8,7 @@ export const forexTimelineElement: TimelineElementParameters = {
title: `Predicting foreign exchange rates`,
date: `2019 autumn`,
figure: new Video({
posterWebP: forexPosterWebP,
poster: forexPoster,
mp4: forexMp4,
webm: forexWebM,
invertButton: true,

View file

@ -1,14 +1,14 @@
import { Image } from '../../page/basics/image/image.html';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import mscThesis from '../media/great-ai-andras-schmelczer.pdf';
import greatAiWebP from '../media/great-ai.png?format=webp';
import greatAi from '../media/great-ai.png';
import { Open, PyPi, Thesis } from '../shared';
export const greatAiTimelineElement: TimelineElementParameters = {
title: `GreatAI`,
date: `2022`,
figure: Image({
imageWebP: greatAiWebP,
image: greatAi,
alt: `some example code using GreatAI`,
container: true,
}),

View file

@ -1,6 +1,6 @@
import { Video } from '../../page/basics/video/video';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import ledPosterWebP from '../media/led.jpg?format=webp';
import ledPoster from '../media/led.jpg';
import ledMp4 from '../media/mp4/led.mp4';
import ledWebM from '../media/webm/led.webm';
@ -8,7 +8,7 @@ export const ledsTimelineElement: TimelineElementParameters = {
title: `Lights synchronised to music`,
date: `2016 spring`,
figure: new Video({
posterWebP: ledPosterWebP,
poster: ledPoster,
mp4: ledMp4,
webm: ledWebM,
}),

View file

@ -1,13 +1,13 @@
import { Image } from '../../page/basics/image/image.html';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import myNotesWebP from '../media/my-notes.png?format=webp';
import myNotes from '../media/my-notes.png';
import { GitHub } from '../shared';
export const myNotesTimelineElement: TimelineElementParameters = {
title: `My Notes`,
date: `2019 November`,
figure: Image({
imageWebP: myNotesWebP,
image: myNotes,
alt: `two screenshots of the application`,
container: true,
}),

View file

@ -1,12 +1,12 @@
import { Image } from '../../page/basics/image/image.html';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import processSimulatorInputWebP from '../media/process-simulator-input.jpg?format=webp';
import processSimulatorInput from '../media/process-simulator-input.jpg';
export const nuclearEditorTimelineElement: TimelineElementParameters = {
title: `Graph editing application`,
date: `2018 October - November`,
figure: Image({
imageWebP: processSimulatorInputWebP,
image: processSimulatorInput,
alt: `a picture of the simulator's UI`,
container: true,
}),

View file

@ -1,12 +1,12 @@
import { Image } from '../../page/basics/image/image.html';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import processSimulatorWebP from '../media/process-simulator.jpg?format=webp';
import processSimulator from '../media/process-simulator.jpg';
export const nuclearTimelineElement: TimelineElementParameters = {
title: `Simulating the cooling system of a nuclear facility`,
date: `2018 October - November`,
figure: Image({
imageWebP: processSimulatorWebP,
image: processSimulator,
alt: `a screenshot of the simulator`,
container: true,
}),

View file

@ -1,13 +1,13 @@
import { Image } from '../../page/basics/image/image.html';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import photosWebP from '../media/photos.jpg?format=webp';
import photos from '../media/photos.jpg';
import { Open } from '../shared';
export const photosTimelineElement: TimelineElementParameters = {
title: `Photos`,
date: `2016 summer`,
figure: Image({
imageWebP: photosWebP,
image: photos,
alt: `a picture of the website`,
container: true,
}),

View file

@ -1,14 +1,14 @@
import { Video } from '../../page/basics/video/video';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import platformMp4 from '../media/mp4/platform.mp4';
import platformPosterWebP from '../media/platform.png?format=webp';
import platformPoster from '../media/platform.png';
import platformWebM from '../media/webm/platform.webm';
export const platformGameTimelineElement: TimelineElementParameters = {
title: `Platform game`,
date: `2017 autumn`,
figure: new Video({
posterWebP: platformPosterWebP,
poster: platformPoster,
mp4: platformMp4,
webm: platformWebM,
}),

View file

@ -1,13 +1,13 @@
import { Preview } from '../../page/basics/preview/preview';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import sdf2dWebP from '../media/sdf2d.png?format=webp';
import sdf2d from '../media/sdf2d.png';
import { NPM, Open, Youtube } from '../shared';
export const sdf2dTimelineElement: TimelineElementParameters = {
title: `2D ray tracing`,
date: `2020 autumn`,
figure: new Preview(
sdf2dWebP,
sdf2d,
'https://sdf2d.schmelczer.dev',
'A webpage showcasing the SDF-2D project.'
),

View file

@ -1,13 +1,13 @@
import { Image } from '../../page/basics/image/image.html';
import { TimelineElementParameters } from '../../page/timeline/timeline-element/timeline-element-parameters';
import towersWebP from '../media/towers.png?format=webp';
import towers from '../media/towers.png';
import { GitHub, Open } from '../shared';
export const towersTimelineElement: TimelineElementParameters = {
title: `Towers tracking app`,
date: `2019 August - September`,
figure: Image({
imageWebP: towersWebP,
image: towers,
alt: `a picture of the website`,
container: true,
}),

View file

@ -4,13 +4,13 @@ import { ResponsiveImage } from '../../../types/responsive-image';
import './image.scss';
export const Image = ({
imageWebP,
image,
alt,
container = false,
isIgnoredByImageViewer = false,
imageScreenRatio = 0.8,
}: {
imageWebP: ResponsiveImage;
image: ResponsiveImage;
alt: string;
container?: boolean;
isIgnoredByImageViewer?: boolean;
@ -19,27 +19,27 @@ export const Image = ({
${
container
? `<div class="figure-container" style="padding-top:${
(imageWebP.height / imageWebP.width) * 100
(image.height / image.width) * 100
}%">`
: ''
}
<div
class="image"
style="background-size: cover; background-image: url('${imageWebP.placeholder}')",
style="background-size: cover; background-image: url('${image.placeholder}')",
}}>
<picture loading="lazy">
<source
srcset="${imageWebP.srcSet}"
sizes="${getSizes(imageWebP, imageScreenRatio)}"
type="image/webp"
srcset="${image.srcSet}"
sizes="${getSizes(image, imageScreenRatio)}"
type="image/"
/>
<img
${isIgnoredByImageViewer ? 'image-viewer-ignore' : ''}
tabindex="0"
loading="lazy"
width="${imageWebP.width}"
height="${imageWebP.height}"
src="${last(imageWebP.images)?.path}"
width="${image.width}"
height="${image.height}"
src="${last(image.images)?.path}"
alt="${alt}"
/>
</picture>

View file

@ -7,14 +7,14 @@ import './preview.scss';
export const generate = ({
alt,
posterWebP,
poster,
}: {
alt: string;
posterWebP: ResponsiveImage;
poster: ResponsiveImage;
}): html => `
<div class="preview">
${Image({
imageWebP: posterWebP,
image: poster,
alt,
container: true,
isIgnoredByImageViewer: true,

View file

@ -4,12 +4,8 @@ import { PageElement } from '../../page-element';
import { generate } from './preview.html';
export class Preview extends PageElement {
public constructor(
posterWebP: ResponsiveImage,
private readonly url: string,
alt: string
) {
super(createElement(generate({ posterWebP, alt })));
public constructor(poster: ResponsiveImage, private readonly url: string, alt: string) {
super(createElement(generate({ poster, alt })));
this.url += '?portfolioView';
this.query('.start-button').addEventListener('click', this.loadContent.bind(this));
}

View file

@ -4,6 +4,6 @@ import { url } from '../../../types/url';
export interface VideoParameters {
mp4: url;
webm: url;
posterWebP: ResponsiveImage;
poster: ResponsiveImage;
invertButton?: boolean;
}

View file

@ -5,17 +5,12 @@ import { Image } from '../../basics/image/image.html';
import { VideoParameters } from './video-parameters';
import './video.scss';
export const generate = ({
webm,
mp4,
posterWebP,
invertButton,
}: VideoParameters): html => `
export const generate = ({ webm, mp4, poster, invertButton }: VideoParameters): html => `
<div class="figure-container video-container" style="padding-top:${
(posterWebP.height / posterWebP.width) * 100
(poster.height / poster.width) * 100
}%">
${Image({
imageWebP: posterWebP,
image: poster,
alt: `thumbnail for the video`,
isIgnoredByImageViewer: true,
})}

View file

@ -8,12 +8,12 @@ import { PageThemeSwitcher } from './theme-switcher/theme-switcher';
export class PageHeader extends PageElement {
public constructor({
name,
imageWebP,
image,
imageAltText,
about,
}: {
name: string;
imageWebP: ResponsiveImage;
image: ResponsiveImage;
imageAltText: string;
about: Array<string>;
}) {
@ -23,7 +23,7 @@ export class PageHeader extends PageElement {
name,
about,
photo: Image({
imageWebP,
image,
alt: imageAltText,
imageScreenRatio: 0.2,
}),