Im trying to add a buffer loader for all of my videos. All of my videos have got the id="video" but only one out of my 6 videos seems to display it. keep in mind i am using chromes network throttle "slow 3g" so i can force a slow buffer. anyone know why only one video will display the loader and none others will? heres the code:
var video = document.getElementById("video");
var placeholder = document.getElementById("placeholder");
placeholder.style.top = video.offsetTop + "px";
placeholder.style.left = video.offsetLeft + "px";
video.onwaiting = function() {
showPlaceholder(placeholder, this);
};
video.onplaying = function() {
hidePlaceholder(placeholder, this);
};
function showPlaceholder(img, vid) {
img.style.height = vid.scrollHeight + "px";
img.style.width = vid.scrollWidth + "px";
img.style.display = "block";
}
function hidePlaceholder(img, vid) {
img.style.display = "none";
}
.placeholder {
display: none;
position: absolute;
background-size: cover;
text-align: center;
z-index: 300000;
}
.THG-video {
width: 100% !important;
height: auto !important;
max-height: 380px;
max-width: 512px;
}
<div id="placeholder" class="placeholder"><img src="https://thg-graphics.com/media/DualRing.gif"></div>
<video class="THG-video" id="video" poster="Images/Rita.jpg" controls controlsList="nodownload noaudio" preload="none">
<source src="videos/Rita.mp4" type="video/mp4"> Your browser does not support the video tag.
</video>
<video class="THG-video" id="video" poster="Images/nat.jpg" controls controlsList="nodownload noaudio" preload="none">
<source src="videos/nat_x264.mp4" id="video" type="video/mp4"> Your browser does not support the video tag.
</video>
<video class="THG-video" id="video" poster="Images/ora.jpg" controls controlsList="nodownload noaudio" preload="none">
<source src="videos/Ora209_x264.mp4" type="video/mp4"> Your browser does not support the video tag.
</video>
<video class="THG-video" id="video" poster="Images/Arff-custom.jpg" controls controlsList="nodownload noaudio" preload="none">
<source src="videos/ARFF-Custom-3_x264.mp4" type="video/mp4"> Your browser does not support the video tag.
</video>
<video class="THG-video" id="video" poster="Images/THG-Green.jpg" controls controlsList="nodownload noaudio" preload="none">
<source src="videos/THG-Green.mp4" type="video/mp4"> Your browser does not support the video tag.
</video>
<video class="THG-video" id="video" poster="Images/mgd.jpg" controls controlsList="nodownload noaudio" preload="none">
<source src="videos/MGD_x264.mp4" type="video/mp4"> Your browser does not support the video tag.
</video>
I have made a working loader that can be used for as many videos as you like. Just edit the ids, video and placeholder tags to a unique word for each video. Here is a Jsfiddle
var video = document.getElementById("video_1");
var placeholder = document.getElementById("placeholder_1");
placeholder_1.style.top = video_1.offsetTop + "px";
placeholder_1.style.left = video_1.offsetLeft + "px";
video_1.onwaiting = function() {
showPlaceholder(placeholder_1, this);
};
video_1.onplaying = function() {
hidePlaceholder(placeholder_1, this);
};
function showPlaceholder(img, vid) {
img.style.height = vid.scrollHeight + "px";
img.style.width = vid.scrollWidth + "px";
img.style.display = "block";
}
function hidePlaceholder(img, vid) {
img.style.display = "none";
}
var video = document.getElementById("video_2");
var placeholder = document.getElementById("placeholder_2");
placeholder_2.style.top = video_2.offsetTop + "px";
placeholder_2.style.left = video_2.offsetLeft + "px";
video_2.onwaiting = function() {
showPlaceholder(placeholder_2, this);
};
video_2.onplaying = function() {
hidePlaceholder(placeholder_2, this);
};
function showPlaceholder(img, vid) {
img.style.height = vid.scrollHeight + "px";
img.style.width = vid.scrollWidth + "px";
img.style.display = "block";
}
function hidePlaceholder(img, vid) {
img.style.display = "none";
}
var video = document.getElementById("video_3");
var placeholder = document.getElementById("placeholder_3");
placeholder_3.style.top = video_3.offsetTop + "px";
placeholder_3.style.left = video_3.offsetLeft + "px";
video_3.onwaiting = function() {
showPlaceholder(placeholder_3, this);
};
video_3.onplaying = function() {
hidePlaceholder(placeholder_3, this);
};
function showPlaceholder(img, vid) {
img.style.height = vid.scrollHeight + "px";
img.style.width = vid.scrollWidth + "px";
img.style.display = "block";
}
function hidePlaceholder(img, vid) {
img.style.display = "none";
}
var video = document.getElementById("video_4");
var placeholder = document.getElementById("placeholder_4");
placeholder_4.style.top = video_4.offsetTop + "px";
placeholder_4.style.left = video_4.offsetLeft + "px";
video_4.onwaiting = function() {
showPlaceholder(placeholder_4, this);
};
video_4.onplaying = function() {
hidePlaceholder(placeholder_4, this);
};
function showPlaceholder(img, vid) {
img.style.height = vid.scrollHeight + "px";
img.style.width = vid.scrollWidth + "px";
img.style.display = "block";
}
function hidePlaceholder(img, vid) {
img.style.display = "none";
}
.placeholder {
display: none;
position: absolute;
background-size: cover;
text-align: center;
float: left;
z-index: 300000;
}
.loader,
.loader:before,
.loader:after {
background: #ff8000;
-webkit-animation: load1 1s infinite ease-in-out;
animation: load1 1s infinite ease-in-out;
width: 1em;
height: 4em;
}
.loader {
color: #ff8000;
text-indent: -9999em;
margin: 88px auto;
position: relative;
font-size: 11px;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
.loader:before,
.loader:after {
position: absolute;
top: 0;
content: '';
}
.loader:before {
left: -1.5em;
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.loader:after {
left: 1.5em;
}
#-webkit-keyframes load1 {
0%,
80%,
100% {
box-shadow: 0 0;
height: 4em;
}
40% {
box-shadow: 0 -2em;
height: 5em;
}
}
#keyframes load1 {
0%,
80%,
100% {
box-shadow: 0 0;
height: 4em;
}
40% {
box-shadow: 0 -2em;
height: 5em;
}
}
<video id="video_1" controls preload="none">
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" />
</video>
<div id="placeholder_1" class="placeholder">
<div class="loader">Loading...</div>
</div>
<video id="video_2" controls preload="none">
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" />
</video>
<div id="placeholder_2" class="placeholder">
<div class="loader">Loading...</div>
</div>
<video id="video_3" controls preload="none">
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" />
</video>
<div id="placeholder_3" class="placeholder">
<div class="loader">Loading...</div>
</div>
<video id="video_4" controls preload="none">
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" />
</video>
<div id="placeholder_4" class="placeholder">
<div class="loader">Loading...</div>
</div>
Related
I'm working with a collaborator on a scrolling video animation where the video should play as you scroll down the page. We've gone through a number of iterations of video compression to get the video to play smoothly, and in the process have noticed that while even the biggest files play really well on Safari (mobile and desktop), even the smallest files are pretty choppy on other browsers. Our goal was to have our video running as smoothly as this Scrolling Controls for HTML5 Video codepen example.
Why is this so much smoother on safari? We're trying to get it that smooth on other browsers, but are wondering if the requestAnimationFrame (which enter-view.js relies on) function is more optimized for safari and if we should be opting for some other animation strategy.
Here's our code:
const container = d3.select('#scrolly-overlay');
const stepSel = container.selectAll('.step');
const progressCounter = d3.select('#progress');
let vid = document.getElementById('v0');
const containerHeightMultiplier = 300;;
const vidUrls = [{
format: 'webm',
name: '10FPS_CQ_35',
file: 'TestVidLowRes_VP8_10FPS_CQ35',
size: "6.5MB"
},
{
format: 'webm',
name: '10FPS_CQ_45',
file: 'TestVidLowRes_VP8_10FPS_CQ45',
size: "4.8MB"
},
{
format: 'mp4',
name: '10FPS_RF_27',
file: 'TestVidLowRes_H264_10FPS_RF27',
size: "4.7MB"
},
{
format: 'mp4',
name: '10FPS_RF_40',
file: 'TestVidLowRes_H264_10FPS_RF40',
size: "0.5MB"
},
{
format: 'webm',
name: '5FPS_RF_40',
file: 'testVidLowRes_VP8_5FPS_CQ35',
size: '3.4MB'
}
]
d3.select('#vid-selection').selectAll('button').data(vidUrls).join('button')
.text(d => d.name + '.' + d.format + '-' + d.size)
.on('click', (event, d) => {
d3.select('#vid-source')
.attr('type', 'video/' + d.format)
.attr('src', "https://s3.us-west-1.amazonaws.com/tao.mo.2021/" + d.file + '.' + d.format)
d3.select('#selected-vid')
.text(d.format + ': ' + d.name + ' (' + d.size + ')')
vid.load()
vid.addEventListener('loadedmetadata', function() {
console.log(vid.fileSize)
d3.select('#scrolly-overlay .scrolly article .step').style('min-height', Math.floor(vid.duration) * containerHeightMultiplier + "px")
});
})
function updateChart(index) {
stepSel.classed('is-active', (d, i) => i === index);
}
function updateVid(progress) {
progressCounter.text(progress);
}
function init() {
Stickyfill.add(d3.select('.sticky').node());
enterView({
selector: stepSel.nodes(),
offset: 0.5,
enter: el => {
const index = +d3.select(el).attr('data-index');
updateChart(index);
},
progress: (el, progress) => {
progressCounter.text(progress);
vid.currentTime = progress * vid.duration
},
exit: el => {
let index = +d3.select(el).attr('data-index');
index = Math.max(0, index - 1);
updateChart(index);
}
})
/*
enterView({
selector: container.selectAll('.v0'),
offset: 0.5,
progress: (el, progress)=> {
progressCounter.text(progress);
vid.currentTime = progress*vid.duration
}
});
*/
}
init();
.filler {
height: 20rem;
text-align: center;
}
#scrolly-overlay .scrolly {
max-width: 60rem;
margin: 3rem auto;
background-color: #f4f4f4;
padding: 1rem;
}
#scrolly-overlay .scrolly article {
padding: 0;
max-width: 30rem;
margin: 0 auto;
position: relative;
}
#scrolly-overlay .scrolly article .step {
/* min-height: 500vh; now set dynamically */
margin-bottom: 1rem;
}
#scrolly-overlay .scrolly article .step:last-of-type {
margin-bottom: 0;
}
#scrolly-overlay .scrolly article .step.is-active p {
background-color: #008080;
}
#scrolly-overlay .scrolly article .step p {
margin: 0;
padding: 1rem;
text-align: center;
font-weight: 400;
background-color: #5b5b5b;
transition: background-color 250ms ease-in-out;
color: #f4f4f4;
}
#scrolly-overlay .scrolly figure.sticky {
position: sticky;
width: 100%;
height: 75vh;
margin: 0;
top: 3vh;
left: 0;
}
#scrolly-overlay .scrolly figure.sticky video {
position: absolute;
top: 1%;
left: 0.5%;
width: 99%;
background-color: #fff;
}
#scrolly-overlay .scrolly figure.sticky #progress {
position: absolute;
background-color: #fff;
}
<section class='filler'>
<p>
Scroll
</p>
<div id='vid-selection'></div>
<h2 style='margin-top:10px;font-weight:bold;' id='selected-vid'></h2>
</section>
<section id='scrolly-overlay'>
<div class='scrolly'>
<!-- sticky graphic -->
<figure class='sticky'>
<video id="v0" playsinline tabindex="0" autobuffer="autobuffer" preload="preload">
<!-- <source type="video/webm; codecs="vp8, vorbis"" src="https://static.observableusercontent.com/files/3e8f13f77456ac7c630d81e395bec55a90b9ab508d4602e2e11e5b3890fa8681b13ec1cc846cfc2e27b44989ca60536d448ee7d63f945eeca91301ca2a0bdce3"></source>
<source type="video/mp4" src="https://static.observableusercontent.com/files/503c7cf52dcf3efaf653791a8919f2f4e186aba59d6e264fd22e46b589c7348b536fa23cc348a62a12e33b5dbcb5d258e4205150326297de0f7842105cab67a2"></source>
<source type="video/webm; codecs="vp8, vorbis"" src="https://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.webm"></source>
<source type="video/webm" src="https://s3.us-west-1.amazonaws.com/tao.mo.2021/testVid2.webm"></source>
<source type="video/webm" src="https://s3.us-west-1.amazonaws.com/tao.mo.2021/testVid.webm"></source>
<source type="video/webm" src="https://s3.us-west-1.amazonaws.com/tao.mo.2021/testVid3.webm"></source>
-->
<source id='vid-source'></source>
</video>
<div id='progress'>0</div>
</figure>
<!-- step text -->
<article>
<div class='step' data-width='10%' data-index='0'>
<p>Text to Trigger Scroll</p>
</div>
</article>
</div>
</section>
<section class='filler'>
<p>
End
</p>
</section>
And here it is on codepen (it uses elements from The Pudding’s enter-view.js examples, and that "Scrolling Controls" example): https://codepen.io/ossermans/pen/LYLbPJd
I need to play/pause videos if they are in the viewport/not in the viewport.
It works so far. The problem is, that if the user presses pause, then the video just starts playing again.
// Limitation: Does not work if the element is
// out of view because it is too far right or left
$.fn.isInViewport = function() {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementBottom > viewportTop && elementTop < viewportBottom;
};
setInterval(function() {
$('video').each(function(){
if ($(this).isInViewport()) {
$(this)[0].play();
} else {
$(this)[0].pause();
}
});
}, 1000);
#right {
position: absolute;
top: 2000px;
}
#video1 {
position: absolute;
left: 0px;
top: 1000px;
}
#video2 {
position: absolute;
left: 0px;
top: 2000px;
}
body {
width: 500px;
height: 3000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="info"></div>
<div id="down">
scroll down please...
</div>
<video id="video1" controls muted>
<source src="https://www.w3schools.com/html/movie.mp4" type="video/mp4">
<source src="https://www.w3schools.com/html/movie.ogg" type="video/ogg">
Your browser does not support the video tag.
</video>
<video id="video2" controls muted>
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"/>
<source src="https://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg"/>
Your browser does not support the video tag.
</video>
I tried to observer the Play/Pause button so I can hook into the event, but the video tag is a shadow dom and I dont know how to deal with it.
https://jsfiddle.net/6agbqjsL/
I figured it out. This way the video only starts playing again if it gets out of the viewport and into the viewport again:
// Limitation: Does not work if the element is
// out of view because it is too far right or left
$.fn.isInViewport = function() {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementBottom > viewportTop && elementTop < viewportBottom;
};
setInterval(function() {
$('video').each(function(){
let id = $(this).attr("id");
let played = $(this).attr("played");
if ($(this).isInViewport()) {
if (played == "false") {
$(this)[0].play();
$(this).attr("played", "true");
}
} else {
if (played == "true") {
$(this)[0].pause();
$(this).attr("played", "false");
}
}
});
}, 1000);
#right {
position: absolute;
top: 2000px;
}
#video1 {
position: absolute;
left: 0px;
top: 1000px;
}
#video2 {
position: absolute;
left: 0px;
top: 2000px;
}
body {
width: 500px;
height: 3000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="info"></div>
<div id="down">
scroll down please...
</div>
<video id="video1" controls muted played="false">
<source src="https://www.w3schools.com/html/movie.mp4" type="video/mp4">
<source src="https://www.w3schools.com/html/movie.ogg" type="video/ogg">
Your browser does not support the video tag.
</video>
<video id="video2" controls muted played="false">
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"/>
<source src="https://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg"/>
Your browser does not support the video tag.
</video>
This way the video does never play again automatically after it was paused:
// Limitation: Does not work if the element is
// out of view because it is too far right or left
$.fn.isInViewport = function() {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementBottom > viewportTop && elementTop < viewportBottom;
};
setInterval(function() {
$('video').each(function(){
var id = $(this).attr("id");
let played = $(this).attr("played");
if ($(this).isInViewport()) {
if (played == "false") {
$(this)[0].play();
$(this).attr("played", "true");
}
} else {
$(this)[0].pause();
}
});
}, 1000);
#right {
position: absolute;
top: 2000px;
}
#video1 {
position: absolute;
left: 0px;
top: 1000px;
}
#video2 {
position: absolute;
left: 0px;
top: 2000px;
}
body {
width: 500px;
height: 3000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="info"></div>
<div id="down">
scroll down please...
</div>
<video id="video1" controls muted played="false">
<source src="https://www.w3schools.com/html/movie.mp4" type="video/mp4">
<source src="https://www.w3schools.com/html/movie.ogg" type="video/ogg">
Your browser does not support the video tag.
</video>
<video id="video2" controls muted played="false">
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"/>
<source src="https://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg"/>
Your browser does not support the video tag.
</video>
My code is as follows
"use strict";
console.clear();
((d,w) => {
const cloneVideo = vid => {
const clone = vid.cloneNode(true);
clone.id += '-'
clone.style.display = 'none'
vid.parentElement.insertBefore(clone, vid);
return clone;
}
const getVideoSources = el => Array.from(el.querySelectorAll(":scope > source"));
const isTypeSupported = type => d.createElement("video").canPlayType(type);
const isMatchMedia = media => w.matchMedia(media).matches;
const onLoadeddata = (vid, clone) => e => {
const t = vid.currentTime;
vid.remove()
clone.currentTime = t;
clone.style.display = ''
clone.removeEventListener('loadeddata', onLoadeddata(vid, clone))
clone.play();
}
const updateVideoSources = vid => {
let changes = getVideoSources(vid).findIndex(src => isMatchMedia(src.media))
if (changes > 0) {
const clone = cloneVideo(vid);
let changes = getVideoSources(clone).filter(src => isMatchMedia(src.media))
changes.reverse().forEach(src => clone.prepend(src))
const id = vid.id
clone.addEventListener('loadeddata', onLoadeddata(vid, clone))
clone.load();
clone.id = id
return clone
}
return vid
};
const checkMedia = (video) => {
return (e) => {
// console.log(e)
video = updateVideoSources(video);
// console.log(39, video, video.parentElement)
}
}
w.checkMedia = checkMedia;
})(document,window);
{
const delay = 250;
const video = document.getElementById("vid");
const check = checkMedia(video)
window.addEventListener("DOMContentLoaded", check);
window.addEventListener("resize", debounce(check, delay));
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this,
args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
}
.container {
max-width: 925px;
margin: auto;
}
.clip {
position: relative;
width: 50%;
overflow: hidden;
display: -webkit-box;
display: flex;
}
.clip:before {
content: '';
padding-bottom: calc(100% * 506 / 448);
visibility: hidden;
pointer-events: none;
flex-basis: 0;
}
.clip:after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #c3a88c;
background: #8a5d2f;
background: #ca935a;
background: #af8457;
mix-blend-mode: soft-light;
-webkit-clip-path: circle(farthest-side at 56.4% 50%);
clip-path: circle(farthest-side at 56.4% 50%);
}
#vid {
-webkit-clip-path: circle(farthest-side at 56.4% 50%);
clip-path: circle(farthest-side at 56.4% 50%);
-o-object-fit: cover;
object-fit: cover;
-o-object-position: 56.4% 50%;
object-position: 56.4% 50%;
}
#vid {
line-height: 0;
display: inline-block;
width: 100%;
}
body {
margin: 0;
padding: 0;
}
<div class="container">
<div class="clip">
<video id="vid" autoplay muted loop playsinline preload="auto" width="100%" height="auto">
<source data-number="1" src="https://assets.codepen.io/96344/pleyces-landing-page-video_240p.webm" type="video/webm" media="(max-width:527px)">
<source data-number="2" src="https://assets.codepen.io/96344/pleyces-landing-page-video_240p.ogv" type="video/ogg" media="(max-width:527px)">
<source data-number="3" src="https://assets.codepen.io/96344/pleyces-landing-page-video_240p.mp4" type="video/mp4" media="(max-width:527px)">
<source data-number="4" src="https://assets.codepen.io/96344/pleyces-landing-page-video_360p.webm" type="video/webm" media="(max-width: 719px) and (min-width:528px)">
<source data-number="5" src="https://assets.codepen.io/96344/pleyces-landing-page-video_360p.ogv" type="video/ogg" media="(max-width: 719px) and (min-width:528px)">
<source data-number="6" src="https://assets.codepen.io/96344/pleyces-landing-page-video_360p.mp4" type="video/webm" media="(max-width: 719px) and (min-width:528px)">
<source data-number="7" src="https://assets.codepen.io/96344/pleyces-landing-page-video_480p.webm" type="video/webm" media="(max-width: 899px) and (min-width:720px)">
<source data-number="8" src="https://assets.codepen.io/96344/pleyces-landing-page-video_480p.ogv" type="video/ogg" media="(max-width: 899px) and (min-width:720px)">
<source data-number="9" src="https://assets.codepen.io/96344/pleyces-landing-page-video_480p.mp4" type="video/mp4" media="(max-width: 899px) and (min-width:720px)">
<source data-number="10" src="https://assets.codepen.io/96344/pleyces-landing-page-video_600p.webm" type="video/webm" media="(min-width:900px)">
<source data-number="11" src="https://assets.codepen.io/96344/pleyces-landing-page-video_600p.ogv" type="video/ogg" media="(min-width:900px)">
<source data-number="12" src="https://assets.codepen.io/96344/pleyces-landing-page-video_600p.mp4" type="video/mp4" media="(min-width:900px)">
</video>
</div>
</div>
What this code does?
Since there is no support for media attributes of <source> elements inside <video> elements (See MDN), I needed to code a workaround. What I coded is: Listen to resize events (debounced) and check the media queries of each source, if it matches with window matchMedia. If some sources match, I change the order of the <source> tags and move the matches to be first children of the <video> elements.
After that I load the video again and jump to the memorized time.
Because this had the disadvantage of flickering when the sources changed (video disappeared and then appeared again), I needed a workaround. For this I clone the video before sorting and loading and then remove the original video after the clone has loaded (event loadeddata).
This prevents the flickering, but has another slight unpleasant behavior. The video jumps to the first video frame and then immediately to the time frame I memorized earlier.
Why does it do that? I set the currentTime before the play() action.
For this issue to show you need to test this in Full page mode and change the window width: I have three break points defined, where the video source should change: 528, 720 and 900 pixels. You can check that it's working by inspecting the Network tab in your Browser's Developer Tools.
I'm trying to play audio when the div .deley change to display: block, but something does not work. The online audio clips are correct, it's not the problem. My problem is in my script, but I can not find it. Maybe .pause is not a function?
What could be wrong?
function see() {
var x = document.getElementById("deley");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
};
// === Scrip for audio play ====
$(document).ready(function(){
$(".deley").hide();
// if sound is currently playing, stop it and reset
if(!$("#notify").paused) {
$("#notify").pause();
$("#notify").currentTime = 0;
}
setTimeout(function () {
$(".deley").show();
$("#notify").play();
}, 0);
});
#cont {
width:200px;
margin:0 auto
}
.deley {
display:none;
width:96px;
height:40px;
background:red;
margin:20px 0;
text-align:center;
line-height:40px;
font-family:Arial, sans-serif;
color:#fff
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="cont">
<div class="deley" id="deley">Deley</div>
<audio id="notify">
<source src="https://notificationsounds.com/soundfiles/8b16ebc056e613024c057be590b542eb/file-sounds-1113-unconvinced.ogg" type="audio/ogg">
<source src="https://notificationsounds.com/soundfiles/8b16ebc056e613024c057be590b542eb/file-sounds-1113-unconvinced.mp3" type="audio/mpeg">
</audio>
<button onclick="see()">Open / Close</button>
</cont>
jQuery Objects✱ and JavaScript Objects🞳 are different. They do not recognize one another which is why the following statements do not work:
if (!$(".notify").paused) {
$(".notify").pause();
$(".notify").currentTime = 0;
...
$(".notify").play();
The MediaElement API is Plain JavaScript only. Any methods/properties/events from said API is not recognized by jQuery -- Plain JavaScript Objects are needed to use methods .pause() and .play(), and properties .paused and .currentTime.
Solutions
Reference a Plain JavaScript Object🞳
document.querySelector(selector)
Dereference a jQuery Object✱
$(selector)[0]
OR
$(selector).get(0)
There are a couple of other important things to remember about jQuery:
Never use onevent attributes: <buttononclick='func();'</button>
Assign .class attributes to elements avoid #id attributes.
The versatility jQuery affords to us makes such antiquated practices unnecessary and wasteful. Also, the function see() is no longer needed -- functionality of see() is now integrated into function audioSwitch().
$('button').on('click', audioSwitch);
function audioSwitch(e) {
if (!$(".notify")[0].paused || $('.delay').is(':visible')) {
$(".notify")[0].pause();
$(".notify")[0].currentTime = 0;
$(".delay").hide();
} else {
setTimeout(function() {
$(".notify")[0].play();
$(".delay").show();
}, 750);
}
}
.cont {
width: 200px;
margin: 0 auto
}
.delay {
display: none;
width: 96px;
height: 40px;
line-height: 40px;
background: red;
color: #fff;
margin: 20px 0;
text-align: center;
font-family: Arial, sans-serif;
}
<section class="cont">
<figure class="delay">
<figcaption>Delay</figcaption>
</figure>
<audio class="notify" src="https://notificationsounds.com/soundfiles/8b16ebc056e613024c057be590b542eb/file-sounds-1113-unconvinced.mp3">
</audio>
<button>Open / Close</button>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Here is a working example.
function see() {
var x = document.getElementById("deley");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
};
// === Scrip for audio play ====
$(document).ready(function(){
$(".deley").hide();
// if sound is currently playing, stop it and reset
if(!$("#notify")[0].paused) {
$("#notify")[0].pause();
$("#notify")[0].currentTime = 0;
}
setTimeout(function () {
$(".deley").show();
$("#notify")[0].play();
}, 0);
});
#cont {
width:200px;
margin:0 auto
}
.deley {
display:none;
width:96px;
height:40px;
background:red;
margin:20px 0;
text-align:center;
line-height:40px;
font-family:Arial, sans-serif;
color:#fff
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="cont">
<div class="deley" id="deley">Deley</div>
<audio id="notify">
<source src="https://notificationsounds.com/soundfiles/8b16ebc056e613024c057be590b542eb/file-sounds-1113-unconvinced.ogg" type="audio/ogg">
<source src="https://notificationsounds.com/soundfiles/8b16ebc056e613024c057be590b542eb/file-sounds-1113-unconvinced.mp3" type="audio/mpeg">
</audio>
<button onclick="see()">Open / Close</button>
</cont>
Jq object dose not have play, pause events. you will have to change it to a simple javascript to access those events.
emphasized text
Have a look below and i also simplified the function fot you
function see() {
$(".deley").toggle("fast", function(){
var player= $("#notify")[0];
// is the player hidden then pause and reset
if($(this).is("hidden")) {
player.pause();
player.currentTime = 0;
}else
player.play();
});
};
#cont {
width:200px;
margin:0 auto
}
.deley {
display:none;
width:96px;
height:40px;
background:red;
margin:20px 0;
text-align:center;
line-height:40px;
font-family:Arial, sans-serif;
color:#fff
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="cont">
<div class="deley" id="deley">Deley</div>
<audio id="notify">
<source src="https://notificationsounds.com/soundfiles/8b16ebc056e613024c057be590b542eb/file-sounds-1113-unconvinced.ogg" type="audio/ogg">
<source src="https://notificationsounds.com/soundfiles/8b16ebc056e613024c057be590b542eb/file-sounds-1113-unconvinced.mp3" type="audio/mpeg">
</audio>
<button onclick="see()">Open / Close</button>
</cont>
$(document).ready(function(){
$(".deley").hide();
// if sound is currently playing, stop it and reset
if(!$("#notify")[0].paused) {
$("#notify")[0].pause();
$("#notify")[0].currentTime = 0;
}
setTimeout(function () {
$(".deley").show();
$("#notify")[0].play();
}, 0);
});
https://stackoverflow.com/a/16093819/11343720
Or
document.getElementById('notify').play();
I can't understand why the waiting event is not firing.
Basically I want the animation in the container to work whenever the video buffers.
Is there any other event that I need to look out for?
function play() {
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<video onwaiting="play()" controls autoplay>
<source src = "bleach-cool-mp3.webm" type="video/webm" >
</video>
<div id="container">
<div id="animate"></div>
</div>
Two important things:
First: You can't name your function play(), because is a reserved keyword for the video api, you have to rename it
Second: Your onwaiting event is working fine, but it only triggers when your video has to buff the next frames (like slow connection problems). If you want it to trigger when the video is searching for the data to show, like the first loading, use onloadstart event:
Bellow, your working snippet:
function PlayAnimation() {
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<video onwaiting="PlayAnimation()" onloadstart="PlayAnimation()" controls autoplay>
<source src = "https://www.w3schools.com/tags/mov_bbb.mp4" type="video/mp4" >
</video>
<div id="container">
<div id="animate"></div>
</div>