This is a finicky issue and may be difficult to figure out. This JavaScript controls the intro, play and stop/start of an mp4 video. Most of the code has to do with the video playback and position of the navigation images and links, and isn’t really relevant to this question.
The problem: on initial page load, sometimes the canvas div is hidden by the display:none
in the <video>
tag and the video start and canvas div is blank. This doesn’t happen all the time; it happens less often in Firefox, but most of the time in Chrome. A mouse click in the blank canvas div will show the video and introstill.png. A hard refresh will sometimes bring up the video start image in the canvas div.
I’m thinking it has something to do with the way the function at the end of the script is constructed with myvideo.init
and maybe breaks addEventListener
, but I don’t know.
I see the issue in both an .html file in localhost and on the live server. I’ve tried wrapping the whole function in jQuery('document').ready(function()
with no luck. I’ve tried disabling caching of the mp4 at the webhost. There are no browser console errors, and no browser add-ons conflicting.
As per @titus’ comment: how would I change
document.addEventListener('DOMContentLoaded', () => {
?
And, I don’t know enough JavaScript to strip out the irrelevant code to make a minimal reproducible example of addEventListener or DOMContentLoaded.
<script>
var myvideo = (function (window) {
var app = {};
var buttonBg_out = new Image();
var buttonBg_over = new Image();
var nextText = new Image();
var beginText = new Image();
var startAgain = new Image();
var introStill = new Image();
var pauseOverlay = new Image();
var REAL_WIDTH = 656;
var REAL_HEIGHT = 386;
var ASPECT_RATIO = REAL_WIDTH / REAL_HEIGHT;
var SCALE = 1.0;
app.init = function (root) {
buttonBg_out.src = root + 'button-out.png';
buttonBg_over.src = root + 'button-over.png';
nextText.src = root + 'next.png';
beginText.src = root + 'begin.png';
startAgain.src = root + 'startagain.png';
introStill.src = root + 'introstill.png';
pauseOverlay.src = root + 'pauseoverlay.png';
var document = window.document;
document.addEventListener('DOMContentLoaded', () => { // addEventListener
var video = document.getElementById('myvid');
var canvas = document.getElementById('playbackcontainer');
var ctx = canvas.getContext('2d');
introStill.onload = () => {
ctx.drawImage(introStill,0,31,introStill.width,introStill.height);
};
var rescaling = function () {
SCALE = canvas.clientWidth / REAL_WIDTH;
setTimeout(rescaling, 10);
};
rescaling();
var drawVideo = function () {
if (video.paused || video.ended) return;
ctx.drawImage(video,0,0,canvas.width,canvas.height);
drawButton();
setTimeout(drawVideo,1); // might fiddle with this timeout;
};
var button = {x:0,y:0,
w:127,
h:66,
state: buttonBg_out,
text: beginText,
visible: false
};
var localXY = function (e) {
var rect = canvas.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
return {x:x,y:y};
};
var isOverButton = function (e) {
var xy = localXY(e);
var x = xy.x;
var y = xy.y;
return (x >= (button.x * SCALE) && y >= (button.y * SCALE) &&
x <= ((button.x + button.w)*SCALE) &&
y <= ((button.y + button.h)*SCALE));
};
var drawButton = function () {
if (button.visible) {
ctx.drawImage(button.state,
button.x ,button.y ,
button.w ,button.h );
ctx.drawImage(button.text,
(button.x + 14) ,
(button.y + 23) ,
button.text.width ,
button.text.height );
}
};
var isOverStartOver = function (e) {
var xy = localXY(e);
return xy.x >= 9*SCALE && xy.x <= 92*SCALE && xy.y >= 367*SCALE && xy.y <= 379*SCALE;
};
var isOverReplayScene = function (e) {
var xy = localXY(e);
return xy.x >= 102*SCALE && xy.x <= 186*SCALE && xy.y >= 367*SCALE && xy.y <= 379*SCALE;
};
var permissionGiven = false;
var currentScene = 0;
var sceneBounds = [{start:4.583, showButton:13.849,
loopStart:15.116, loopEnd:22.183,
afterPress:23.416},
{start:25.649, showButton:53.416,
afterPress: 55.983},
{start:58.216, showButton:99.0,
afterPress:100.483},
{start:103.649, showButton:156.149,
afterPress:156.816},
{start:159.049, showButton:229.883,
loopStart:230.5, loopEnd:236.383,
afterPress:242.00}];
video.addEventListener('play', drawVideo, false);
video.addEventListener('timeupdate', () => {
var bounds = sceneBounds[currentScene];
if (video.currentTime >= bounds.showButton) {
button.visible = true;
drawButton();
}
if (bounds.loopEnd != null) { // keep playing
if (video.currentTime >= bounds.loopEnd) {
video.currentTime = bounds.loopStart;
}
} else if (video.currentTime >= bounds.showButton) { // pause
video.pause();
}
});
canvas.addEventListener('mousemove', (e) => {
if (isOverButton(e)) {
button.state=buttonBg_over;
drawButton();
} else {
button.state=buttonBg_out;
drawButton();
}
});
canvas.addEventListener('mousedown', (e) => {
if (!permissionGiven)
{
permissionGiven = true;
video.currentTime = sceneBounds[0].start;
video.play();
button.x = 322;
button.y = 244;
} else {
if (video.paused && currentScene > 0 && currentScene < 4 && !isOverButton(e)) {
if (isOverStartOver(e)) {
video.currentTime = sceneBounds[0].start;
button.visible = false;
button.x = 322;
button.y = 244;
button.text = beginText;
currentScene = 0;
video.play();
} else if (isOverReplayScene(e)) {
button.visible = false;
video.currentTime = sceneBounds[currentScene].start;
video.play();
} else {
video.play();
}
} else if (currentScene == 4 && !isOverButton(e)) {
if (isOverStartOver(e)) {
button.visible = false;
video.currentTime = sceneBounds[currentScene].start;
video.play();
}
} else if (button.visible && isOverButton(e)) { // button was presssed
currentScene = (currentScene + 1) % sceneBounds.length;
if (currentScene == 0)
{
button.text = beginText;
video.currentTime = sceneBounds[currentScene].start;
button.x = 322;
button.y = 244;
} else {
button.text = nextText;
button.x = 515;
button.y = 304;
video.currentTime = sceneBounds[currentScene-1].afterPress;
}
if (currentScene == 4)
button.text = startAgain;
button.visible = false;
video.play();
} else if (video.paused) {
video.play();
} else {
video.pause();
ctx.drawImage(pauseOverlay,0,0,canvas.width,canvas.height);
}
}
});
});
};
return app;
})(window);
(function(){
var thevid = document.getElementById("myvid");
myvideo.init("/path/to/folder/with/images/and/mp4/");
})();
</script>
<div class="flex-video">
<video id="myvid" style="display:none;" playsinline>
<source src="/path/to/folder/with/images/and/mp4/the_video.mp4" type="video/mp4"/></video>
<canvas id="playbackcontainer" width="656" height="386"></canvas>
</div>
2
Answers
If you give your
<script>
tag thedefer
keyword (<script defer></script>
), it will be run after all of the elements on the DOM have been loaded.To change the
document.addEventListener('DOMContentLoaded', () => {}
) in the JavaScript code you provided, you can use the following code:The
load
event is fired when the entire page has loaded, including all images, scripts, and CSS files. This is a good event to use to initialize your JavaScript code, as it ensures that the DOM is fully loaded and ready to be manipulated.Here is an example of how to use the
load
event to initialize themyvideo
code:This code will ensure that the
myvideo
code is not initialized until the entire page has loaded.