-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/arahmitz/adamblogstuff
- Loading branch information
Showing
8 changed files
with
359 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
lite-vimeo { | ||
background-color: #000; | ||
position: relative; | ||
display: block; | ||
contain: content; | ||
background-position: center center; | ||
background-size: cover; | ||
cursor: pointer; | ||
max-width: 720px; | ||
min-width: 480px; | ||
} | ||
|
||
/* gradient */ | ||
lite-vimeo::before { | ||
content: attr(data-title); | ||
display: block; | ||
position: absolute; | ||
top: 0; | ||
/* Pixel-perfect port of YT's gradient PNG, using https://github.com/bluesmoon/pngtocss plus optimizations */ | ||
background-image: linear-gradient(180deg, rgb(0 0 0 / 67%) 0%, rgb(0 0 0 / 54%) 14%, rgb(0 0 0 / 15%) 54%, rgb(0 0 0 / 5%) 72%, rgb(0 0 0 / 0%) 94%); | ||
height: 99px; | ||
width: 100%; | ||
font-family: "Youtube Noto",Roboto,Arial,Helvetica,sans-serif; | ||
color: hsl(0deg 0% 93.33%); | ||
text-shadow: 0 0 2px rgba(0,0,0,.5); | ||
font-size: 18px; | ||
padding: 25px 20px; | ||
overflow: hidden; | ||
white-space: nowrap; | ||
text-overflow: ellipsis; | ||
box-sizing: border-box; | ||
} | ||
|
||
lite-vimeo:hover::before { | ||
color: white; | ||
} | ||
|
||
/* responsive iframe with a 16:9 aspect ratio | ||
thanks https://css-tricks.com/responsive-iframes/ | ||
*/ | ||
lite-vimeo::after { | ||
content: ""; | ||
display: block; | ||
padding-bottom: calc(100% / (16 / 9)); | ||
} | ||
lite-vimeo > iframe { | ||
width: 100%; | ||
height: 100%; | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
border: 0; | ||
} | ||
|
||
/* play button */ | ||
lite-vimeo > .lty-playbtn { | ||
display: block; | ||
/* Make the button element cover the whole area for a large hover/click target… */ | ||
width: 100%; | ||
height: 100%; | ||
/* …but visually it's still the same size */ | ||
background: no-repeat center/68px 48px; | ||
/* YT's actual play button svg */ | ||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 48"><path d="M66.52 7.74c-.78-2.93-2.49-5.41-5.42-6.19C55.79.13 34 0 34 0S12.21.13 6.9 1.55c-2.93.78-4.63 3.26-5.42 6.19C.06 13.05 0 24 0 24s.06 10.95 1.48 16.26c.78 2.93 2.49 5.41 5.42 6.19C12.21 47.87 34 48 34 48s21.79-.13 27.1-1.55c2.93-.78 4.64-3.26 5.42-6.19C67.94 34.95 68 24 68 24s-.06-10.95-1.48-16.26z" fill="red"/><path d="M45 24 27 14v20" fill="white"/></svg>'); | ||
position: absolute; | ||
cursor: pointer; | ||
z-index: 1; | ||
filter: grayscale(100%); | ||
transition: filter .1s cubic-bezier(0, 0, 0.2, 1); | ||
border: 0; | ||
} | ||
|
||
lite-vimeo:hover > .lty-playbtn, | ||
lite-vimeo .lty-playbtn:focus { | ||
filter: none; | ||
} | ||
|
||
/* Post-click styles */ | ||
lite-vimeo.lyt-activated { | ||
cursor: unset; | ||
} | ||
lite-vimeo.lyt-activated::before, | ||
lite-vimeo.lyt-activated > .lty-playbtn { | ||
opacity: 0; | ||
pointer-events: none; | ||
} | ||
|
||
.lyt-visually-hidden { | ||
clip: rect(0 0 0 0); | ||
clip-path: inset(50%); | ||
height: 1px; | ||
overflow: hidden; | ||
position: absolute; | ||
white-space: nowrap; | ||
width: 1px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
const style = document.head.appendChild(document.createElement('style')); | ||
style.textContent = /*css*/` | ||
lite-vimeo { | ||
aspect-ratio: 16 / 9; | ||
background-color: #000; | ||
position: relative; | ||
display: block; | ||
contain: content; | ||
background-position: center center; | ||
background-size: cover; | ||
cursor: pointer; | ||
} | ||
lite-vimeo > iframe { | ||
width: 100%; | ||
height: 100%; | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
border: 0; | ||
} | ||
lite-vimeo > .ltv-playbtn { | ||
font-size: 10px; | ||
padding: 0; | ||
width: 6.5em; | ||
height: 4em; | ||
background: rgba(23, 35, 34, .75); | ||
z-index: 1; | ||
opacity: .8; | ||
border-radius: .5em; | ||
transition: opacity .2s ease-out, background .2s ease-out; | ||
outline: 0; | ||
border: 0; | ||
cursor: pointer; | ||
} | ||
lite-vimeo:hover > .ltv-playbtn { | ||
background-color: rgb(0, 173, 239); | ||
opacity: 1; | ||
} | ||
/* play button triangle */ | ||
lite-vimeo > .ltv-playbtn::before { | ||
content: ''; | ||
border-style: solid; | ||
border-width: 10px 0 10px 20px; | ||
border-color: transparent transparent transparent #fff; | ||
} | ||
lite-vimeo > .ltv-playbtn, | ||
lite-vimeo > .ltv-playbtn::before { | ||
position: absolute; | ||
top: 50%; | ||
left: 50%; | ||
transform: translate3d(-50%, -50%, 0); | ||
} | ||
/* Post-click styles */ | ||
lite-vimeo.ltv-activated { | ||
cursor: unset; | ||
} | ||
lite-vimeo.ltv-activated::before, | ||
lite-vimeo.ltv-activated > .ltv-playbtn { | ||
opacity: 0; | ||
pointer-events: none; | ||
} | ||
`; | ||
|
||
/** | ||
* Ported from https://github.com/paulirish/lite-youtube-embed | ||
* | ||
* A lightweight vimeo embed. Still should feel the same to the user, just MUCH faster to initialize and paint. | ||
* | ||
* Thx to these as the inspiration | ||
* https://storage.googleapis.com/amp-vs-non-amp/youtube-lazy.html | ||
* https://autoplay-youtube-player.glitch.me/ | ||
* | ||
* Once built it, I also found these: | ||
* https://github.com/ampproject/amphtml/blob/master/extensions/amp-youtube (👍👍) | ||
* https://github.com/Daugilas/lazyYT | ||
* https://github.com/vb/lazyframe | ||
*/ | ||
class LiteVimeo extends (globalThis.HTMLElement ?? class {}) { | ||
/** | ||
* Begin pre-connecting to warm up the iframe load | ||
* Since the embed's network requests load within its iframe, | ||
* preload/prefetch'ing them outside the iframe will only cause double-downloads. | ||
* So, the best we can do is warm up a few connections to origins that are in the critical path. | ||
* | ||
* Maybe `<link rel=preload as=document>` would work, but it's unsupported: http://crbug.com/593267 | ||
* But TBH, I don't think it'll happen soon with Site Isolation and split caches adding serious complexity. | ||
*/ | ||
static _warmConnections() { | ||
if (LiteVimeo.preconnected) return; | ||
LiteVimeo.preconnected = true; | ||
|
||
// The iframe document and most of its subresources come right off player.vimeo.com | ||
addPrefetch('preconnect', 'https://player.vimeo.com'); | ||
// Images | ||
addPrefetch('preconnect', 'https://i.vimeocdn.com'); | ||
// Files .js, .css | ||
addPrefetch('preconnect', 'https://f.vimeocdn.com'); | ||
// Metrics | ||
addPrefetch('preconnect', 'https://fresnel.vimeocdn.com'); | ||
} | ||
|
||
connectedCallback() { | ||
this.videoId = this.getAttribute('videoid'); | ||
|
||
/** | ||
* Lo, the vimeo placeholder image! (aka the thumbnail, poster image, etc) | ||
* We have to use the Vimeo API. | ||
*/ | ||
let { width, height } = getThumbnailDimensions(this.getBoundingClientRect()); | ||
let devicePixelRatio = window.devicePixelRatio || 1; | ||
if (devicePixelRatio >= 2) devicePixelRatio *= .75; | ||
width = Math.round(width * devicePixelRatio); | ||
height = Math.round(height * devicePixelRatio); | ||
|
||
fetch(`https://vimeo.com/api/v2/video/${this.videoId}.json`) | ||
.then(response => response.json()) | ||
.then(data => { | ||
let thumbnailUrl = data[0].thumbnail_large; | ||
thumbnailUrl = thumbnailUrl.replace(/-d_[\dx]+$/i, `-d_${width}x${height}`); | ||
this.style.backgroundImage = `url("${thumbnailUrl}")`; | ||
}); | ||
|
||
let playBtnEl = this.querySelector('.ltv-playbtn'); | ||
// A label for the button takes priority over a [playlabel] attribute on the custom-element | ||
this.playLabel = (playBtnEl && playBtnEl.textContent.trim()) || this.getAttribute('playlabel') || 'Play video'; | ||
|
||
if (!playBtnEl) { | ||
playBtnEl = document.createElement('button'); | ||
playBtnEl.type = 'button'; | ||
playBtnEl.setAttribute('aria-label', this.playLabel); | ||
playBtnEl.classList.add('ltv-playbtn'); | ||
this.append(playBtnEl); | ||
} | ||
playBtnEl.removeAttribute('href'); | ||
|
||
// On hover (or tap), warm up the TCP connections we're (likely) about to use. | ||
this.addEventListener('pointerover', LiteVimeo._warmConnections, { | ||
once: true | ||
}); | ||
|
||
// Once the user clicks, add the real iframe and drop our play button | ||
// TODO: In the future we could be like amp-youtube and silently swap in the iframe during idle time | ||
// We'd want to only do this for in-viewport or near-viewport ones: https://github.com/ampproject/amphtml/pull/5003 | ||
this.addEventListener('click', this.addIframe); | ||
} | ||
|
||
addIframe() { | ||
if (this.classList.contains('ltv-activated')) return; | ||
this.classList.add('ltv-activated'); | ||
|
||
const iframeEl = document.createElement('iframe'); | ||
iframeEl.width = 640; | ||
iframeEl.height = 360; | ||
// No encoding necessary as [title] is safe. https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#:~:text=Safe%20HTML%20Attributes%20include | ||
iframeEl.title = this.playLabel; | ||
iframeEl.allow = 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture'; | ||
// AFAIK, the encoding here isn't necessary for XSS, but we'll do it only because this is a URL | ||
// https://stackoverflow.com/q/64959723/89484 | ||
iframeEl.src = `https://player.vimeo.com/video/${encodeURIComponent(this.videoId)}?autoplay=1`; | ||
this.append(iframeEl); | ||
|
||
// Set focus for a11y | ||
iframeEl.addEventListener('load', iframeEl.focus, { once: true }); | ||
} | ||
} | ||
|
||
if (globalThis.customElements && !globalThis.customElements.get('lite-vimeo')) { | ||
globalThis.customElements.define('lite-vimeo', LiteVimeo); | ||
} | ||
|
||
/** | ||
* Add a <link rel={preload | preconnect} ...> to the head | ||
*/ | ||
function addPrefetch(kind, url, as) { | ||
const linkElem = document.createElement('link'); | ||
linkElem.rel = kind; | ||
linkElem.href = url; | ||
if (as) { | ||
linkElem.as = as; | ||
} | ||
linkElem.crossorigin = true; | ||
document.head.append(linkElem); | ||
} | ||
|
||
/** | ||
* Get the thumbnail dimensions to use for a given player size. | ||
* | ||
* @param {Object} options | ||
* @param {number} options.width The width of the player | ||
* @param {number} options.height The height of the player | ||
* @return {Object} The width and height | ||
*/ | ||
function getThumbnailDimensions({ width, height }) { | ||
let roundedWidth = width; | ||
let roundedHeight = height; | ||
|
||
// If the original width is a multiple of 320 then we should | ||
// not round up. This is to keep the native image dimensions | ||
// so that they match up with the actual frames from the video. | ||
// | ||
// For example 640x360, 960x540, 1280x720, 1920x1080 | ||
// | ||
// Round up to nearest 100 px to improve cacheability at the | ||
// CDN. For example, any width between 601 pixels and 699 | ||
// pixels will render the thumbnail at 700 pixels width. | ||
if (roundedWidth % 320 !== 0) { | ||
roundedWidth = Math.ceil(width / 100) * 100; | ||
roundedHeight = Math.round((roundedWidth / width) * height); | ||
} | ||
|
||
return { | ||
width: roundedWidth, | ||
height: roundedHeight | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
+++ | ||
title = 'Talks' | ||
languageCode = 'en-us' | ||
draft = false | ||
showAuthor = false | ||
showDate = false | ||
showReadingTime = false | ||
showZenmode = false | ||
sharingLinks = false | ||
heroStyle = "background" | ||
+++ | ||
|
||
## Animacyjne Dojo (PL) | ||
![Animacyjne Dojo Cover](/images/talks/animacyjnedojo_cover.jpg "[Presentation available here](https://docs.google.com/presentation/d/e/2PACX-1vSADucq-Mkmv9_flTBaHDkf3mogJBdUehcg0T6xx7BUkQURv_w4KIVLAtIQUPArO64mrpnpCvUndw5F/pub?start=false&loop=false&delayms=3000)") | ||
|
||
*Animacyjne Dojo* is a presentation I gave for Digital Night Studio at Lodz University of Technology, focusing on gameplay animation. It provides an overview of the fundamental principles from a gameplay animator's perspective, | ||
addresing daily tasks and unique challanges. The presentation covers essential animation exeercises such as *the bouncing ball* and *tails/squirrel*, offering tips and tricks for each. It concludes with resources and guidance for those | ||
looking to learn animation and start their careers in the field. (*Presentation in Polish*) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.