Displaying multiple Thumbnails not working - javascript

So I am making this "drop-zone" for a website.
The user can drag and drop images over this area and all jpegs that are dropped on the area are displayed as thumbnailes. I made a List of all jpegs that are dropped on the area and that is working fine. Now everytime a new jpeg is added to that list I want to display all jpegs as thumbnailes of the size 100x150px.
Here is my code for that.
And here is a like to the fiddle http://jsfiddle.net/cJkYj/2/
function displayThumbnailes( ) {
//Clear the div.
var outerDiv = document.getElementById('fileChooserDiv');
while (outerDiv.hasChildNodes()) {
outerDiv.removeChild(outerDiv.lastChild);
}
var div = document.createElement('div');
outerDiv.appendChild(div);
//Go over the Files and add Thumbnails for all jpegs.
for( var i = 0; i < files.size(); i++) {
if( files.get(i).type == "image/jpeg") {
var reader = new FileReader();
reader.onloadend = function() {
var result = reader.result;
displayThumbnail( result, div );
}
reader.readAsDataURL(files.get(i));
}
}
}
function displayThumbnail( src, div ) {
var img = new Image();
img.onload = function () {
var cv = document.createElement('canvas');
cv.style.border = "1px solid #ffffff";
cv.width = 100;
cv.height = 150;
var ctx = cv.getContext( "2d" );
ctx.drawImage(img, 0, 0, 100, 150);
div.appendChild(cv);
}
img.src = src;
}
MY PROBLEM: I believe this code would display all thumbnailes in the area of the div but I only see the last one.
This looks like I am messing up some synchronisation or something.
"files" is an Object that manages the files dragged on the "drop-zone".
I want every Thumbnail to have his own canvas so I can add an onclick event to them later.
Any help would be appriciated ^^

Your code:
reader.onloadend = function() {
var result = reader.result;
displayThumbnail( result, div );
}
reader.readAsDataURL(files.get(i));
was failing because of the async onloadend callback. Each pass through the loop updated the outer reader variable, so each event used only the last reference.
You could either change your code to wrap that in a closure:
(function(reader) {
reader.onloadend = function() {
var result = reader.result;
displayThumbnail( result, div );
}})(reader);
or (preferred) change your code to use the event specific data :
reader.onloadend = function(evt) {
var result = evt.target.result;
displayThumbnail( result, div );
};
-- or using onload --
reader.onload = function (evt) {
var result = evt.target.result;
displayThumbnail(result, div);
}
reader.readAsDataURL(files.get(i));
works: example
I should also note that I rearranged your code to completely run within an onload handler.

Related

Can't draw imported image through input file

I am trying to load an image with an html input type="file" and load it to an with javascript without success.
Here is my code so far:
HTML:
<canvas class="imported" id="imported"></canvas>
<button class="import_button" id="import_button">Import a picture</button>
<input type="file" id="imgLoader"/>
JAVASCRIPT:
document.getElementById('import_button').onclick = function() {
document.getElementById('imgLoader').click();
};
document.getElementById('imgLoader').addEventListener('change', importPicture, false);
function importPicture()
{
alert("HERE");
var canvas = document.querySelector('#imported');
var context = canvas.getContext("2d");
var fileinput = document.getElementById('imgLoader');
var img = new Image();
var file = document.getElementById('imgLoader').files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(evt)
{
alert("THERE");
if( evt.target.readyState == FileReader.DONE)
{
alert("AGAIN");
img.src = evt.target.result;
context.drawImage(img, 200, 200);
}
}
}
The alerts are all fired up, no errors or message in the console..
How can I load it and display it? Thank you!
The logic (of your original code, not the edited version) is a bit baffling:
document.getElementById('imgLoader').addEventListener('change', importPicture, false);
adds a change event to the file input. That's fine. But then within the "importPicture" function, which runs when the file input changes, you add another change event listener (via fileinput.onchange) ...why are you doing that? I can't see how it makes sense. It means you have to change the file again before the code in there runs. And it also means that every time you change the file it adds more and more listeners, until you have lots of functions firing at once.
The other problem is that you're not waiting for the data to be loaded into the Image object before you try to draw the image on the canvas. You also need to set the dimensions of the canvas itself, and not be prescriptive about the dimensions of the image (because the user could upload anything, of any size).
Here's a working demo:
document.getElementById('import_button').onclick = function() {
document.getElementById('imgLoader').click();
};
var fileinput = document.getElementById('imgLoader').addEventListener('change', importPicture, false);
function importPicture() {
var canvas = document.querySelector('#imported');
var context = canvas.getContext("2d");
var img = new Image();
var file = this.files[0];
var reader = new FileReader();
reader.onload = function(evt) {
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0);
}
img.src = evt.target.result;
}
reader.readAsDataURL(file);
}
<canvas class="imported" id="imported"></canvas>
<button class="import_button" id="import_button">Import a picture</button>
<input type="file" id="imgLoader" />
Credit to this answer for the final bits.

