Fix video loading
This commit is contained in:
parent
a39c8c9350
commit
4b11edfbd9
9 changed files with 80 additions and 16 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import adAstraPoster from '../static/media/ad_astra.jpg?format=jpg';
|
import adAstraWebP from '../static/media/ad_astra.jpg?format=webp';
|
||||||
|
import adAstraJpeg from '../static/media/ad_astra.jpg?format=jpg';
|
||||||
import adAstraMp4 from '../static/media/mp4/ad_astra.mp4';
|
import adAstraMp4 from '../static/media/mp4/ad_astra.mp4';
|
||||||
import adAstraWebM from '../static/media/webm/ad_astra.webm';
|
import adAstraWebM from '../static/media/webm/ad_astra.webm';
|
||||||
|
|
||||||
|
|
@ -9,7 +10,8 @@ export const adAstraTimelineElement = {
|
||||||
title: `Gaming on an ATtiny85`,
|
title: `Gaming on an ATtiny85`,
|
||||||
date: `2020 Spring`,
|
date: `2020 Spring`,
|
||||||
figure: new Video({
|
figure: new Video({
|
||||||
poster: adAstraPoster,
|
posterWebP: adAstraWebP,
|
||||||
|
posterJpeg: adAstraJpeg,
|
||||||
mp4: adAstraMp4,
|
mp4: adAstraMp4,
|
||||||
webm: adAstraWebM,
|
webm: adAstraWebM,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import citySimulationPoster from '../static/media/simulation.jpg?format=jpg';
|
import citySimulationPosterWebP from '../static/media/simulation.jpg?format=webp';
|
||||||
|
import citySimulationPosterJpeg from '../static/media/simulation.jpg?format=jpg';
|
||||||
import citySimulationMp4 from '../static/media/mp4/simulation.mp4';
|
import citySimulationMp4 from '../static/media/mp4/simulation.mp4';
|
||||||
import citySimulationWebM from '../static/media/webm/simulation.webm';
|
import citySimulationWebM from '../static/media/webm/simulation.webm';
|
||||||
|
|
||||||
|
|
@ -8,7 +9,8 @@ export const citySimulationTimelineElement = {
|
||||||
date: `2018 July - August`,
|
date: `2018 July - August`,
|
||||||
title: `City simulation`,
|
title: `City simulation`,
|
||||||
figure: new Video({
|
figure: new Video({
|
||||||
poster: citySimulationPoster,
|
posterWebP: citySimulationPosterWebP,
|
||||||
|
posterJpeg: citySimulationPosterJpeg,
|
||||||
mp4: citySimulationMp4,
|
mp4: citySimulationMp4,
|
||||||
webm: citySimulationWebM,
|
webm: citySimulationWebM,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
import forexPosterWebP from '../static/media/forex.jpg?format=webp';
|
||||||
|
import forexPosterJpeg from '../static/media/forex.jpg?format=jpg';
|
||||||
import forexMp4 from '../static/media/mp4/forex.mp4';
|
import forexMp4 from '../static/media/mp4/forex.mp4';
|
||||||
import forexWebM from '../static/media/webm/forex.webm';
|
import forexWebM from '../static/media/webm/forex.webm';
|
||||||
import forexPoster from '../static/media/forex.jpg';
|
|
||||||
|
|
||||||
import { Video } from '../page/basics/video/video';
|
import { Video } from '../page/basics/video/video';
|
||||||
|
|
||||||
|
|
@ -8,7 +9,8 @@ export const forexTimelineElement = {
|
||||||
title: `Predicting foreign exchange rates`,
|
title: `Predicting foreign exchange rates`,
|
||||||
date: `2019 Autumn`,
|
date: `2019 Autumn`,
|
||||||
figure: new Video({
|
figure: new Video({
|
||||||
poster: forexPoster,
|
posterWebP: forexPosterWebP,
|
||||||
|
posterJpeg: forexPosterJpeg,
|
||||||
mp4: forexMp4,
|
mp4: forexMp4,
|
||||||
webm: forexWebM,
|
webm: forexWebM,
|
||||||
invertButton: true,
|
invertButton: true,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import ledPoster from '../static/media/led.jpg?format=jpg';
|
import ledPosterWebP from '../static/media/led.jpg?format=webp';
|
||||||
|
import ledPosterJpeg from '../static/media/led.jpg?format=jpg';
|
||||||
import ledMp4 from '../static/media/mp4/led.mp4';
|
import ledMp4 from '../static/media/mp4/led.mp4';
|
||||||
import ledWebM from '../static/media/webm/led.webm';
|
import ledWebM from '../static/media/webm/led.webm';
|
||||||
|
|
||||||
|
|
@ -8,7 +9,8 @@ export const ledsTimelineElement = {
|
||||||
date: `2016 spring`,
|
date: `2016 spring`,
|
||||||
title: `Lights synchronised to music`,
|
title: `Lights synchronised to music`,
|
||||||
figure: new Video({
|
figure: new Video({
|
||||||
poster: ledPoster,
|
posterWebP: ledPosterWebP,
|
||||||
|
posterJpeg: ledPosterJpeg,
|
||||||
mp4: ledMp4,
|
mp4: ledMp4,
|
||||||
webm: ledWebM,
|
webm: ledWebM,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import platformJpeg from '../static/media/platform.png?format=jpg';
|
import platformPosterWebP from '../static/media/platform.png?format=webp';
|
||||||
|
import platformPosterJpeg from '../static/media/platform.png?format=jpg';
|
||||||
import platformMp4 from '../static/media/mp4/platform.mp4';
|
import platformMp4 from '../static/media/mp4/platform.mp4';
|
||||||
import platformWebM from '../static/media/webm/platform.webm';
|
import platformWebM from '../static/media/webm/platform.webm';
|
||||||
|
|
||||||
|
|
@ -8,7 +9,8 @@ export const platformGameTimelineElement = {
|
||||||
date: `2017 autumn`,
|
date: `2017 autumn`,
|
||||||
title: `Platform game`,
|
title: `Platform game`,
|
||||||
figure: new Video({
|
figure: new Video({
|
||||||
poster: platformJpeg,
|
posterWebP: platformPosterWebP,
|
||||||
|
posterJpeg: platformPosterJpeg,
|
||||||
mp4: platformMp4,
|
mp4: platformMp4,
|
||||||
webm: platformWebM,
|
webm: platformWebM,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { html } from '../../../types/html';
|
||||||
|
|
||||||
export const generate = ({ alt }: { alt: string }): html => `
|
export const generate = ({ alt }: { alt: string }): html => `
|
||||||
<div class="preview">
|
<div class="preview">
|
||||||
<img image-viewer-ignore class="poster" />
|
<img image-viewer-ignore class="poster"/>
|
||||||
<div class="overlay">
|
<div class="overlay">
|
||||||
<div class="loading">${loading}</div>
|
<div class="loading">${loading}</div>
|
||||||
<iframe title="${alt}" allowfullscreen loading="lazy"></iframe>
|
<iframe title="${alt}" allowfullscreen loading="lazy"></iframe>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,23 @@
|
||||||
import './video.scss';
|
import './video.scss';
|
||||||
|
|
||||||
|
import loading from '../../../static/icons/loading.svg';
|
||||||
|
|
||||||
import { html } from '../../../types/html';
|
import { html } from '../../../types/html';
|
||||||
import play from '../../../static/icons/play-button.svg';
|
import play from '../../../static/icons/play-button.svg';
|
||||||
import { VideoParameters } from './video';
|
import { VideoParameters } from './video';
|
||||||
import { last } from '../../../helper/last';
|
|
||||||
|
|
||||||
export const generate = ({ webm, mp4, poster, invertButton }: VideoParameters): html => `
|
export const generate = ({
|
||||||
<div class="figure-container" style="padding-top:${(poster.height / poster.width) *
|
webm,
|
||||||
|
mp4,
|
||||||
|
posterJpeg,
|
||||||
|
invertButton,
|
||||||
|
}: VideoParameters): html => `
|
||||||
|
<div class="figure-container video-container" style="padding-top:${(posterJpeg.height /
|
||||||
|
posterJpeg.width) *
|
||||||
100}%">
|
100}%">
|
||||||
<video playsinline preload="none" poster="${last(poster.images)!.path}">
|
<img image-viewer-ignore class="poster"/>
|
||||||
|
<div class="loading">${loading}</div>
|
||||||
|
<video playsinline preload="none">
|
||||||
<source src="${webm}" type="video/webm"/>
|
<source src="${webm}" type="video/webm"/>
|
||||||
<source src="${mp4}" type="video/mp4"/>
|
<source src="${mp4}" type="video/mp4"/>
|
||||||
</video>
|
</video>
|
||||||
|
|
|
||||||
|
|
@ -1 +1,35 @@
|
||||||
@use '../../../style/mixins' as *;
|
@use '../../../style/mixins' as *;
|
||||||
|
|
||||||
|
.video-container {
|
||||||
|
& > *:not(.start-button) {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
@include square(var(--large-icon-size));
|
||||||
|
@include absolute-center;
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
& > svg {
|
||||||
|
@include square(var(--large-icon-size));
|
||||||
|
@include absolute-center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
z-index: 1;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.loaded .loading {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fully-loaded video {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
import { PageElement } from '../../page-element';
|
import { PageElement } from '../../page-element';
|
||||||
import { createElement } from '../../../helper/create-element';
|
import { createElement } from '../../../helper/create-element';
|
||||||
import { generate } from './video.html';
|
import { generate } from './video.html';
|
||||||
|
import { Image } from '../image/image';
|
||||||
import { url } from '../../../types/url';
|
import { url } from '../../../types/url';
|
||||||
import { ResponsiveImage } from '../../../types/responsive-image';
|
import { ResponsiveImage } from '../../../types/responsive-image';
|
||||||
|
|
||||||
export interface VideoParameters {
|
export interface VideoParameters {
|
||||||
mp4: url;
|
mp4: url;
|
||||||
webm: url;
|
webm: url;
|
||||||
poster: ResponsiveImage;
|
posterWebP: ResponsiveImage;
|
||||||
|
posterJpeg: ResponsiveImage;
|
||||||
invertButton?: boolean;
|
invertButton?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -16,8 +18,16 @@ export class Video extends PageElement {
|
||||||
|
|
||||||
public constructor(options: VideoParameters) {
|
public constructor(options: VideoParameters) {
|
||||||
super(createElement(generate(options)));
|
super(createElement(generate(options)));
|
||||||
|
this.attachElementByReplacing(
|
||||||
|
'.poster',
|
||||||
|
new Image(options.posterWebP, options.posterJpeg, `thumbnail for the video`, false)
|
||||||
|
);
|
||||||
|
|
||||||
this.video = this.query('video') as HTMLVideoElement;
|
this.video = this.query('video') as HTMLVideoElement;
|
||||||
this.video.addEventListener('click', this.startVideo.bind(this));
|
this.video.addEventListener('click', this.startVideo.bind(this));
|
||||||
|
this.video.addEventListener('play', () =>
|
||||||
|
this.htmlRoot.classList.add('fully-loaded')
|
||||||
|
);
|
||||||
this.query('.start-button').addEventListener('click', this.startVideo.bind(this));
|
this.query('.start-button').addEventListener('click', this.startVideo.bind(this));
|
||||||
this.video.addEventListener('pause', this.stopVideo.bind(this));
|
this.video.addEventListener('pause', this.stopVideo.bind(this));
|
||||||
}
|
}
|
||||||
|
|
@ -25,6 +35,7 @@ export class Video extends PageElement {
|
||||||
private startVideo(e: Event) {
|
private startVideo(e: Event) {
|
||||||
if (this.video.paused) {
|
if (this.video.paused) {
|
||||||
this.query('.start-button').style.visibility = 'hidden';
|
this.query('.start-button').style.visibility = 'hidden';
|
||||||
|
this.htmlRoot.classList.add('loaded');
|
||||||
this.video.play();
|
this.video.play();
|
||||||
this.video.controls = true;
|
this.video.controls = true;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue