When saving a screenshot of large video files on a canvas, it seems that it cannot get its blob. It is working fine when the video blob has been displayed on the container.
Here's a JSFiddle without timeout (does not work)
Here's a JSFiddle with timeout (works)
$('#txtFileUpload').on('change', function() {
var countFiles = $(this)[0].files.length;
for (var ctr = 0; ctr < countFiles; ctr++) {
var reader = new FileReader();
readerOnLoad(reader, ctr, $(this)[0], this.files[0]);
}
});
var readerOnLoad = function(reader, ctr, fileInput, files) {
reader.onloadend = (function(ctr) {
return function(e, ctr) {
var videoIdClass = 'thumb-video-' + ctr;
var $video = $('<video />', {
'src': e.target.result,
'id': videoIdClass,
'class': videoIdClass,
}).appendTo($('.video-container')).wrap('<div class="thumb-container"></div>');
setVideoCapture($video);
};
})(ctr);
reader.readAsDataURL(fileInput.files[ctr]);
}
var setVideoCapture = function(videoElement) {
var $output;
var $canvas = document.createElement('canvas');
var $img = document.createElement('img');
$output = $('#output');
$video = videoElement.get(0);
$canvas.width = $video.videoWidth * 2;
$canvas.height = $video.videoHeight * 2;
$canvas.getContext('2d').drawImage($video, 0, 0, $canvas.width, $canvas.height);
$img.src = $canvas.toDataURL();
$output.prepend($img);
}
A quick fix would be set a timeout on the setVideoCapture method like this:
This works.
var setVideoCapture = function(videoElement) {
setTimeout(function() {
var $output;
var $canvas = document.createElement('canvas');
var $img = document.createElement('img');
$output = $('#output');
$video = videoElement.get(0);
$canvas.width = $video.videoWidth * 2;
$canvas.height = $video.videoHeight * 2;
$canvas.getContext('2d').drawImage($video, 0, 0, $canvas.width, $canvas.height);
$img.src = $canvas.toDataURL();
$output.prepend($img);
}, 2000, videoElement)
}
Weird that it has to be INSIDE the setVideoCapture method and not when triggering the setVideoCapture method like this:
This does not work.
reader.onloadend = (function(ctr) {
return function(e, ctr) {
var videoIdClass = 'thumb-video-' + ctr;
var $video = $('<video />', {
'src': e.target.result,
'id': videoIdClass,
'class': videoIdClass,
}).appendTo($('.video-container')).wrap('<div class="thumb-container"></div>');
setTimeout(setVideoCapture($video), 3000, $video);
};
})(ctr);
But of course using a setTimeout is not a recommended fix. What should be is that setVideoCapture method should only be triggered when the $video element has already been appened and displayed on the container.
Nevermind, I was able to fix this by:
$video.addEventListener('loadeddata', function() {
// do something here
}, false);
Related
I got this code from a website and applied to my code:
window.onload = function () {
var fileUpload = document.getElementById("fileupload");
fileUpload.onchange = function () {
if (typeof (FileReader) != "undefined") {
var dvPreview = document.getElementById("dvpreview");
dvPreview.innerHTML = "";
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png)$/;
for (var i = 0; i < fileUpload.files.length; i++) {
var file = fileUpload.files[i];
if (regex.test(file.name.toLowerCase())) {
var reader = new FileReader();
reader.onload = function (e) {
var img = document.createElement("IMG");
img.width="300";
img.height ="300";
img.src = e.target.result;
dvPreview.appendChild(img);
}
reader.readAsDataURL(file);
} else {
alert(file.name + " is not a valid image file.");
dvPreview.innerHTML = "";
return false;
}
}
}
}
};
It works properly, but I want some more style to be added to my code. Specially the padding and the object-fit css properties.
I tried to run:
img.objectFit="cover";
img.style.objectFit="cover";
img.css("object-fit","cover");
and a lot more possibilities that i could search and apply, but any of those worked out.
What is the right way to make this work?
var img = document.createElement('img');
img.width = '300';
img.height = '300';
img.style.padding = '20px';
img.style.objectFit = 'fill';
document.body.appendChild(img);
var $img = 0;
var arraySrc=[];
var main = function () {
var i = 0;
var url = "myurl";
$.getJSON(url, function (Response) {
flickrResponse.items.forEach(function (photo) {
$img = $('<img />', { id: 'img' + i, rc: photo.media.m, alt: 'MyAlt' });
var queryData = {src:$img.attr('src')}
arraySrc.push(queryData);
$("main .photos").append($img);
i++;
});
$(document).ready(main);
I'm having trouble with a simple file input.
I'm trying to get the width, height and dataURL of multiple images and save them to global variables, but all that's saved is "undefined".
When I tried to make a "demo-fiddle" the "onchange"-event doesn't even seem to fire.
can anyone help me out?
Here's the code of the demo-fiddle:
var WIDTH = [];
var HEIGHT = [];
var SRC = [];
$(window).load(function()
{
grabData();
displayImgs();
});
function grabData()
{
$("#fileInput").on("change",function(e)
{
var file = e.target.files;
for(var i = 0; i<file.length; i++)
{
var reader= new fileReader();
var img = new Image();
reader.onload = function(e)
{
SRC = e.target.result;
img.onload = function()
{
WIDTH = this.width;
HEIGHT = this.height;
}
}
reader.readAsDataURL(file);
console.log(WIDTH);
}
console.log(WIDTH);
});
}
function displayImgs()
{
/*display images*/
for(var i = 0; i<SRC.length; i++)
{
$("body").append("<img src="+SRC[i]+" width="+WIDTH[i]+" height="+HEIGHT[i]+">");
}
}
try below code, tested in fiddle and working - http://jsfiddle.net/02468Lr9/
var WIDTH = [];
var HEIGHT = [];
var SRC = [];
$(document).ready(function() {
grabData();
;
});
function grabData() {
$("#fileInput").on("change",function(e) {
var file = e.target.files;
for(var i = 0; i<file.length; i++) {
var reader= new FileReader();
var img = new Image();
reader.onload = function(e) {
SRC.push(e.target.result);
img.onload = function() {
alert(this.width);
WIDTH.push(this.width);
HEIGHT.push(this.height);
displayImgs();
}
img.src = e.target.result;
}
reader.readAsDataURL(file[i]);
}
});
}
function displayImgs()
{
/*display images*/
for(var i = 0; i<SRC.length; i++) {
console.log(WIDTH);
$("body").append("<img src="+SRC[i]+" width="+WIDTH[i]+" height="+HEIGHT[i]+">");
}
}
The log result is undefined because you log it outside the onload function, and for that it runs before the images load and the value is still undefined.
I'm trying to make drag n' drop upload file in JS. I've written code as follow:
<div id="drop_zone">
<div style="clear: both"></div>
</div>
<output id="list"></output>
<script type="text/javascript">
var Vector = function() {
var _array = [];
this.add = function(item) {
_array.push(item);
};
this.delete = function(index) {
_array.splice(index, 1);
};
this.foreach = function(callback) {
for(i=0; i<_array.length; i++) {
callback(_array[i]);
}
};
this.length = function() {
return _array.length;
};
this.clear = function() {
_array = [];
};
};
var Snap = function(args) {
this.name = args.name || null;
this.type = args.type || null;
this.size = args.size || null;
this.modified = args.modified || null;
this.source = args.source || null;
}
var images = new Vector();
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files;
if(files.length != 0) {
for(var i=0, f; f = files[i]; i++) {
var image = new Snap({
name : escape(f.name),
type : f.type||'n/a',
size : f.size,
modified : f.lastModifiedDate ? f.lastModifiedDate.toLocaleString() : 'n/a'
});
var file = files[i];
var filereader = new FileReader;
filereader.onload = function(e) {
image.source = this.result;
};
filereader.readAsDataURL(file);
images.add(image);
}
}
alert(images.length());
render();
}
function render() {
var list = document.getElementById('list');
images.foreach(function(elem) {
var div = document.createElement('div');
var divtext = elem.name + '(<i>' + elem.type + '</i>), ' + elem.size + ' <small>[' + elem.modified + ']</small>';
div.innerHTML = divtext;
list.appendChild(div);
var img = document.createElement('img');
img.src = elem.source;
document.getElementById('drop_zone').appendChild(img);
});
}
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy';
}
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
</script>
It's not working as I wish.
This view is after I drag image first time. images.length = 1
This view is after I drag image second time. images.length actually = 2, not 3, so Vector images works as it is supposed to work.
View after third dragging, one and the same image. images.length = 3, not 6, so when it comes to Vector, it's ok.
I haven't no idea how to make it works.
Thanks in advance.
I wanna display images instantly as all the images are loaded for my smooth slider,
but its not working.
var myPhotos = {
_counter: 0,
images: [],
init: function() {
ServerCall1(0, 'xml', 'rssphotos.php', function(xml) {
imageObj = new Image();
$(xml).find('item').each(function() {
var desc = $(this).find('description').text();
var resp = getImgArray(desc);
myPhotos.images[myPhotos._counter] = resp[0];
myPhotos._counter++;
});
//start preloading
for (i = 0; i < myPhotos._counter; i++) {
imageObj.src = myPhotos.images[i];
}
////PUT THE HEADER HOME PAGE
topHeader.putData(topHeader.photoData());
});
}
};
After the execution of this function, I loop through myPhotos.images to get them instantly, but its rendering one by one very slowly.
Perhaps this
var myPhotos = {
_counter: 0,
images: [],
init: function() {
ServerCall1(0, 'xml', 'rssphotos.php', function(xml) {
$(xml).find('item').each(function() {
var desc = $(this).find('description').text();
var resp = getImgArray(desc);
myPhotos.images[myPhotos._counter] = resp[0];
myPhotos._counter++;
});
//start preloading
for (i = 0; i < myPhotos._counter; i++) {
this.images[i]= new Image(); this.images[i].src = myPhotos.images[i];
}
////PUT THE HEADER HOME PAGE
topHeader.putData(topHeader.photoData());
});
}
};