Saving a image which is captured by a camera on local machine on a folder

I am using HTML5 inputs to take a picture from camera using below line,
<input id="cameraInput" type="file" accept="image/*;capture=camera"></input>
and getting used image in blob:, using following javascript,
var mobileCameraImage = function() {
var that = this
;
$("#cameraInput").on("change", that.sendMobileImage);
if (!("url" in window) && ("webkitURL" in window)) {
window.URL = window.webkitURL;
}
});
var sendMobileImage = function( event ) {
var that = this;
if (event.target.files.length == 1 && event.target.files[0].type.indexOf("image/") == 0) {
var capturedImage = URL.createObjectURL(event.target.files[0])
;
alert( capturedImage );
}
});
Here, I am getting proper image url but the problem i am facing is to send this image url to the server, After reading blogs i found i can not send Blob: url to the server due to its local instance. Does anyone can help to save the clicked image on local machine on a folder or any where, or to help how i can send this image url to the server.
Thanks in advance.
You may need to submit your form every time via Ajax or you may upload the image data manually. In order to do that, you may draw the image unto a canvas, then obtain the canvas data.
// create an image to receive the data
var img = $('<img>');
// create a canvas to receive the image URL
var canvas = $('<canvas>');
var ctx = canvas[0].getContext("2d");
$("#cameraInput").on("change", function () {
var capturedImage = URL.createObjectURL(this.files[0]);
img.attr('src', capturedImage);
ctx.drawImage(img);
var imageData = canvas[0].toDataURL("image/png");
// do something with the image data
});
Or use a FileReader
// only need to create this once
var reader = new FileReader();
reader.onload = function () {
var imageData = reader.result;
// do something with the image data
};
$("#cameraInput").on("change", function () {
reader.readAsDataURL(this.files[0]);
});
Then you can upload that data to the server.

Is there a way to check if a SVG has valid source? (problems creating svg to canvas)

