i am trying to design a video player like youtube player and when the mouse over the time line of the video,i want it to show a minimize image of the video on the time of the time line like youtube player
and to do this i have put two video tag in html file
one is the main video and the other is appear when mouse over the time line of the video with a currentTime of the time of time line where the mouse is above time line
but i noticed that this way is stress on the internet because the second video each time i set to it
the currentTime is buffering
is there a solution to stop buffering or any alternative way to show this minimize image
Create video timeline thumbnails (stills)
The best you could do would be: on video upload, (i.e: using FFMPEG) to take still images/thumbnails of the video data. Than when you draw your seek-preview, simply take the desired thumbnail image index.
Otherwise, you could:
Create a video element
Create a canvas element
Create an array to store the stills
If a still does not exist in array:
set the cloned video time
grab the video data to canvas
store the image data into the stills array
If a still exists, just use that image
Here's a dirty code just to give you an idea:
const totStills = 10;
const addSeekThumbnail = (EL) => {
const VID = EL.querySelector("video");
const DSK = document.createElement("div");
const VSK = document.createElement("video");
const CTX = document.createElement("canvas").getContext("2d");
const stills = new Array(totStills);
VSK.setAttribute("preload", "metadata");
VSK.setAttribute("crossorigin", "*");
DSK.classList.add("videoSeek");
VSK.src = VID.src;
EL.append(DSK);
VID.addEventListener("mousemove", seekShot);
EL.addEventListener("mousemove", toggleSeek);
EL.addEventListener("mouseleave", toggleSeek);
function takeStill() {
const i = VSK.dataset.fr * totStills;
if (stills[i]) return;
CTX.drawImage(VSK, 0, 0, VSK.videoWidth, VSK.videoHeight);
stills[i] = CTX.canvas.toDataURL("image/png");
loadStill()
}
function loadStill() {
const i = VSK.dataset.fr * totStills;
if (stills[i]) {
DSK.style.backgroundImage = `url(${stills[i]})`;
} else {
DSK.style.backgroundImage = `none`;
VSK.currentTime = Math.round(VSK.dataset.fr * VID.duration);
VSK.addEventListener("seeked", takeStill, {
once: true
});
}
}
function toggleSeek(ev) {
if (ev.type === "mouseleave") {
return DSK.classList.remove("show");
}
const bcr = EL.getBoundingClientRect();
const my = ev.clientY - bcr.top;
DSK.classList.toggle("show", bcr.height - my < 30);
}
function seekShot(ev) {
const bcr = EL.getBoundingClientRect();
const mx = ev.clientX - bcr.left;
const x = mx / bcr.width;
const fr = Math.round(x * totStills) / totStills;
if (VSK.dataset.fr === fr) return;
VSK.dataset.fr = fr;
DSK.style.left = `${fr * 80}%`; // 80 because it's 20% wide
loadStill();
}
};
const ELS_frames = document.querySelectorAll(".videoFrame");
ELS_frames.forEach(addSeekThumbnail);
video {
max-width: 100%;
}
.videoFrame {
display: inline-block;
position: relative;
margin: 0;
}
.videoSeek {
position: absolute;
z-index: 2;
bottom: 70px;
left: 0;
width: 20%;
height: 20%;
pointer-events: none;
box-shadow: 0 0 0 2px #fff;
background-color: rgba(255, 255, 255, 0.6);
transition: opacity 0.3s, left 0.2s;
opacity: 0;
}
.videoSeek.show {
opacity: 1;
}
<div class="videoFrame">
<video id="video" crossorigin="*" src="https://raw.githubusercontent.com/Ahmetaksungur/aksvideoplayer/main/videos/video-360.mp4" controls></video>
</div>
Related
But When i select the other picture it did not show in magnifier box, instead it show the default picture in magnifier. how i can fix that?. I want to change the image after selecting from below and magnifier should work on that image.
and magnifier position is very downside, can we also make the appropriate position
HTML
Css
.product-image {
height: 300px;
cursor: zoom-in;
}
.magnifier-container {
display: inline-block;
position: relative;
}
.magnifier {
display: none;
position: absolute;
top: 0;
left: 100%;
overflow: hidden;
height: 300px;
width: 300px;
border: 1px solid #ddd;
border-radius: 10px;
background-color: white;
}
.magnifier__img {
width: 1000px;
transform-origin: 150px 150px;
}
js
// most efficient way to add HTML, faster than innerHTML
const parseHTML = (htmlStr) => {
const range = document.createRange();
range.selectNode(document.body); // required in Safari
return range.createContextualFragment(htmlStr);
};
// pass this function any image element to add magnifying functionality
const makeImgMagnifiable = (img) => {
const magnifierFragment = parseHTML(`
<div class="magnifier-container">
<div class="magnifier">
<img class="magnifier__img" src="${img.src}"/>
</div>
</div>
`);
// This preserves the original element reference instead of cloning it.
img.parentElement.insertBefore(magnifierFragment, img);
const magnifierContainerEl = document.querySelector(".magnifier-container");
img.remove();
magnifierContainerEl.appendChild(img);
// query the DOM for the newly added elements
const magnifierEl = magnifierContainerEl.querySelector(".magnifier");
const magnifierImg = magnifierEl.querySelector(".magnifier__img");
// set up the transform object to be mutated as mouse events occur
const transform = {
translate: [0, 0],
scale: 1,
};
// shortcut function to set the transform css property
const setTransformStyle = (el, { translate, scale }) => {
const [xPercent, yRawPercent] = translate;
const yPercent = yRawPercent < 0 ? 0 : yRawPercent;
// make manual pixel adjustments to better center
// the magnified area over the cursor.
const [xOffset, yOffset] = [
`calc(-${xPercent}% + 250px)`,
`calc(-${yPercent}% + 70px)`,
];
el.style = `
transform: scale(${scale}) translate(${xOffset}, ${yOffset});
`;
};
// show magnified thumbnail on hover
img.addEventListener("mousemove", (event) => {
const [mouseX, mouseY] = [event.pageX + 40, event.pageY - 20];
const { top, left, bottom, right } = img.getBoundingClientRect();
transform.translate = [
((mouseX - left) / right) * 100,
((mouseY - top) / bottom) * 100,
];
magnifierEl.style = `
display: block;
top: ${mouseY}px;
left: ${mouseX}px;
`;
setTransformStyle(magnifierImg, transform);
});
// zoom in/out with mouse wheel
img.addEventListener("wheel", (event) => {
event.preventDefault();
const scrollingUp = event.deltaY < 0;
const { scale } = transform;
transform.scale =
scrollingUp && scale < 3
? scale + 0.1
: !scrollingUp && scale > 1
? scale - 0.1
: scale;
setTransformStyle(magnifierImg, transform);
});
// reset after mouse leaves
img.addEventListener("mouseleave", () => {
magnifierEl.style = "";
magnifierImg.style = "";
});
};
const img = document.querySelector(".product-image");
makeImgMagnifiable(img);
My implementation,
http://kodhus.com/kodnest/land/PpNFTgp
I am curious, as I am not able for some reason to figure this out, how to get my JavaScript to make my slider behave more natural and smoother, if someone knows, how to, or can make this, feel free. I'd be happy to understand.
JavaScript:
const thumb = document.querySelector('.thumb');
const thumbIndicator = document.querySelector('.thumb .thumb-indicator');
const sliderContainer = document.querySelector('.slider-container');
const trackProgress = document.querySelector('.track-progress');
const sliderContainerStart = sliderContainer.offsetLeft;
const sliderContainerWidth = sliderContainer.offsetWidth;
var translate;
var dragging = false;
var percentage = 14;
document.addEventListener('mousedown', function(e) {
if (e.target.classList.contains('thumb-indicator')) {
dragging = true;
thumbIndicator.classList.add('focus');
}
});
document.addEventListener('mousemove', function(e) {
if (dragging) {
console.log('moving', e)
if (e.clientX < sliderContainerStart) {
translate = 0;
} else if (e.clientX > sliderContainerWidth + sliderContainerStart) {
translate = sliderContainerWidth;
} else {
translate = e.clientX - sliderContainer.offsetLeft;
}
thumb.style.transform = 'translate(-50%) translate(' + translate + 'px)';
trackProgress.style.transform = 'scaleX(' + translate / sliderContainerWidth + ')'
}
});
function setPercentage() {
thumb.style.transform = 'translate(-50%) translate(' + percentage/100 * sliderContainerWidth + 'px)';
trackProgress.style.transform = 'scaleX(' + percentage/100 + ')';
}
function init() {
setPercentage();
}
init();
document.addEventListener('mouseup', function(e) {
dragging = false;
thumbIndicator.classList.remove('focus');
});
EDIT: Is there a way to smoothly and naturally increment by one for every slow move?
Is it possible to make to behave as if, like when one clicks the progress bar so that it jumps there?
The kodhus site is very janky in my browser, so I can't tell if your code lacks responsiveness or whether it's the site itself. I feel that your code is a bit convoluted: translate and width / height are mixed unnecessarily; no need to use a dragging boolean when that information is always stored in the classlist. The following slider performs nicely, and has a few considerations I don't see in yours:
stopPropagation when clicking the .thumb element
drag stops if window loses focus
pointer-events: none; applied to every part of the slider but the .thumb element
let applySliderFeel = (slider, valueChangeCallback=()=>{}) => {
// Now `thumb`, `bar` and `slider` are the elements that concern us
let [ thumb, bar ] = [ '.thumb', '.bar' ].map(v => slider.querySelector(v));
let changed = amt => {
thumb.style.left = `${amt * 100}%`;
bar.style.width = `${amt * 100}%`;
valueChangeCallback(amt);
};
// Pressing down on `thumb` activates dragging
thumb.addEventListener('mousedown', evt => {
thumb.classList.add('active');
evt.preventDefault();
evt.stopPropagation();
});
// Releasing the mouse button (anywhere) deactivates dragging
document.addEventListener('mouseup', evt => thumb.classList.remove('active'));
// If the window loses focus dragging also stops - this can be a very
// nice quality of life improvement!
window.addEventListener('blur', evt => thumb.classList.remove('active'));
// Now we have to act when the mouse moves...
document.addEventListener('mousemove', evt => {
// If the drag isn't active do nothing!
if (!thumb.classList.contains('active')) return;
// Compute `xRelSlider`, which is the mouse position relative to the
// left side of the slider bar. Note that *client*X is compatible with
// getBounding*Client*Rect, and using these two values we can quickly
// get the relative x position.
let { width, left } = slider.getBoundingClientRect();
// Consider mouse x, subtract left offset of slider, and subtract half
// the width of the thumb (so drags position the center of the thumb,
// not its left side):
let xRelSlider = evt.clientX - left - (thumb.getBoundingClientRect().width >> 1);
// Clamp `xRelSlider` between 0 and the slider's width
if (xRelSlider < 0) xRelSlider = 0;
if (xRelSlider > width) xRelSlider = width;
// Apply styling (using percents is more robust!)
changed(xRelSlider / width);
evt.preventDefault();
evt.stopPropagation();
});
slider.addEventListener('mousedown', evt => {
let { width, left } = slider.getBoundingClientRect();
// Clicking the slider also activates a drag
thumb.classList.add('active');
// Consider mouse x, subtract left offset of slider, and subtract half
// the width of the thumb (so drags position the center of the thumb,
// not its left side):
let xRelSlider = evt.clientX - left - (thumb.getBoundingClientRect().width >> 1);
// Apply styling (using percents is more robust!)
changed(xRelSlider / width);
evt.preventDefault();
evt.stopPropagation();
});
changed(0);
};
let valElem = document.querySelector('.value');
applySliderFeel(document.querySelector('.slider'), amt => valElem.innerHTML = amt.toFixed(3));
.slider {
position: absolute;
width: 80%; height: 4px; background-color: rgba(0, 0, 0, 0.3);
left: 10%; top: 50%; margin-top: -2px;
}
.slider > .bar {
position: absolute;
left: 0; top: 0; width: 0; height: 100%;
background-color: #000;
pointer-events: none;
}
.slider > .thumb {
position: absolute;
width: 20px; height: 20px; background-color: #000; border-radius: 100%;
left: 0; top: 50%; margin-top: -10px;
}
.slider > .thumb.active {
box-shadow: 0 0 0 5px rgba(0, 0, 0, 0.5);
}
<div class="slider">
<div class="bar"></div>
<div class="thumb"></div>
</div>
<div class="value"></div>
Sorry, this is going to be a little long...
A bit of context
As part of a larger project I'm trying to make a project timeline to include in a webpage used to remote control a music making program (called Reaper for those who are interested). I'm trying to get it to display the current play position, the project markers, and project regions. These are all served straight from the program's API, no problem getting the info. For starters I'm just trying to display the project markers, however I've been pulling my hair out for over a week now trying to get it to work.
Here's a quick screencap from inside the software to illustrate what I'm trying to emulate: Reaper ruler screencap
Normally I would use a progress bar for something like this, or one of the thousands of examples from the web, however I have no way of knowing the length of the project as the software doesn't limit it. As a result I fell back onto using a fixed scale of 10px per bar. Kind of arbitrary, I chose that as it's the optimal for a 5 minute song at 120 bpm. Not too worried about looks for the moment, I just want to get it to work haha.
The problem I have (code is included at the bottom) is that because I'm using absolute positioning for the markers in order to align them all from the left of the screen, they are pulled from the document flow and so I can't wrap them in the parent div. In the end I intend setting the parent div to an 80% width with a scrollbar to see the rest of the markers, so obviously I'm doing it wrong. However I can't seem to find any coded snippets of anything similar to what I'm trying to achieve.
So here is the actual question:
What sort of display/position/float CSS should I be using to do this instead of position: absolute and float: left? If I need JS to do it, then how to I go about it?
Thanks for any help you can bring me, be it actual code or just a nudge in the right direction!
Here's my (relevant) code:
index.html
<html>
<body>
<div id="timeline">
<div id="labels"></div>
<div id="markers"></div>
</div>
</body>
</html>
script.js:
// hardcoded for debugging purposes
// See section below about the API for info about how I get this data
var markers = [
{label: "Start", pos: "20.00000000000000"},
{label: "First", pos: "50.00000000000000"},
{label: "Second", pos: "200.00000000000000"},
{label: "Last", pos: "576.845412000000000"}
];
function draw_markers(marker_list) {
var label_html = "";
var marker_html = "";
$.each(marker_list, function(index, obj) {
var label = obj.label;
var offset = parseFloat(obj.pos) * 7; // obj.pos is mesured in bars, not px
label_html = label_html +
"<span class='label' style='margin-left:"+offset+"px'>" +
label + "</span>";
marker_html = marker_html +
"<span class='marker' style='margin-left:"+offset+"px'>|</span>";
});
document.getElementById("labels").innerHTML = label_html;
document.getElementById("markers").innerHTML = marker_html;
}
draw_markers(markers);
style.css:
html, body {
background: #eeeeee;
}
#timeline {
height: 4em;
width: 100%;
background-color: #9E9E9E;
}
#labels {
border-bottom: 1px solid black;
height: 50%;
width: 100%;
}
#markers {
height: 50%;
width: 100%;
}
.label {
position: absolute;
float: left;
}
.marker {
position: absolute;
float: left;
}
About the API
We're given a bunch of functions that poll the server at regular intervals and parse the (cleartext) responses. A typical response looks something like this:
MARKERLIST_BEGINMARKER_LIST
MARKER \t label \t ID \t position
...
MARKER_LIST_END
TRANSPORT \t playstate \t position_seconds \t isRepeatOn \t position_string \t position_string_beats
...
Using JS I split each line and use a switch statement to figure out what to do with each line. I then build up a global array containing all the marker in the project with just the info I need.
Alternatively you could use <canvas> to draw the timeline from Javascript (this is what I use for Song Switcher's web interface). Also you can get the project length using the GetProjectLength API function (for example, by calling a script to put the length into a temporary extstate then reading it from the web interface).
function Timeline(canvas) {
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.length = 0;
this.markers = [];
}
Timeline.prototype.resize = function() {
this.canvas.width = this.canvas.clientWidth;
this.canvas.height = this.canvas.clientHeight;
this.scale = this.length / this.canvas.width;
}
Timeline.prototype.update = function() {
this.resize();
this.ctx.fillStyle = '#414141';
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.textBaseline = 'hanging';
for(var marker of this.markers)
this.drawMarker(marker);
}
Timeline.prototype.drawMarker = function(marker) {
const MARKER_WIDTH = 2;
const FONT_SIZE = 14;
const PADDING = MARKER_WIDTH * 2;
var xpos = this.timeToPx(marker.pos);
this.ctx.strokeStyle = this.ctx.fillStyle = 'red';
this.ctx.lineWidth = MARKER_WIDTH;
this.ctx.beginPath();
this.ctx.moveTo(xpos, 0);
this.ctx.lineTo(xpos, this.canvas.height);
this.ctx.stroke();
if(marker.name.length > 0) {
this.ctx.font = `bold ${FONT_SIZE}px sans-serif`;
var boxWidth = this.ctx.measureText(marker.name).width + PADDING;
this.ctx.fillRect(xpos, 0, boxWidth, FONT_SIZE + PADDING);
this.ctx.fillStyle = 'white';
this.ctx.fillText(marker.name, xpos + MARKER_WIDTH, PADDING);
}
}
Timeline.prototype.timeToPx = function(time) {
return time / this.scale;
}
var timeline = new Timeline(document.getElementById('timeline'));
timeline.length = 30; // TODO: Fetch using GetProjectLength
timeline.markers = [
{pos: 3, name: "Hello"},
{pos: 15, name: "World!"},
{pos: 29, name: ""},
];
timeline.update();
window.addEventListener('resize', timeline.update.bind(timeline));
#timeline {
height: 50px;
line-height: 50px;
image-rendering: pixelated;
width: 100%;
}
<canvas id="timeline"></canvas>
you can use divs as display: inline-block and set their width as percentages of deltas of the overlaping absolute timeline positions:
function draw_markers(marker_list) {
var label_html = "";
var marker_html = "";
var total = null;
var prev = 0;
$.each(marker_list, function(index, obj) {
var delta = parseFloat(obj.pos) - prev;
obj.delta = delta;
prev += parseFloat(obj.pos);
total += delta;
})
$.each(marker_list, function(index, obj) {
var label = obj.label;
var offset = parseFloat(obj.delta) / (total / 100); // obj.pos is mesured in bars, not px
label_html = label_html +
"<div class='label' style='width:"+offset+"%'>" +
label + "</div>";
marker_html = marker_html +
"<div class='marker' style='width:"+offset+"%'>|</div>";
});
document.getElementById("labels").innerHTML = label_html;
document.getElementById("markers").innerHTML = marker_html;
}
draw_markers(markers);
css:
html, body {
background: #eeeeee;
}
#timeline {
height: 4em;
width: 100%;
background-color: #9E9E9E;
}
#labels {
border-bottom: 1px solid black;
height: 50%;
width: 100%;
}
#markers {
height: 50%;
width: 100%;
}
.label {
position: relative;
display: inline-block;
}
.marker {
position: relative;
display: inline-block;
}
I have side tabs that are overlaying. I want to be able to click one and do something with it, but I am having trouble getting my event handlers to register correct div.
<div class="tabs">
<div class="blueTab">
<div class="blueTab__container">
</div>
</div>
<div class="brownTab">
<div class="brownTab__container">
</div>
</div>
</div>
.tabs {
position: relative;
margin-left: 853px;
}
.brownTab {
position: absolute;
.brownTab__container {
background-image: url(https://i.imgur.com/Fd49HkH.png) !important;
background-repeat: no-repeat !important;
width: 400px;
height: 853px;
}
}
.blueTab {
position: absolute;
.blueTab__container {
background-image: url(https://i.imgur.com/F5qg6xo.png) !important;
background-repeat: no-repeat !important;
width: 400px;
height: 873px;
}
}
let brownTabElement = document.getElementsByClassName('brownTab')[0]
let blueTabElement = document.getElementsByClassName('blueTab')[0]
brownTabElement.addEventListener('click', brownTabHandler, false)
blueTabElement.addEventListener('click', blueTabHandler, false)
function brownTabHandler() {
alert('brownTab')
}
function blueTabHandler() {
alert('blueTab')
}
When ever I click both the blue or brown tab, only the event handler for the browntab gets called. How can I fix this?
https://jsfiddle.net/Le80rvL0/3/
Your problem is that, even though you can see both tabs (because their backgrounds are partially transparent), the .brownTab__container element is overlapping the .blueTab__container, as they are in the exact same position, so you always click on that one. You can see that using the developer tools' inspector.
One solution to your problem would be to actually create different, non-overlapping elements that look like tabs. Maybe something like this or like this.
Another solution could be to use a single HTML element with a single background image of all the tabs, get the color of the clicked pixel and use it to distinguish the clicked tab. Something like this:
const message = document.getElementById('message');
// Get the tabs element:
const tabs = document.getElementById('tabs');
// Get its computed styles:
const style = window.getComputedStyle(tabs);
// Extract the background-image's url:
const backgroundImage = style.getPropertyValue('background-image');
const url = backgroundImage.substring(5, backgroundImage.length - 2);
// Create an image with that url:
const img = document.createElement('IMG');
img.src = url;
// Create a canvas with the original size of the image:
const canvas = document.createElement('CANVAS');
const width = canvas.width = 1;
const height = canvas.height = 123;
// Draw that image on it:
canvas.getContext('2d').drawImage(img, 0, 0, width, height);
// Listen for click events:
document.getElementById('tabs').addEventListener('click', (e) => {
// Get clicked pixel's RGBA value, taking into account the image on the tabs element is
// repeated, while the one on the canvas it's not:
const rgba = canvas.getContext('2d').getImageData(e.offsetX % width, e.offsetY % height, 1, 1).data;
// Set color thresholds for each tab (as in your images the colors are not uniform as
// they are here:
if (rgba[2] > 200) {
message.innerText = 'You clicked the blue tab.';
} else if (rgba[2] < 150 && rgba[1] > 50) {
message.innerText = 'You clicked the brown tab.';
} else if (rgba[1] > 200) {
message.innerText = 'You clicked the gold tab.';
} else if (rgba[1] < 50) {
message.innerText = 'You clicked the purple tab.';
} else {
message.innerText = 'Unknown tab clicked.';
}
});
body {
position: relative;
margin: 0;
height: 800px;
}
#message {
position: fixed;
top: 0;
left: 0;
right: 90px;
padding: 16px;
font-size: 32px;
}
#tabs {
position: absolute;
width: 90px;
height: 100%;
top: 0;
right: 0;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAB7CAYAAAC1rOouAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAqSURBVChTYzAOPfN/kBJnGtIGK/H+yYbBSpzRBjkSRNzUTkfmDhyR9h8AMPtPIMUTD3YAAAAASUVORK5CYII=);
}
<div id="message"></div>
<div id="tabs"></div>
Keep in mind that with the first approach it will be way easier to add other effects and features like hover/active/focus styles, add/remove tabs, move tabs, drag tabs...
I'm having trouble resizing this canvas that is displaying a video. After resizing, it continually jerks all around into different sizes between the "before" and "after" window sizes.
I tried this posts' idea, and that seemed to calm down Chrome a little, but had no affect on Firefox.
This other post gave me some ideas, but still didn't fix it. It seems like I'm either calling resize multiple times in a loop (which I don't see), or the canvas's context doesn't know how to settle on the final size. Any ideas?
<!DOCTYPE html>
<html>
<head>
<title>overflow</title>
<style>
#c {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
z-index: 1;
}
#hold {
position: fixed;
}
#v {
position: absolute;
height: auto;
width: 100%;
z-index: 0;
}
#see {
position: relative;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
}
</style>
</head>
<body>
<canvas id=c></canvas>
<div id=hold>
<video id=v>
</video>
</div>
<canvas id=see></canvas>
<script>
window.onload = start;
function start() {
var v = document.getElementById('v');
var house = document.getElementById('hold');
var base = document.getElementById('c');
var canvas = base.getContext('2d');
var cover = document.getElementById('see');
var canvastwo = cover.getContext('2d');
v.src=("keyed.ogv")
v.load();
v.play();
resize();
function resize() {
var wth = (window.innerWidth * 0.65);
house.width = wth;
house.height = (wth * 9/16);
house.style.marginTop=((window.innerHeight/2) - (house.height/2) + "px");
house.style.marginLeft=((window.innerWidth/2) - (house.width/2) + "px");
cover.width = (wth/2);
cover.height = (house.height/2);
cover.style.marginTop=((window.innerHeight/2) - (cover.height/2) + "px");
cover.style.marginLeft=((window.innerWidth/2) - (cover.width/2) + "px");
var rw = cover.width;
var rh = cover.height;
canvastwo.clearRect(0, 0, rw, rh);
draw(v, canvastwo, rw, rh);
}
window.onresize = resize;
function draw(o,j,w,h) {
if(v.paused || v.ended) return false;
j.drawImage(o,0,0,w,h);
setTimeout(draw,20,o,j,w,h);
}
}
</script>
</body>
</html>
You seem to lock in the old values you use for the setTimeout function the way you are using it here, as the context changes. So when you re-size the loop still uses the old values which no longer corresponds with the new sizes and results in the video toggle between these sizes.
Try to more "globalize" the values so that the loop call is clean when it comes to arguments. This way you are sure the variables contains the correct values for each round.
Also change setTimeout with requestAnimationFrame to make the loop more low-level (efficient) and fluid as this syncs to the monitor's vblank gap. This is particular important with video as you otherwise will get skipped frames as setTimeout is not able to sync with monitor.
Here is the essential code you need to change:
/// put these into you start block to keep them "global"
/// for the functions within it.
var w, h;
Change this part in the resize function:
/// ...
w = cover.width;
h = cover.height;
canvastwo.clearRect(0, 0, w, h);
/// argument free call to draw:
draw();
And finally the loop:
function draw() {
if(v.paused || v.ended) return false;
canvastwo.drawImage(v,0,0,w,h);
requestAnimationFrame(draw);
}
This will remove the jerking video and also make the update in sync to the monitor like the video element itself does.
ONLINE DEMO