How can I take multiple snapshots (via onclick buttons) from an HTML5 video playing locally, and add the snapshot images with timestamp to a scrollable div without jQuery or external libraries?
I'm able to make a snapshot via canvas but how can I convert the canvas image to a small file size format and append the image (with a href="" scrpt) to a scrolling div?
codepine example http://codepen.io/anon/pen/OVGZEg
HTML
<span> Working example</span>
<br>
<video controls id="sourceVid">
<source src="http://html5multimedia.com/code/ch9/media/elephants-dream-medium.mp4" type="video/mp4">
<source src="../media/elephants-dream-medium.webm" type="video/webm">
</video>
<canvas></canvas>
<br>
<button id="snap" onclick="snap()">Take Snapshot</button>
<br>
<br>
<br>
<!----------------------------------------
Desired Result
---------------------------------------->
<div id="DesiredResult" style="background-color:grey;width: 100%;">
<br>
Desired Result
<br>
How can I take a snapshot & add it to scrolling DIV on the left?
<br>
<video controls id="Result" style="float: left;" >
<source src="http://html5multimedia.com/code/ch9/media/elephants-dream-medium.mp4" type="video/mp4">
<source src="../media/elephants-dream-medium.webm" type="video/webm">
</video>
<div id="snapshotscroll" >
<div id="snapshot#1" class="snapshots" style="background-color:#FE2E2E;" >
snapshot image
<br>#1
</div>
<div id="snapshot#1" class="snapshots" style="background-color:#FA5858;" >
snapshot image
<br>#2
</div>
<div id="snapshot#1" class="snapshots" style="background-color:#F78181;" >
snapshot image
<br>#3
</div>
<div id="snapshot#1" class="snapshots" style="background-color:#F5A9A9;" >
snapshot image
<br>#4
</div>
<div id="snapshot#1" class="snapshots" style="background-color:#F6CECE;" >
snapshot image
<br>#5
</div>
</div>
</div>
<button id="snap" onclick="alert('How can I take a snapshot & add it to scrolling DIV on the left?')">Take Snapshot</button>
CSS
video, canvas {
border:1px solid #000;
}
#snapshotscroll {
overflow-y: scroll;
height:258px;
width:220px;
}
.snapshots {
width: 200px;
height: 100px;
border: 1px solid #000;
}
JAVASCRIPT
// Get handles on the video and canvas elements
var video = document.getElementById('sourceVid');
var canvas = document.querySelector('canvas');
// Get a handle on the 2d context of the canvas element
var context = canvas.getContext('2d');
// Define some vars required later
var w, h, ratio;
// Add a listener to wait for the 'loadedmetadata' state so the video's dimensions can be read
video.addEventListener('loadedmetadata', function() {
// Calculate the ratio of the video's width to height
ratio = video.videoWidth / video.videoHeight;
// Define the required width as 100 pixels smaller than the actual video's width
w = 200;
// Calculate the height based on the video's width and the ratio
h = 100;
// Set the canvas width and height to the values just calculated
canvas.width = w;
canvas.height = h;
}, false);
// Takes a snapshot of the video
function snap() {
// Define the size of the rectangle that will be filled (basically the entire element)
context.fillRect(0, 0, w, h);
// Grab the image from the video
context.drawImage(video, 0, 0, w, h);
}
I ended up getting your example working with a few tweaks. This example uses a counter to keep track of which div to append the snapshot to.
Live Working Example (full screen it):
var w = 200, h = 100, snapnum = 1;
// Takes a snapshot of the video
function snap() {
var cv = document.createElement("canvas");
cv.width = w;
cv.height = h;
console.log(document.getElementById("snapshot#" + snapnum));
document.getElementById("snapshot#" + snapnum).textContent = "";
document.getElementById("snapshot#" + snapnum).appendChild(cv);
var cx = cv.getContext('2d');
cx.fillRect(0, 0, w, h);
// Grab the image from the video
cx.drawImage(document.getElementById('Result'), 0, 0, w, h);
snapnum++;
}
video, canvas {
border:1px solid #000;
}
#snapshotscroll {
overflow-y: scroll;
height:258px;
width:220px;
}
.snapshots {
width: 200px;
height: 100px;
border: 1px solid #000;
}
<!---------------------------------------- Desired Result ---------------------------------------->
<div id="DesiredResult" style="background-color:grey;width: 100%;">
<br>Desired Result
<br>
<video controls id="Result" style="float: left;">
<source src="http://html5multimedia.com/code/ch9/media/elephants-dream-medium.mp4" type="video/mp4">
<source src="../media/elephants-dream-medium.webm" type="video/webm">
</video>
<div id="snapshotscroll">
<div id="snapshot#1" class="snapshots" style="background-color:#FE2E2E;">snapshot image
<br>#1</div>
<div id="snapshot#2" class="snapshots" style="background-color:#FA5858;">snapshot image
<br>#2</div>
<div id="snapshot#3" class="snapshots" style="background-color:#F78181;">snapshot image
<br>#3</div>
<div id="snapshot#4" class="snapshots" style="background-color:#F5A9A9;">snapshot image
<br>#4</div>
<div id="snapshot#5" class="snapshots" style="background-color:#F6CECE;">snapshot image
<br>#5</div>
</div>
</div>
<button id="snap" onclick="snap()">Take Snapshot</button>
JSFiddle Version: https://jsfiddle.net/y80m3z33/
Related
I want to append the video tag with full width in div that id is video using javascript. Could you help me?
let video = document.createElement("video")
video.width = 320;
video.height = 180;
video.style.background = "black"
document.getElementById("video").append(video);
<html>
<body style="background: lightgrey">
<div class="container">
<div id="video"></div>
</div>
</body>
</html>
<video width="100%" height="auto" controls>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
message if vodeo does not show
</video>
with
#video {
width: 100%;
height: auto;
}
in your css, the video will always use the full available width of its parent, in this case, of "container".
I think it's a comment, but I cannot comment, so I post it as an answer.
let video = document.createElement("video")
video.width = 320;
video.height = 180;
video.style.background = "black"
document.getElementById("video").append(video);
#video video {
width: 100% !important;
}
<html>
<body style="background: lightgrey">
<div class="container">
<div id="video"></div>
</div>
</body>
</html>
Here it is:
<script>
var myVideo = document.getElementById("video");
myVideo.innerHTML()='
<video id="video" controls>
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>';
</script>
But the script need to be after the creation of the <div id="video"> tag.
I'm try to play my video in canvas but I got this error:
Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
I can't change the source (the server to support cors), so what can I do to solve this?
document.addEventListener('DOMContentLoaded', function(){
var v = document.getElementById('my-video');
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
var back = document.createElement('canvas');
var backcontext = back.getContext('2d');
var cw,ch;
console.log({ v });
v.addEventListener('play', function(){
cw = v.clientWidth;
ch = v.clientHeight;
canvas.width = cw;
canvas.height = ch;
back.width = cw;
back.height = ch;
draw(v,context,backcontext,cw,ch);
},false);
},false);
function draw(v,c,bc,w,h) {
if(v.paused || v.ended) return false;
// First, draw it into the backing canvas
bc.drawImage(v,0,0,w,h);
// Grab the pixel data from the backing canvas
var idata = bc.getImageData(0,0,w,h);
var data = idata.data;
idata.data = data;
// Draw the pixels onto the visible canvas
c.putImageData(idata,0,0);
// Start over!
setTimeout(draw,20,v,c,bc,w,h);
}
#c {
position: absolute;
top: 50%;
left: 50%;
margin: -180px 0 0 20px;
}
<head>
<link href="https://vjs.zencdn.net/7.6.6/video-js.css" rel="stylesheet" />
<!-- If you'd like to support IE8 (for Video.js versions prior to v7) -->
<script src="https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"></script>
</head>
<body>
<video
id="my-video"
class="video-js"
controls
preload="auto"
width="640"
height="264"
poster="MY_VIDEO_POSTER.jpg"
data-setup="{}"
>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4" />
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a
web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank"
>supports HTML5 video</a
>
</p>
</video>
<canvas id="c" ></canvas>
<script src="https://vjs.zencdn.net/7.6.6/video.js"></script>
</body>
according to the post HTML Canvas: Scaling image to fit without stretching?, when I open an image to fit on canvas it Works if I am using the descktop view, but when I i am using a responsive view It doesn't work well.
My application is published in https://www.galeonweb.es/web, and the code I am using to open an image is:
var img=new Image();
img.onload=function(){
var wrh=img.width/img.height;
var newWidth=canvas.width;
var newHeight=newWidth/wrh;
if (newHeight>canvas.height){
newHeight=canvas.height;
newWidth=newHeight*wrh;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, newWidth, newHeight);
//ctx.drawImage(img,0,0, img.width, img.height, 0,0, canvas.width, canvas.height); //Coloco la imagen en el canvas
imgData=ctx.getImageData(0,0,canvas.width,canvas.height); //Extraigo su array forma.guardarEnHistorico(imgData);
};
img.src=url;
//Cerramos el cuadro de dialogo abrir
ocultarVentana($('#abrir'));
On the other hand, I use a responsive CSS with the following code:
canvas {
width:100%;
height:420px;
background:white;
box-shadow: 0 0 10px black;
}
and the HTML code is:
<div id="lienzo">
<video id="video" class="oculto" preload="none" autoplay>
<source src="video.webM" type="video/webM">
</video>
<button id="snap" class="oculto">Tomar Foto</button>
<canvas id="poo"></canvas>
</div>
I appreciate any help, thanks
I want to get width and height of canvas which is responsive. I have 5 canvas elements on a single page.
Using Javascript before drawing I want to know the height and width of canvas to be able to draw images at the right size.
HTML Code:
<div id='container'>
<div class='all'>
<canvas id='clock1' style="border:solid">
</div>
<div class='all'>
<canvas id='clock2' style="border:solid">
</div>
<div class='all'>
<canvas id='clock3' style="border:solid">
</div>
<div class='all'>
<canvas id='clock4' style="border:solid">
</div>
<div class='all'>
<canvas id='clock5' style="border:solid">
</div>
</div>
CSS:
#container
{
width:100%;
height:100%;
position:relative;
}
.all
{
width:30%;
height:45%;
float:left;
}
canvas
{
width:100%;
height:100%;
}
Usually you don't set size of canvas using CSS but calculating the w/h and use the width and height properties.
But if you use CSS you can get the calculated size of the canvas element set by CSS using getComputedStyle():
Online demo
var cs = getComputedStyle(canvas);
var width = parseInt( cs.getPropertyValue('width'), 10);
var height = parseInt( cs.getPropertyValue('height'), 10);
the size is here returned by getPropertyValue() as a string and in pixel size (ie. "400px"), so we use parseInt() to chop of the "px" part.
Then simply set the width and height on canvas and update its content.
Full example (adjust as needed):
window.onresize = updateCanvas;
updateCanvas();
function updateCanvas() {
var cs = getComputedStyle(canvas);
var width = parseInt(cs.getPropertyValue('width'), 10);
var height = parseInt(cs.getPropertyValue('height'), 10);
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(width, height);
ctx.moveTo(0, height);
ctx.lineTo(width, 0);
ctx.stroke();
}
How do I get a video to be play on the canvas under my canvas animation?
For instance this clip.
So this animation moves along the bottom of the video.
Code:
<html>
<head>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.3.js'></script>
<script type="text/javascript">
var context;
var text = "";
var textDirection ="";
$(function()
{
context = document.getElementById("cvs").getContext("2d");
setInterval("animate()", 360);
textDirection ="right";
textXpos = 5;
text = "This is my video..";
});
function animate() {
// Clear screen
context.clearRect(0, 0, 500, 500);
context.globalAlpha = 1;
context.fillStyle = '#fff';
context.fillRect(0, 0, 500, 500);
var metrics = context.measureText(text);
var textWidth = metrics.width;
if (textDirection == "right") {
textXpos += 10;
if (textXpos > 500 - textWidth) {
textDirection = "left";
}
}
else {
textXpos -= 10;
if (textXpos < 10) {
textDirection = "right";
}
}
context.font = '20px _sans';
context.fillStyle = 'black';
context.textBaseline = 'top';
context.fillText ( text, textXpos, 180);
}
</script>
</head>
<body>
<div id="page">
<canvas id="cvs" width="500" height="500">
Your browser does not support the HTML 5 Canvas.
</canvas>
</div>
</body>
</html>
I don't think you need to play the video in the canvas. Just create a video element in your HTML and use CSS to place your canvas element over it.
HTML:
<div id="page">
<video id="video" autoplay loop>
<source id='mp4'
src="http://media.w3.org/2010/05/sintel/trailer.mp4"
type='video/mp4'>
<source id='webm'
src="http://media.w3.org/2010/05/sintel/trailer.webm"
type='video/webm'>
<source id='ogv'
src="http://media.w3.org/2010/05/sintel/trailer.ogv"
type='video/ogg'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
<canvas id="cvs" width="500" height="500">
Your browser does not support the HTML 5 Canvas.
</canvas>
</div>
CSS:
#cvs {
position: absolute;
top: 0px;
left: 0px;
}
Fiddle.