When using an SVG generated by a chart plugin ( https://wordpress.org/plugins/visualizer/ ) I can't figure out how to retrieve the source of the SVG-image being generated. I have tried to use other SVG's with exactly the same code and it works like a charm, but SVG's generated from the Visualizer plugin - for some reason - does not work.
The onload-function is not triggered.
No errors are shown in console.
No image is created in canvas
My suspicion is that there are stuff in that SVG that are not valid - which makes the source of SVG not being valid!? I'm not sure, but that seems to be som kind of issue. Please tell me if I'm totally on the "wrong track" here..
Javascript:
var svgText = document.getElementById("myViewer").outerHTML;
var myCanvas = document.getElementById("canvas");
var ctxt = myCanvas.getContext("2d");
function drawInlineSVG(ctx, rawSVG, callback) {
var svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"}),
domURL = self.URL || self.webkitURL || self,
url = domURL.createObjectURL(svg),
img = new Image;
img.onload = function () {
//Does not come here...
ctx.drawImage(this, 0, 0);
domURL.revokeObjectURL(url);
callback(this);
};
img.src = url;
}
// usage:
drawInlineSVG(ctxt, svgText, function() {
console.log(canvas.toDataURL()); // -> PNG
alert("see console for output...");
});
For some reason the following code was triggered, even though the final result was not what I expected it to be...
img.onload = savepng();
function savepng() {
// ...code...
}
But the following was not triggered...
img.onload = function() {
// ...code...
}
The issue was that the SVG needed to be declared as an XML document. It is strange that no error arose because of this
I added some rows to my code and now it's working.
var svgBase = document.getElementById("myViewer");
//This attribute is needed for the image creation to work
svgBase.setAttribute("xmlns", "http://www.w3.org/2000/svg");
//this attribute is not needed for the imagecreation to work,
//but I guess it doesn't hurt to add this...
svgBase.setAttribute("xmlns:svg", "http://www.w3.org/2000/svg");
//Get the outer html now when xml is declared
var svgText = svgBase.outerHTML;
UPDATE
Based on recommendation in the comments (from #Kaiido) below I have changed my code to:
var svgBase = document.getElementById("myViewer");
var svgURL = new XMLSerializer().serializeToString(svgBase);
var myCanvas = document.getElementById("mycanvas");
var ctxt = myCanvas.getContext("2d");
var img = new Image();
img.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgURL);
//Wait for image to be being loaded
img.onload = function() {
ctxt.drawImage(img,0,0);
var dataPNG = myCanvas.toDataURL('image/png');
console.log(dataPNG);
}

Why produce the canvas rendering an empty image file? [duplicate]

This question already has answers here:
async or sync ? when we set the src property of the Image object?
(4 answers)
Closed 7 years ago.
My goal:
If the Camera button on my site is clicked > open the smartphone Camera > take a picture from a qr-code > resize it with js > load the picture on my server > read the qr-code > give me the value from the qr-code back.
My problem is that my code produce an empty image file(jpg) and gives me an error.
I tested it with uploading a existing qr-code image and it works on the second try to upload it. On the first try i get the same error like if i try to upload the taken picture from the smartphone.
my html
<form id="qr-code-upload-form" class="form-group" action="" method="post" enctype="multipart/form-data">
<label>
<span id="qr-pic" class="glyphicon glyphicon-camera"></span>
<input type="file" capture="camera" accept="image/*" id="cameraInput" name="cameraInput" style="display: none;">
</label>
<canvas id="cnvsForFormat" width="400" height="266" style="display:none;"></canvas>
</form>
my js/jquery
$(document).ready(function(){
$('body').on("change", "#cameraInput", readCode);
function readCode() {
var cnvs=document.getElementById("cnvsForFormat");
var input = document.getElementById('cameraInput').files[0];
var img = new Image();
if (input) {
var reader = new FileReader();
reader.onload = function (e) {
//Get the input image file
img.src = e.target.result;
var newHeight = img.height/2;
var newWidth = img.width/2;
//reduce the size until its lower than 600px
while (newWidth>600 || newHeight>600) {
newHeight = newHeight/2;
newWidth = newWidth/2;
}
$("#cnvsForFormat").attr("height",newHeight);
$("#cnvsForFormat").attr("width",newWidth);
//Draw the input image in a canvas with the right size for the upload
var ctx=cnvs.getContext("2d");
ctx.drawImage(img,0,0, newWidth, newHeight);
var resizedImg = cnvs.toDataURL("image/jpeg");
//Send the resized Image to my php-request-file
$.post("?cmd=ajax&param=qr_verarbeiten",{photo:resizedImg},function(e) {
alert(e);
});
};
reader.readAsDataURL(input);
}
};
});
</script>
my php to read the qr-code
if (isset($_GET['param']) && $_GET['param'] == "qr_verarbeiten" && isset($_POST['photo'])) {
$img = base64_decode(substr($_POST['photo'],23));
file_put_contents("img/upload/qr.jpg", $img);
$qrcode = new QrReader("img/upload/qr.jpg");
echo $qrcode->text();
}
I use jQuery, Bootstrap and SMARTY in that project
I really hope somebody can help me!
Thanks for taking time to read this and i apologize for my bad english.
The problem was in the js. And i've added the js/MegaPixImage Libraray to handle the big files i get from the iPhone Camera - The working code is :
$(document).ready(function(){
$('body').on("change", "#cameraInput", readCode);
function readCode() {
// var cnvs=document.getElementById("cnvsForFormat");
var input = document.getElementById('cameraInput').files[0];
if (input) {
var img = new Image();
var reader = new FileReader();
reader.onload = function (e) {
img.onload = function() {
var count=0;
while (img.width<1) {
count++;
}
var newHeight = img.height;
var newWidth = img.width;
while (newWidth>600 || newHeight>600) {
newHeight = newHeight/2;
newWidth = newWidth/2;
}
var renderImg = new Image();
var mpImg = new MegaPixImage(img);
mpImg.render(renderImg, { width: newWidth, height: newHeight });
$.post("?cmd=ajax&param=qr_verarbeiten",{photo:renderImg.src},function(e) {
alert(e);
});
};
img.src = e.target.result;
};
reader.readAsDataURL(input);
}
};
});
I got it. It was cause the browser load the img.src asynchron. So i have to add an img.onload function before i load my img.src to make sure the img is already rendered. ;-)
I've added the working code to my question.

drag and drop images from `dropbox` account to html canvas - `not working in chrome`

This code is to drag images from image gallery and drop inside canvas (fabric.js is used) and also drag and drop images from dropbox account which is opend in another tab. This works fine in firefox, I can drag images from my drop box account and drop in inside canvas. But not in chrome. e.dataTransfer.getData("Text") gives an empty value in chrome. I thought it's a problem of same-origin-policy and tried a lot to fix it. But no luck. Please help me to get a work around for this.
function handleDrop(e) {
e.stopPropagation();
e.preventDefault();
// handle local images
if(e.dataTransfer.files.length > 0){
var files = e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (f.type.match('image.*')) {
// Read the File objects in this FileList.
var reader = new FileReader();
// listener for the onload event
reader.onload = function(evt) {
// create img element
var img = document.createElement('img');
img.src= evt.target.result;
// put image on canvas
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
// Set the center of the new object based on the event coordinates relative to the canvas container.
left: e.layerX,
top: e.layerY
});
canvas.add(newImage);
};
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
}
// handle dropbox images
else{
var img = e.dataTransfer.getData("Text");
console.log(img);
var img = e.dataTransfer.getData("Text");
if (img.indexOf('jpg')>0 ||img.indexOf('png')>0){
var temp = '<img draggable="true" src="'+img+'" width="250" height="250"></img>';
$('#before').append(temp);
var i = document.querySelector('img[src="'+img+'"]');
console.log('i: ',i);
var nI = new fabric.Image(i,{
width: i.width,
height:i.height,
left:e.layerX,
top:e.layerY
});
canvas.add(nI);
}
}
return false;
}

Categories