diff --git a/src/data/ad-astra.ts b/src/data/ad-astra.ts
index 87eea44..a6982fe 100644
--- a/src/data/ad-astra.ts
+++ b/src/data/ad-astra.ts
@@ -1,16 +1,15 @@
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 adAstraMp4 from '../static/media/mp4/ad_astra.mp4';
+import adAstraWebM from '../static/media/webm/ad_astra.webm';
import { GitHub } from './shared';
-import { last } from '../helper/last';
import { Video } from '../page/basics/video/video';
export const adAstraTimelineElement = {
title: `Gaming on an ATtiny85`,
date: `2020 Spring`,
figure: new Video({
- poster: last(adAstraPoster.images)!.path,
+ poster: adAstraPoster,
mp4: adAstraMp4,
webm: adAstraWebM,
}),
diff --git a/src/data/city-simulation.ts b/src/data/city-simulation.ts
index 3cb0377..ce5e8ca 100644
--- a/src/data/city-simulation.ts
+++ b/src/data/city-simulation.ts
@@ -1,15 +1,14 @@
import citySimulationPoster from '../static/media/simulation.jpg?format=jpg';
-import citySimulationWebM from '../static/media/simulation.webm';
-import citySimulationMp4 from '../static/media/simulation.mp4';
+import citySimulationMp4 from '../static/media/mp4/simulation.mp4';
+import citySimulationWebM from '../static/media/webm/simulation.webm';
import { Video } from '../page/basics/video/video';
-import { last } from '../helper/last';
export const citySimulationTimelineElement = {
date: `2018 July - August`,
title: `City simulation`,
figure: new Video({
- poster: last(citySimulationPoster.images)!.path,
+ poster: citySimulationPoster,
mp4: citySimulationMp4,
webm: citySimulationWebM,
}),
diff --git a/src/data/forex.ts b/src/data/forex.ts
index ee06a88..d0d0a7c 100644
--- a/src/data/forex.ts
+++ b/src/data/forex.ts
@@ -1,14 +1,17 @@
-import forexMp4 from '../static/media/forex.mp4';
-import forexWebM from '../static/media/forex.webm';
+import forexMp4 from '../static/media/mp4/forex.mp4';
+import forexWebM from '../static/media/webm/forex.webm';
+import forexPoster from '../static/media/forex.jpg';
+
import { Video } from '../page/basics/video/video';
export const forexTimelineElement = {
title: `Predicting foreign exchange rates`,
date: `2019 Autumn`,
figure: new Video({
+ poster: forexPoster,
mp4: forexMp4,
webm: forexWebM,
- shouldActLikeGif: true,
+ invertButton: true,
}),
description: `
From the animation, we can see that my implementation does a somewhat acceptable job at
diff --git a/src/data/leds.ts b/src/data/leds.ts
index 0c482f2..a7e2972 100644
--- a/src/data/leds.ts
+++ b/src/data/leds.ts
@@ -1,15 +1,14 @@
import ledPoster from '../static/media/led.jpg?format=jpg';
-import ledMp4 from '../static/media/led.mp4';
-import ledWebM from '../static/media/led.webm';
+import ledMp4 from '../static/media/mp4/led.mp4';
+import ledWebM from '../static/media/webm/led.webm';
-import { last } from '../helper/last';
import { Video } from '../page/basics/video/video';
export const ledsTimelineElement = {
date: `2016 spring`,
title: `Lights synchronised to music`,
figure: new Video({
- poster: last(ledPoster.images)!.path,
+ poster: ledPoster,
mp4: ledMp4,
webm: ledWebM,
}),
diff --git a/src/page/background/background.scss b/src/page/background/background.scss
index e92879e..82105be 100644
--- a/src/page/background/background.scss
+++ b/src/page/background/background.scss
@@ -7,6 +7,7 @@
top: 0;
border-radius: 1000px;
transition: background-color var(--transition-time);
+ transform: translateX(-100%);
&:nth-child(odd) {
background-color: #fff9e0;
diff --git a/src/page/basics/image/image.html.ts b/src/page/basics/image/image.html.ts
index 09fab71..09590fc 100644
--- a/src/page/basics/image/image.html.ts
+++ b/src/page/basics/image/image.html.ts
@@ -16,7 +16,13 @@ export const generate = ({
alt: string;
container: boolean;
}): html => `
- ${container ? `
` : ''}
+ ${
+ container
+ ? `
`;
diff --git a/src/page/basics/preview/preview.scss b/src/page/basics/preview/preview.scss
index 1d2b6a0..868324c 100644
--- a/src/page/basics/preview/preview.scss
+++ b/src/page/basics/preview/preview.scss
@@ -9,27 +9,9 @@
left: 0;
top: 0;
- * {
+ iframe {
position: absolute;
left: 0;
- right: 0;
- }
-
- .load-button {
- @include image-button(var(--large-icon-size));
- @include absolute-center;
- @include square(calc(var(--large-icon-size) + var(--normal-margin) * 2));
-
- &:hover svg {
- box-shadow: var(--shadow);
- }
-
- svg {
- border-radius: 10000px;
- backdrop-filter: blur(16px);
- transition: transform var(--transition-time), box-shadow var(--transition-time);
- stroke: var(--normal-text-color);
- }
}
.loading {
@@ -54,9 +36,10 @@
&.loaded {
.figure-container,
- .load-button {
+ .start-button {
visibility: hidden;
}
+
.loading {
visibility: visible;
}
diff --git a/src/page/basics/preview/preview.ts b/src/page/basics/preview/preview.ts
index 36960e9..26abdcd 100644
--- a/src/page/basics/preview/preview.ts
+++ b/src/page/basics/preview/preview.ts
@@ -14,7 +14,7 @@ export class Preview extends PageElement {
super(createElement(generate({ alt })));
this.url += '?portfolioView';
this.attachElementByReplacing('.poster', new Image(posterWebP, posterJpeg, alt));
- this.query('.load-button').addEventListener('click', this.loadContent.bind(this));
+ this.query('.start-button').addEventListener('click', this.loadContent.bind(this));
}
public setParent(parent: PageElement) {
diff --git a/src/page/basics/video/video.html.ts b/src/page/basics/video/video.html.ts
index d691a26..c254041 100644
--- a/src/page/basics/video/video.html.ts
+++ b/src/page/basics/video/video.html.ts
@@ -1,26 +1,17 @@
import './video.scss';
-import { url } from '../../../types/url';
-import { html } from '../../../types/html';
-export const generate = ({
- webm,
- mp4,
- poster,
- shouldActLikeGif,
- container,
-}: {
- webm: url;
- mp4: url;
- poster?: url;
- shouldActLikeGif?: boolean;
- container?: boolean;
-}): html => `
- ${container === undefined || container ? `
`;
diff --git a/src/page/basics/video/video.scss b/src/page/basics/video/video.scss
index e69de29..dba155f 100644
--- a/src/page/basics/video/video.scss
+++ b/src/page/basics/video/video.scss
@@ -0,0 +1 @@
+@use '../../../style/mixins' as *;
diff --git a/src/page/basics/video/video.ts b/src/page/basics/video/video.ts
index ec94334..52551dd 100644
--- a/src/page/basics/video/video.ts
+++ b/src/page/basics/video/video.ts
@@ -2,15 +2,40 @@ import { PageElement } from '../../page-element';
import { createElement } from '../../../helper/create-element';
import { generate } from './video.html';
import { url } from '../../../types/url';
+import { ResponsiveImage } from '../../../types/responsive-image';
+
+export interface VideoParameters {
+ mp4: url;
+ webm: url;
+ poster: ResponsiveImage;
+ invertButton?: boolean;
+}
export class Video extends PageElement {
- public constructor(options: {
- poster?: url;
- mp4: url;
- webm: url;
- shouldActLikeGif?: boolean;
- container?: boolean;
- }) {
+ private video: HTMLVideoElement;
+
+ public constructor(options: VideoParameters) {
super(createElement(generate(options)));
+ this.video = this.query('video') as HTMLVideoElement;
+ this.video.addEventListener('click', this.startVideo.bind(this));
+ this.query('.start-button').addEventListener('click', this.startVideo.bind(this));
+ this.video.addEventListener('pause', this.stopVideo.bind(this));
+ }
+
+ private startVideo(e: Event) {
+ if (this.video.paused) {
+ this.query('.start-button').style.visibility = 'hidden';
+ this.video.play();
+ this.video.controls = true;
+ e.preventDefault();
+ }
+ }
+
+ private stopVideo(e: Event) {
+ if (this.video.paused) {
+ this.query('.start-button').style.visibility = 'visible';
+ this.video.controls = false;
+ e.preventDefault();
+ }
}
}
diff --git a/src/styles.scss b/src/styles.scss
index 617588b..0fed989 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -51,6 +51,26 @@ noscript {
@include center-children();
}
+.start-button {
+ @include image-button(var(--large-icon-size));
+ @include absolute-center;
+ @include square(calc(var(--large-icon-size) + var(--normal-margin) * 2));
+
+ &:hover svg {
+ box-shadow: var(--shadow);
+ }
+
+ svg {
+ border-radius: 10000px;
+ backdrop-filter: blur(16px);
+ transition: transform var(--transition-time), box-shadow var(--transition-time);
+ }
+
+ &.inverted svg {
+ fill: var(--accent-color);
+ }
+}
+
.figure-container {
font-size: 0;
box-shadow: var(--inset-shadow);
@@ -59,14 +79,19 @@ noscript {
cursor: pointer;
position: relative;
+ * {
+ pointer-events: auto;
+ }
+
img,
video,
iframe {
- pointer-events: auto;
- position: relative;
z-index: -1;
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
width: 100%;
- height: auto;
}
}