From e291817264f6dad1aa2c7780ed9241cb45c18446 Mon Sep 17 00:00:00 2001 From: schmelczerandras Date: Thu, 19 Nov 2020 15:57:59 +0100 Subject: [PATCH] Add webp --- .vscode/settings.json | 5 +- custom.d.ts | 26 +++- package.json | 2 +- src/page/basics/image/image.html.ts | 34 +++-- src/page/basics/image/image.ts | 17 ++- src/page/basics/preview/preview.ts | 9 +- src/portfolio.ts | 121 ++++++++++++------ ...hesis.pdf => andras_schmelczer_thesis.pdf} | Bin .../{cv => media}/cv_andras_schmelczer.pdf | Bin webpack.config.js | 5 +- 10 files changed, 159 insertions(+), 60 deletions(-) rename src/static/media/{andras-schmelczer-thesis.pdf => andras_schmelczer_thesis.pdf} (100%) rename src/static/{cv => media}/cv_andras_schmelczer.pdf (100%) diff --git a/.vscode/settings.json b/.vscode/settings.json index a9fa003..c050d5b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,11 @@ { "cSpell.words": [ "andras", + "decla", "favicons", + "forex", "schmelczer", - "webm" + "webm", + "webp" ] } \ No newline at end of file diff --git a/custom.d.ts b/custom.d.ts index ec9057b..59667d5 100644 --- a/custom.d.ts +++ b/custom.d.ts @@ -3,13 +3,37 @@ declare module '*.svg' { export default content; } +declare module '*.jpg' { + import { ResponsiveImage } from 'src/types/responsive-image'; + const content: ResponsiveImage; + export default content; +} + +declare module '*.jpg?format=webp' { + import { ResponsiveImage } from 'src/types/responsive-image'; + const content: ResponsiveImage; + export default content; +} + +declare module '*.jpg?format=jpg' { + import { ResponsiveImage } from 'src/types/responsive-image'; + const content: ResponsiveImage; + export default content; +} + declare module '*.png' { import { ResponsiveImage } from 'src/types/responsive-image'; const content: ResponsiveImage; export default content; } -declare module '*.jpg' { +declare module '*.png?format=webp' { + import { ResponsiveImage } from 'src/types/responsive-image'; + const content: ResponsiveImage; + export default content; +} + +declare module '*.png?format=jpg' { import { ResponsiveImage } from 'src/types/responsive-image'; const content: ResponsiveImage; export default content; diff --git a/package.json b/package.json index 92e240e..a8d739b 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "prettier": "^1.19.1", "raw-loader": "^4.0.2", "resolve-url-loader": "^3.1.1", - "responsive-loader": "^1.2.0", + "responsive-loader": "^2.2.0", "sass": "^1.26.10", "sass-loader": "^8.0.2", "sharp": "^0.23.4", diff --git a/src/page/basics/image/image.html.ts b/src/page/basics/image/image.html.ts index b9648e0..b9351b5 100644 --- a/src/page/basics/image/image.html.ts +++ b/src/page/basics/image/image.html.ts @@ -5,24 +5,36 @@ import { html } from '../../../types/html'; export const generate = ({ sizes, - image, + imageWebP, + imageJpeg, alt, container, }: { sizes: string; - image: ResponsiveImage; + imageWebP: ResponsiveImage; + imageJpeg: ResponsiveImage; alt: string; container: boolean; }): html => ` ${container ? `
` : ''} - ${alt} + + + ${alt} + ${container ? `
` : ''} `; diff --git a/src/page/basics/image/image.ts b/src/page/basics/image/image.ts index 64048b4..9c764fb 100644 --- a/src/page/basics/image/image.ts +++ b/src/page/basics/image/image.ts @@ -7,9 +7,22 @@ import { ResponsiveImage } from '../../../types/responsive-image'; export class Image extends PageElement { private static readonly imageScreenRatio = 0.8; - public constructor(image: ResponsiveImage, alt: string, container = true) { + public constructor( + imageWebP: ResponsiveImage, + imageJpeg: ResponsiveImage, + alt: string, + container = true + ) { super( - createElement(generate({ image, alt, container, sizes: Image.getSizes(image) })) + createElement( + generate({ + imageWebP, + imageJpeg, + alt, + container, + sizes: Image.getSizes(imageWebP), + }) + ) ); } diff --git a/src/page/basics/preview/preview.ts b/src/page/basics/preview/preview.ts index d56b270..df2c584 100644 --- a/src/page/basics/preview/preview.ts +++ b/src/page/basics/preview/preview.ts @@ -6,10 +6,15 @@ import { ResponsiveImage } from '../../../types/responsive-image'; import { OnLoadEvent } from '../../../events/concrete-events/on-load-event'; export class Preview extends PageElement { - public constructor(poster: ResponsiveImage, private readonly url: string, alt: string) { + public constructor( + posterWebP: ResponsiveImage, + posterJpeg: ResponsiveImage, + private readonly url: string, + alt: string + ) { super(createElement(generate({ alt }))); this.url += '?portfolioView'; - this.attachElementByReplacing('.poster', new Image(poster, alt)); + this.attachElementByReplacing('.poster', new Image(posterWebP, posterJpeg, alt)); this.query('.load-button').addEventListener('click', this.loadContent.bind(this)); } diff --git a/src/portfolio.ts b/src/portfolio.ts index a5a7027..c331d6b 100644 --- a/src/portfolio.ts +++ b/src/portfolio.ts @@ -11,29 +11,54 @@ import { Anchor } from './page/basics/anchor/anchor'; import { Body } from './page/body/body'; import { ImageAnchorFactory } from './page/basics/image-anchor/image-anchor'; import { Preview } from './page/basics/preview/preview'; -import me from './static/media/me.jpg'; -import declared from './static/media/decla-red.png'; -import forexMP4 from './static/media/forex.mp4'; -import forexWEBM from './static/media/forex.webm'; -import thesis from './static/media/andras-schmelczer-thesis.pdf'; -import adAstraMP4 from './static/media/ad_astra_720.mp4'; -import cvIcon from './static/icons/cv.svg'; -import adAstraWEBM from './static/media/ad_astra_720.webm'; -import ad_astra_index from './static/media/ad_astra.jpg'; -import myNotes from './static/media/my-notes.png'; -import sdf2d from './static/media/sdf2d.png'; -import processSimulator from './static/media/process-simulator.jpg'; -import processSimulatorInput from './static/media/process-simulator-input.jpg'; -import citySimulation from './static/media/simulation.jpg'; -import colour from './static/media/color.jpg'; -import platform from './static/media/platform.png'; -import photos from './static/media/photos.jpg'; -import led from './static/media/led.jpg'; -import cvEnglish from './static/cv/cv_andras_schmelczer.pdf'; -import ledMP4 from './static/media/led.mp4'; -import ledWEBM from './static/media/led.webm'; + +import meJpeg from './static/media/me.jpg?format=jpg'; +import meWebP from './static/media/me.jpg?format=webp'; + +import declaredJpeg from './static/media/decla-red.png?format=jpg'; +import declaredWebP from './static/media/decla-red.png?format=webp'; + +import sdf2dJpeg from './static/media/sdf2d.png?format=jpg'; +import sdf2dWebP from './static/media/sdf2d.png?format=webp'; + +import myNotesJpeg from './static/media/my-notes.png?format=jpg'; +import myNotesWebP from './static/media/my-notes.png?format=webp'; + +import processSimulatorJpeg from './static/media/process-simulator.jpg?format=jpg'; +import processSimulatorWebP from './static/media/process-simulator.jpg?format=webp'; + +import processSimulatorInputJpeg from './static/media/process-simulator-input.jpg?format=jpg'; +import processSimulatorInputWebP from './static/media/process-simulator-input.jpg?format=webp'; + +import citySimulationJpeg from './static/media/simulation.jpg?format=jpg'; +import citySimulationWebP from './static/media/simulation.jpg?format=webp'; + +import colourJpeg from './static/media/color.jpg?format=jpg'; +import colourWebP from './static/media/color.jpg?format=webp'; + +import platformJpeg from './static/media/platform.png?format=jpg'; +import platformWebP from './static/media/platform.png?format=webp'; + +import photosJpeg from './static/media/photos.jpg?format=jpg'; +import photosWebP from './static/media/photos.jpg?format=webp'; + +import cvEnglish from './static/media/cv_andras_schmelczer.pdf'; +import thesis from './static/media/andras_schmelczer_thesis.pdf'; + +import forexMp4 from './static/media/forex.mp4'; +import forexWebM from './static/media/forex.webm'; + +import adAstraPoster from './static/media/ad_astra.jpg?format=jpg'; +import adAstraMp4 from './static/media/ad_astra_720.mp4'; +import adAstraWebM from './static/media/ad_astra_720.webm'; + +import ledPoster from './static/media/led.jpg?format=jpg'; +import ledMp4 from './static/media/led.mp4'; +import ledWebM from './static/media/led.webm'; + import githubIcon from './static/icons/github.svg'; import openIcon from './static/icons/open.svg'; +import cvIcon from './static/icons/cv.svg'; export const create = () => { const GitHub = ImageAnchorFactory(githubIcon, 'Open on GitHub'); @@ -44,7 +69,7 @@ export const create = () => { imageViewer: new PageImageViewer(), header: new PageHeader({ name: `AndrĂ¡s Schmelczer`, - picture: new Image(me, `a picture of me`, false), + picture: new Image(meWebP, meJpeg, `a picture of me`, false), about: [ new Text(`I have always been fascinated by the engineering feats that surround us and pervade every aspect of our lives. When I realised I might someday be able to contribute to this field, I knew that @@ -62,7 +87,8 @@ export const create = () => { title: `Multiplayer game`, date: `2020 Autumn`, figure: new Preview( - declared, + declaredWebP, + declaredJpeg, 'https://decla.red', 'The website of the video game' ), @@ -88,7 +114,8 @@ export const create = () => { title: `2D ray tracing`, date: `2020 Autumn`, figure: new Preview( - sdf2d, + sdf2dWebP, + sdf2dJpeg, 'https://sdf2d.schmelczer.dev', 'A webpage showcasing the SDF-2D project.' ), @@ -112,9 +139,9 @@ export const create = () => { title: `Video game on an ATtiny85`, date: `2020 Spring`, figure: new Video( - last(ad_astra_index.images).path, - adAstraMP4, - adAstraWEBM, + last(adAstraPoster.images).path, + adAstraMp4, + adAstraWebM, `controls playsinline preload="none"` ), description: new Text(`A simple game engine with a sample game set in space. The greatest challenge was to overcome @@ -142,8 +169,8 @@ export const create = () => { date: `2019 Autumn`, figure: new Video( null, - forexMP4, - forexWEBM, + forexMp4, + forexWebM, `autoplay loop muted playsinline controls` ), description: new Text( @@ -167,7 +194,11 @@ export const create = () => { { date: `2019 November`, title: `My Notes`, - figure: new Image(myNotes, `two screenshots of the application`), + figure: new Image( + myNotesWebP, + myNotesJpeg, + `two screenshots of the application` + ), description: new Text( `A minimalist note organizer and editor powered by Markwon.` ), @@ -189,7 +220,11 @@ export const create = () => { { date: `2018 October - November`, title: `Simulating the cooling system of a nuclear facility`, - figure: new Image(processSimulator, `a screenshot of the simulator`), + figure: new Image( + processSimulatorWebP, + processSimulatorJpeg, + `a screenshot of the simulator` + ), description: new Text( `Dynamically calculating the temperatures and flow velocities in a fluid-based cooling system based on a simple model.` @@ -212,7 +247,11 @@ export const create = () => { { date: `2018 October - November`, title: `Graph editing application`, - figure: new Image(processSimulatorInput, `a picture of the simulator's UI`), + figure: new Image( + processSimulatorInputWebP, + processSimulatorInputJpeg, + `a picture of the simulator's UI` + ), description: new Text( `An intuitive editor to create and edit input files for the nuclear facility simulator.` ), @@ -231,7 +270,11 @@ export const create = () => { { date: `2018 July - August`, title: `City simulation`, - figure: new Image(citySimulation, `a picture of a low-poly city`), + figure: new Image( + citySimulationWebP, + citySimulationJpeg, + `a picture of a low-poly city` + ), description: new Text( `Simulating a city where car crashes are more frequent than usual.` ), @@ -260,7 +303,7 @@ export const create = () => { { date: `2018 June`, title: `Photo colour grader`, - figure: new Image(colour, `a picture of the app`), + figure: new Image(colourWebP, colourJpeg, `a picture of the app`), description: new Text( `An innovative (at least I thought so) colour grader web application.` ), @@ -284,7 +327,7 @@ export const create = () => { { date: `2017 autumn`, title: `Platform game`, - figure: new Image(platform, `a picture of the app`), + figure: new Image(platformWebP, platformJpeg, `a picture of the app`), description: new Text( `A 3D game written in C with the help of SDL 1.2 (I haven't heard of GPU programming at the time).` ), @@ -300,7 +343,7 @@ export const create = () => { { date: `2016 summer`, title: `Photos`, - figure: new Image(photos, `a picture of the website`), + figure: new Image(photosWebP, photosJpeg, `a picture of the website`), description: new Text(`A simple web page where you can view my photos.`), links: [new Open('https://photo.schmelczer.dev')], }, @@ -308,9 +351,9 @@ export const create = () => { date: `2016 spring`, title: `Lights synchronised to music`, figure: new Video( - last(led.images).path, - ledMP4, - ledWEBM, + last(ledPoster.images).path, + ledMp4, + ledWebM, `controls playsinline preload="none"` ), description: new Text( diff --git a/src/static/media/andras-schmelczer-thesis.pdf b/src/static/media/andras_schmelczer_thesis.pdf similarity index 100% rename from src/static/media/andras-schmelczer-thesis.pdf rename to src/static/media/andras_schmelczer_thesis.pdf diff --git a/src/static/cv/cv_andras_schmelczer.pdf b/src/static/media/cv_andras_schmelczer.pdf similarity index 100% rename from src/static/cv/cv_andras_schmelczer.pdf rename to src/static/media/cv_andras_schmelczer.pdf diff --git a/webpack.config.js b/webpack.config.js index 70350d3..3e1e129 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -70,8 +70,8 @@ module.exports = (env, argv) => ({ options: { adapter: Sharp, outputPath: 'static/', - sizes: [200, 400, 800, 1200, 2000], - placeholder: false, + sizes: [200, 400, 800, 1200, 1600, 2000], + format: 'webp', }, }, { @@ -122,7 +122,6 @@ module.exports = (env, argv) => ({ test: /\.svg$/i, use: 'raw-loader', }, - { test: /\.scss$/i, use: [