Last active
January 10, 2024 19:45
-
-
Save ryandejaegher/e3f4b406d50140d3d2e2d2065e9cf52f to your computer and use it in GitHub Desktop.
Knockout Video #web-component #squarespace
This file contains hidden or 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
| { | |
| "scripts": [], | |
| "styles": [] | |
| } |
This file contains hidden or 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
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>Document</title> | |
| </head> | |
| <body> | |
| Yes | |
| <video-text | |
| video-src="https://static1.squarespace.com/static/5ff1ec940400f40890097046/t/602aa4aeef4fdf139f943ab1/1613407407624/Girl+Surfer+Observes+the+Surfers+in+the+Sea.mp4" | |
| > | |
| <h2 slot="text">SURF SURF</h2> | |
| <h2 slot="text">WAVES</h2> | |
| <h2 slot="text">ALL DAY</h2> | |
| </video-text> | |
| <div class="container"></div> | |
| <div class="big-block"></div> | |
| <!--Based off https://codepen.io/jonathanedempsey/pen/YzyRaKj--> | |
| <div class="block"> | |
| <div class="overlay"> | |
| <video | |
| src="https://static1.squarespace.com/static/5ff1ec940400f40890097046/t/602aa4aeef4fdf139f943ab1/1613407407624/Girl+Surfer+Observes+the+Surfers+in+the+Sea.mp4" | |
| autoplay | |
| ></video> | |
| </div> | |
| <div class="text-container"> | |
| <h1>SURF LIFE</h1> | |
| </div> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or 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
| // TODO Add Intersection Observer for video so it only loads when necessary | |
| // TODO If video is in view load and play | |
| // TODO If video is out of view pause | |
| // TODO What if the video doesn't play on mobile? | |
| // TODO Add slot for text | |
| // TODO Add att | |
| // TODO Add ability to customize overlay color | |
| // TODO Add ability to remove overlay | |
| // TODO Add ability to add border | |
| // TODO Add ability to | |
| (function () { | |
| // Create the template for the component | |
| const template = document.createElement('template'); | |
| template.innerHTML = ` | |
| <style> | |
| :host { | |
| display: block; | |
| height: 100%; | |
| } | |
| :host([invert]) ::slotted(*) { | |
| color: white; | |
| } | |
| :host([invert]) .text-container { | |
| background: black; | |
| mix-blend-mode:multiply; | |
| } | |
| .block { | |
| height: 100%; | |
| position: relative; | |
| } | |
| .video-overlay { | |
| width: 100%; | |
| height: 100%; | |
| overflow: hidden; | |
| // background: hsla(200,80%,50%,1); | |
| } | |
| .text-container { | |
| position: absolute; | |
| background: white; | |
| width:100%; | |
| height: 100%; | |
| top: 0; | |
| left: 0; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| mix-blend-mode: screen; | |
| overflow: hidden; | |
| } | |
| ::slotted(*) { | |
| margin: 0; | |
| color: black; | |
| z-index: 2; | |
| // border: 8px solid black; | |
| // padding: 40px; | |
| // border-radius: 4px; | |
| } | |
| video { | |
| width: 100%; | |
| height: 100%; | |
| display: block; | |
| object-fit: cover; | |
| // mix-blend-mode: overlay; | |
| } | |
| </style> | |
| <div class="block"> | |
| <div class="video-overlay"> | |
| <video data-src autoplay loop playsinline></video> | |
| </div> | |
| <div class="text-container"> | |
| <slot name="text"></slot> | |
| </div> | |
| </div> | |
| ` | |
| class VideoText extends HTMLElement { | |
| // Always call super first in constrcutor | |
| constructor() { | |
| super(); | |
| // Create shadow root | |
| this.attachShadow({ | |
| mode: 'open' | |
| }); | |
| // Insert the template into the shadow Root/DOM | |
| this.shadowRoot.append(template.content.cloneNode(true)); | |
| this._video = this.shadowRoot.querySelector('video'); | |
| this._text = this.shadowRoot.querySelector('.text-container'); | |
| // this.observerCallback = this.observerCallback.bind(this); | |
| this.observer = new IntersectionObserver(this.observerCallback, { | |
| rootMargin: "0px 0px 0px 0px", | |
| threshold:[0,0.25,.4,.5] | |
| }) | |
| } | |
| loadVideo() { | |
| if(this._video.src === '') { | |
| this._video.src = this._video.dataset.src | |
| console.log(this._video.src); | |
| } | |
| } | |
| pauseVideo() { | |
| this._video.pause() | |
| console.log('video paused') | |
| } | |
| playVideo() { | |
| this._video.play() | |
| console.log('video play') | |
| } | |
| fadeIn() { | |
| this._video.animate([{ | |
| opacity: 1 | |
| }], { | |
| duration: 700, | |
| fill: 'forwards' | |
| }) | |
| console.log('fade in') | |
| } | |
| fadeOut() { | |
| this._video.animate([{ | |
| opacity: 0 | |
| }], { | |
| duration: 700, | |
| fill: 'forwards' | |
| }) | |
| console.log('fade out') | |
| } | |
| observerCallback = (entries) => { | |
| entries.forEach(entry => { | |
| if(entry.isIntersecting) { | |
| this.loadVideo(); | |
| console.log(entry.intersectionRatio) | |
| } | |
| if(entry.intersectionRatio > 0.1) { | |
| this.playVideo() | |
| } else { | |
| this.pauseVideo() | |
| } | |
| if(entry.intersectionRatio >= 0.5) { | |
| this.fadeIn(); | |
| } else { | |
| this.fadeOut(); | |
| } | |
| }) | |
| } | |
| get text() { | |
| return this.getAttribute('text') | |
| } | |
| set text(newValue) { | |
| this.setAttribute('text', newValue) | |
| } | |
| get video() { | |
| return this.getAttribute('video-src'); | |
| } | |
| set video(newValue) { | |
| this.setAttribute('video-src', newValue) | |
| } | |
| // Web Component lifecycle callbacks | |
| // Runs as soon as the component is used in document | |
| connectedCallback() { | |
| console.log('I have been added to the document') | |
| this._video.dataset.src = this.video; | |
| this.observer.observe(this); | |
| } | |
| // Runs as soon as the component is removed or disconnected from the document | |
| disconnectedCallback() { | |
| console.log('I have been removed') | |
| } | |
| // Runs when the component is moved within the document | |
| adoptedCallback() { | |
| console.log('I have moved') | |
| } | |
| // Runs when one of the documents observed elements is changed in some way | |
| attributeChangedCallback(name, oldValue, newValue) { | |
| console.log('My attributes have changed') | |
| console.log(`${name} changed from ${oldValue} to ${newValue}`) | |
| } | |
| // You need to list the attributes you want to observe in order for the attributeChangedCallback to work | |
| // This should return an array containing the names of the attributes you want to observe | |
| static get observedAttributes() { | |
| return ['video-src'] | |
| } | |
| } | |
| window.customElements.define('video-text', VideoText); | |
| })(); |
This file contains hidden or 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
| *, | |
| *:before, | |
| *:after { | |
| box-sizing: border-box; | |
| } | |
| html,body { | |
| width: 100%; | |
| height: 100%; | |
| margin: 0; | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; | |
| } | |
| .big-block { | |
| height: 100vh; | |
| } | |
| .flex { | |
| display: flex; | |
| } | |
| .flex-col { | |
| flex-direction: column; | |
| } | |
| .block { | |
| height: 100%; | |
| position: relative; | |
| } | |
| .overlay { | |
| width: 100%; | |
| height: 100%; | |
| overflow: hidden; | |
| background: hsla(200,80%,50%,1); | |
| } | |
| .text-container { | |
| position: absolute; | |
| background: white; | |
| width:100%; | |
| height: 100%; | |
| top: 0; | |
| left: 0; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| mix-blend-mode: screen; | |
| overflow: hidden; | |
| } | |
| h1 { | |
| margin: 0; | |
| font-weight: 800; | |
| font-style: italic; | |
| font-size: 15vw; | |
| color: black; | |
| border: 16px solid black; | |
| padding: 40px; | |
| border-radius: 8px; | |
| } | |
| h2 { | |
| font-weight: 900; | |
| font-style: italic; | |
| font-size: 160px; | |
| margin: 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment