Skip to content

Instantly share code, notes, and snippets.

@anova
Created November 16, 2022 12:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anova/19a0403c6d163b003a45c2ced3422878 to your computer and use it in GitHub Desktop.
Save anova/19a0403c6d163b003a45c2ced3422878 to your computer and use it in GitHub Desktop.
creates an Intersection Observer.
/** @return IntersectionObserver */
function createObserver(p_threshold) {
return new IntersectionObserver(
(entries) => {
entries.forEach((/** @type IntersectionObserverEntry */ entry) => {
if (entry.isIntersecting) {
const eventIntersecting = new CustomEvent("intersecting");
entry.target.dispatchEvent(eventIntersecting);
return;
}
const eventNotIntersecting = new CustomEvent("not-intersecting");
entry.target.dispatchEvent(eventNotIntersecting);
});
},
{
threshold: p_threshold,
}
);
}
export {
createObserver
};
@anova
Copy link
Author

anova commented Nov 16, 2022

Thanks to Ben Frain for Intersection Observer example!
Link: https://benfrain.com/automatically-play-and-pause-video-as-it-enters-and-leaves-the-viewport-screen/

This code's usage example:

import {createObserver} from "./createObserver.js";
const /** @type IntersectionObserver */ videoObserver = createObserver(0.5); // Half of the element in viewport, element is "intersecting" else "not-intersecting"
const videos = document.querySelectorAll('video');
videos.forEach((video) => {
  videoObserver.observe(video);
  video.addEventListener('intersecting', ()=> {
    if(video.paused) {
      video.play();
    }
  });
  video.addEventListener('not-intersecting', ()=> {
    video.pause();
  });
});

@banonoyrpetsoy
Copy link

How do I use it ?

@anova
Copy link
Author

anova commented Nov 24, 2022

How do I use it ?

If you are using a module bundler like webpack, or using <script type=module> you can export and import like my previous comment.

https://gist.github.com/anova/19a0403c6d163b003a45c2ced3422878?permalink_comment_id=4371316#gistcomment-4371316

If you are not using a module bundler and not using module type scripts, you can copy the createObserver function and using it for create an observer for desired threshold. The threshold told the observer how much of the element is in viewport, it is "intersecting" with the viewport.

After creating the observer you must register the elements you want watching. This is done with the observe method.
Link: https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/observe

Caution: If your script is in <head> when the script is working the script will not see the elements on the page. Because they are not on the page yet. You must use the script before the closing </body> tag or place your code in DOMContentLoaded event or window.load

document.addEventListener('DOMContentLoaded',() => { 
  /* here the DOM Content is loaded and elements visible to JS */
})

After all this, an Intersection observer will created with desired threshold, and with observe method, the observer "observing" the element or elements.

You can use the custom event which createObserver function triggers when the observed elements when intersecting or not-intersecting like a video play or pause.

@thanhtutzaw
Copy link

thanhtutzaw commented Dec 2, 2022

Hi @anova can you help me ? . https://tiktok-zee.vercel.app This work well in Brave Browser . But in Chrome , I need to click one time and scroll . Why this is happening . I use next js intersection in useEffect . Also my videos have audio . https://github.com/thanhtutzaw/tiktok

@anova
Copy link
Author

anova commented Dec 19, 2022

Hi @anova can you help me ? . https://tiktok-zee.vercel.app This work well in Brave Browser . But in Chrome , I need to click one time and scroll . Why this is happening . I use next js intersection in useEffect . Also my videos have audio . https://github.com/thanhtutzaw/tiktok

Hello @thanhtutzaw , JS console says: "Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause(). https://goo.gl/LdLk22" You call play() and pause() methods on same element, pause() interrupts the play. It seems the pause() callen on every video. There must be a condition. If element intersects, play() must be called. If element stopped being intersected, pause() must be called.

@thanhtutzaw
Copy link

but This console warning is gone. I am not sure . But It autoplaying without audio in Chrome . I think in my Chrome Browser my url have good engagement to auto play .
chrome://media-engagement/

if my url is high It can auto play But I think It is only in Desktop

https://developer.chrome.com/blog/autoplay/#media-engagement-index

@anova
Copy link
Author

anova commented Jan 4, 2023

@thanhtutzaw I am sorry. I don't know about media engagement, but I will read about it.

I wrote this code from Ben Frain's blog post. I noticed this observer being re-used not only videos, also connect the sliders autoplay/pause is useful. I de-coupled the createObserver, and use with custom events.

Our agency's portfolio detail pages are using this createObserver code.
(Note for future: This links may be expire someday, if I notice, I will remove the links which became obsolete)

https://www.kreatif.net/markalarimiz/portakal-bahcem/

This is the createObserver: https://www.kreatif.net/wp-content/themes/kreatif_wp_theme/js/create-observer.js
And this is where its used: https://www.kreatif.net/wp-content/themes/kreatif_wp_theme/js/kr-videos.js

@anova
Copy link
Author

anova commented Aug 7, 2023

Note to myself: if "muted" attribute is absent, autoplay blocked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment