From 60aaaf7132e479e9f715564ee011cd47e70cb3ee Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Sun, 27 Nov 2022 00:53:36 +0100 Subject: [PATCH] Significantly improve the media player UX --- _includes/blocks/media.liquid | 150 ++++++++--------- .../2022-01-10-h264-encoder-showdown.html | 21 +-- _sass/_block-media.scss | 158 +++++++++++------- assets/site.js | 79 ++++----- 4 files changed, 224 insertions(+), 184 deletions(-) diff --git a/_includes/blocks/media.liquid b/_includes/blocks/media.liquid index 93a281b..c6c2dfa 100644 --- a/_includes/blocks/media.liquid +++ b/_includes/blocks/media.liquid @@ -1,85 +1,81 @@ +{% assign file_info = site.static_files | where: "path", include.url %} {% capture content %} -{% if include.player %} -
- -
-
- -
+ {% if include.player %} +
+ +
+
+ 0:00 / 0:00 -
-
+
- -
-{% endif %} -{% if include.link %}{% endif %} -{% assign file_info = site.static_files | where: "path", include.url %} -{% if include.type == "image" %} - - {% if include.lazyload %}{% endif %} - -{% elsif include.type == "video" %} - -{% elsif include.type == "audio" %} - -{% endif %} -{% if include.link %} - -{% endif %} -{% if include.caption %} -
{{ include.caption }}
-{% endif %} + {% endif %} + {% if include.link %}{% endif %} + {% if include.type == "image" %} + + {% if include.lazyload %}{% endif %} + + {% if include.content %}{{include.content}}{% endif %} + + {% elsif include.type == "video" %} + + {% elsif include.type == "audio" %} + + {% endif %} + {% if include.link %}{% endif %} + {% if include.caption %}
{{ include.caption }}
{% endif %} {% endcapture %} -{% if include.player %} -{% assign class = include.type | append: " player" %} -{% else %} -{% assign class = include.type %} -{% endif %} +{% if include.player %}{% assign class = include.type | append: " player" %}{% else %}{% assign class = include.type %}{% endif %} {% include blocks/_base.liquid type="media" class=class content=content float=include.float align=include.align id=include.id %} \ No newline at end of file diff --git a/_posts/2022/2022-01-10-h264-encoder-showdown.html b/_posts/2022/2022-01-10-h264-encoder-showdown.html index f622a41..4310716 100644 --- a/_posts/2022/2022-01-10-h264-encoder-showdown.html +++ b/_posts/2022/2022-01-10-h264-encoder-showdown.html @@ -68,16 +68,17 @@ videos: {% for video in page.videos.videos %} {% capture capture_video %} - {% include blocks/media.liquid type="video" caption=caption poster=video.poster muted=true preload="none" id=video.id player=true %} - {% endcapture %} {% include blocks/details.liquid title=video.name content=capture_video level=1 open=true %} diff --git a/_sass/_block-media.scss b/_sass/_block-media.scss index 9bfdabf..2e622ed 100644 --- a/_sass/_block-media.scss +++ b/_sass/_block-media.scss @@ -8,6 +8,8 @@ .block-media > a > .content, .block-media > .content { + object-fit: contain; + object-position: center center; } .block-media > figcaption { @@ -22,6 +24,7 @@ // -------------------------------------------------------------------------------- // Block: Media Player // -------------------------------------------------------------------------------- +$media-player-button-size: 1.5rem; .block-media.hide { cursor: none; @@ -29,144 +32,181 @@ .block-media > .top, .block-media > .bottom { + display: block; margin: 0; - padding: 0.5rem .5rem; + padding: 0.2rem 0.5rem; } .block-media > .top { - background: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 80%); position: absolute; top: 0; left: 0; right: 0; - display: grid; - grid-template-columns: 1; - grid-template-rows: 1; - justify-content: stretch; + + padding-bottom: 1rem; + + display: flex; + flex-flow: row nowrap; + justify-content: space-between; align-items: stretch; - gap: 0; - transition: top ease-in-out 333ms, opacity ease-in-out 333ms; + align-content: stretch; + gap: 0.5rem; + + background: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 80%); + transition: top ease-in-out 100ms, opacity ease-in-out 100s; opacity: 1.0; + + overflow: hidden; + user-select: none; } .block-media.hide > .top { top: -100%; opacity: 0.0; + transition: top ease-in-out 500ms, opacity ease-in-out 500s; } .block-media > .top > .variant { - // ToDo: Style this + flex-grow: 1; } .block-media > .bottom { - background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 80%); position: absolute; bottom: 0; left: 0; right: 0; - display: grid; - grid-template-columns: max-content 1fr max-content max-content; - justify-content: stretch; + + padding-top: 1rem; + + display: flex; + flex-flow: row nowrap; + justify-content: space-between; align-items: stretch; + align-content: stretch; gap: 0.5rem; + + background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 80%); + transition: top ease-in-out 100ms, opacity ease-in-out 100s; + opacity: 1.0; + overflow: hidden; user-select: none; - transition: bottom ease-in-out 333ms, opacity ease-in-out 333ms; - opacity: 1.0; } .block-media.hide > .bottom { bottom: -100%; + opacity: 0.0; + transition: top ease-in-out 500ms, opacity ease-in-out 500s; } .block-media > .bottom > .play { - width: 2rem; - height: 2rem; + flex-grow: 0; + display: block; margin: 0; padding: 0; - font-size: 2rem; - line-height: 2rem; + width: $media-player-button-size; + height: $media-player-button-size; + font-size: $media-player-button-size; + line-height: $media-player-button-size; text-align: center; user-select: none; } .block-media > .bottom > .play.playing { } -.block-media > .bottom > .playback { +.block-media > .bottom > .time { margin: 0; padding: 0; - display: grid; - grid-template-columns: max-content 1fr max-content; - justify-content: stretch; - align-items: stretch; - gap: 0.5rem; - user-select: none; -} + width: auto; + height: $media-player-button-size; + flex-grow: 0; + flex-shrink: 0; + flex-basis: auto; -.block-media > .bottom > .playback > .time { display: block; - height: 2rem; - margin: 0; - padding: 0; text-align: right; - line-height: 2rem; + line-height: $media-player-button-size; user-select: auto; } -.block-media > .bottom > .playback > .progress { - display: block; +.block-media > .bottom > .progress { margin: 0; padding: 0; width: auto; + min-width: 5rem; height: 100%; - user-select: none; -} + flex-grow: 5; + flex-shrink: 1; -.block-media > .bottom > .audio { - margin: 0; - padding: 0; - display: grid; - grid-template-columns: max-content 1fr; - justify-content: stretch; - align-items: stretch; - gap: 0.5rem; - user-select: none; -} - -.block-media > .bottom > .audio > .mute { display: block; + user-select: none; +} +.block-media > .bottom > .mute { margin: 0; padding: 0; - width: 2rem; - height: 2rem; - font-size: 2rem; - line-height: 2rem; + width: $media-player-button-size; + height: $media-player-button-size; + flex-grow: 0; + flex-shrink: 0; + flex-basis: auto; + + display: block; + font-size: $media-player-button-size; + line-height: $media-player-button-size; text-align: center; user-select: none; } -.block-media > .bottom > .audio > .mute.muted { +.block-media > .bottom > .mute.muted { } -.block-media > .bottom > .audio > .volume { - display: block; +.block-media > .bottom > .volume { margin: 0; padding: 0; width: auto; + min-width: 3rem; + max-width: 6rem; height: 100%; + flex-grow: 1; + flex-shrink: 5; + flex-basis: auto; + + display: block; user-select: none; } .block-media > .bottom > .fullscreen { - width: 2rem; - height: 2rem; margin: 0; padding: 0; - font-size: 2rem; - line-height: 2rem; + width: $media-player-button-size; + height: $media-player-button-size; + flex-grow: 0; + flex-shrink: 0; + flex-basis: auto; + + display: block; + font-size: $media-player-button-size; + line-height: $media-player-button-size; text-align: center; user-select: none; } +@media (max-width: 500px) { + .block-media > .bottom > .time { + display: none; + } +} +@media (max-width: 350px) { + .block-media > .bottom > .volume { + display: none; + } +} +@media (max-width: 250px) { + .block-media > .bottom > .play, + .block-media > .bottom > .mute, + .block-media > .bottom > .fullscreen { + display: none; + } +} // -------------------------------------------------------------------------------- // Block: Media > Audio diff --git a/assets/site.js b/assets/site.js index 3e814c9..d096a1a 100644 --- a/assets/site.js +++ b/assets/site.js @@ -23,7 +23,7 @@ async function xmr_initialize_player(el) { el.querySelector("audio"); // Play/Pause - let play_pause = el.querySelector(".bottom > .play"); + let play_pause = el.querySelector(".play"); play_pause.update = function() { if (media.paused) { play_pause.classList.remove("playing"); @@ -50,7 +50,7 @@ async function xmr_initialize_player(el) { play_pause.update(); // Mute - let audio_mute = el.querySelector(".bottom > .audio > .mute"); + let audio_mute = el.querySelector(".mute"); audio_mute.update = function() { if (media.muted) { audio_mute.classList.add("muted"); @@ -75,7 +75,7 @@ async function xmr_initialize_player(el) { audio_mute.update(); // Volume - let audio_volume = el.querySelector(".bottom > .audio > .volume"); + let audio_volume = el.querySelector(".volume"); audio_volume.min = 0; audio_volume.max = 2147483647; audio_volume.update = function() { @@ -102,7 +102,7 @@ async function xmr_initialize_player(el) { audio_volume.update(); // Time - let playback_time = el.querySelector(".bottom > .playback > .time"); + let playback_time = el.querySelector(".time"); playback_time.update = function() { let duration_text = ""; let need_hour = false; @@ -153,7 +153,7 @@ async function xmr_initialize_player(el) { playback_time.update(); // Progress - let playback_progress = el.querySelector(".bottom > .playback > .progress"); + let playback_progress = el.querySelector(".progress"); playback_progress.update = function() { playback_progress.disabled = !media.seekable; playback_progress.min = 0; @@ -188,39 +188,6 @@ async function xmr_initialize_player(el) { }); fullscreen.update(); - // Variants - let variants = el.querySelector(".variant"); - variants.addEventListener("input", () => { - media.pause(); - play_pause.update(); - media.src = variants.value; - }); - variants.addEventListener("value", () => { - media.pause(); - play_pause.update(); - media.src = variants.value; - }); - function createVariants(el, key, value) { - if (typeof(value) === "object") { - for (let k in value) { - let v = value[k]; - createVariants(el, `${key} / ${k}`, v); - } - } else if (typeof(value) === "string") { - let option = document.createElement("option"); - option.value = value; - option.textContent = key; - el.appendChild(option); - } else { - el.appendChild(document.createElement(typeof(value))); - } - } - for (let k in el.variants) { - let v = el.variants[k]; - createVariants(variants, k, v); - } - variants.value = media.src = variants.querySelectorAll("option")[0].value; - // Media Play/Pause by click media.addEventListener("click", () => { play_pause.click(); @@ -257,6 +224,42 @@ async function xmr_initialize_player(el) { } }); el.hideOverlay(); + + // Variants + let variant = el.querySelector(".variant"); + variant.update = function() { + let paused = media.paused; + let muted = media.muted; + let volume = media.volume; + let time = media.currentTime; + + media.pause(); + media.currentSrc = variant.value; + media.play(); + + media.currentTime = time; + media.volume = volume; + media.muted = muted; + if (paused) { + media.pause(); + } else { + media.play(); + } + + play_pause.update(); + } + variant.addEventListener("input", () => { variant.update(); }); + variant.addEventListener("value", () => { variant.update(); }); + + // Add options from available sources. + let sources = el.querySelectorAll("source"); + for (let k of sources) { + let option = document.createElement("option"); + option.value = k.src; + option.textContent = k.title; + variant.appendChild(option); + } + variant.value = media.currentSrc; } async function xmr_initialize_players() {