-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start autoplay when video is in view #2839
base: main
Are you sure you want to change the base?
Conversation
58f2db7
to
9688201
Compare
9688201
to
13a48c7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These functions should be in the respective blocks. There's no need for a separate file IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed here: 42b53fb
@@ -0,0 +1,20 @@ | |||
import { RefObject, useEffect, useState } from "react"; | |||
|
|||
export const useIsElementVisible = (ref: RefObject<HTMLDivElement>) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming: useIsElementInViewport would probably be better. An element can still be hidden using display: none
.
BTW, nice implementation using IntersectionObserver 👏🏼
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you :)
Naming changed here: 0ebb7d3
a48e93d
to
108a218
Compare
@@ -21,6 +22,20 @@ const parseYoutubeIdentifier = (value: string): string | undefined => { | |||
return youtubeId ?? undefined; | |||
}; | |||
|
|||
const pauseYoutubeVideo = () => { | |||
const iframe = document.getElementsByTagName("iframe")[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if there are multiple iframe tags?
use a ref instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Changed here: b880c4c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also use Refs for the iframes
@johnnyomair |
useEffect(() => { | ||
inView && autoplay ? playYoutubeVideo() : pauseYoutubeVideo(); | ||
}, [autoplay, inView]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useIsElementInViewport has a local state and re-renders the Video Block once it gets into view. But you don't have to re-render, as you only call the JS api inside the iframe.
You could argue that performance doesn't matter here, it's only re-rendered once - but I'd argue that it makes the code more complicated than it has to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would you design useIsElementInViewport to remove the state and effect? Something like this?
useIsElementInViewport(ref, (inView) => {
if(autoplay) {
if(inView) {
playYouTubeVideo();
} else {
pauseYouTubeVideo();
}
}
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it better like this?
23411e5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it better like this?
yes, much simpler - isn't it?
|
||
const inView = useIsElementInViewport(inViewRef); | ||
|
||
inView && autoplay ? playDamVideo(videoRef) : pauseDamVideo(videoRef); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be in a useEffect
nvm since the state in useIsElementInViewport
only changes if the element get in view, not triggering unnecessary rerenders
@@ -33,6 +46,13 @@ export const DamVideoBlock = withPreview( | |||
const [showPreviewImage, setShowPreviewImage] = useState(true); | |||
const hasPreviewImage = Boolean(previewImage && previewImage.damFile); | |||
|
|||
const inViewRef = useRef<HTMLDivElement>(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need the extra inViewRef? Wouldn't it be possible to use the videoRef directly to check if it's in view?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I already tried that, but using only one ref is not possible, as controlling the videos does not work in that case.
Quality Gate failedFailed conditions See analysis details on SonarQube Cloud Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE |
Description
Videos that are set to autoplay should only start if the user scrolls to the Video. If he scrolls away, the video should pause. Implementation for: DamVideoBlock, YoutubeVideoBlock and VimeoVideoBlock.
Screenshots/screencasts
DamVideoBlock:
Screen.Recording.2024-11-27.at.13.32.10.mov
YoutubeVideoBlock:
Screen.Recording.2024-11-27.at.13.34.19.mov
VimeoVideoBlock:
Screen.Recording.2024-11-27.at.13.35.36.mov
Changeset
Related tasks and documents
(https://vivid-planet.atlassian.net/browse/COM-1313)