I'm trying to get an image from a canvas, it worked on pc browsers, but not on mobile (I tested on an iPhone in Safari)...
Here is the code:
$('#draw').click(function() {
$('#drawing').css("visibility", "visible");
var drawing = document.getElementById("drawing");
var con = drawing.getContext("2d");
var img = new Image();
img.src = "http://www.deque.com/wbcntnt928/wp-content/dquploads/jquery_logo.png";
img.onload = function() {
con.drawImage(img, 0, 0, 250, 250);
//Generate Image
var drawing = document.getElementById("drawing");
var dataURL = drawing.toDataURL(); //Does nothing on mobile, not even an error
document.getElementById("result").src = dataURL;
};
});
Any hint of why?
I have the same issue. Tested on HTC Desire with Android 2.3, HTC One with Android 4.0 and iPhone 7s ... I run over the toDataURL() but only get "data:," as output.
According to here it's not supported by Android, dunno about iOS7 but it seems it isn't either.
Btw. is there a reason for calling var drawing = document.getElementById("drawing"); twice?
Related
Ok, so a little bit of background... I'm trying to generate animated gifs from animations done on an HTML5 canvas using JavaScript. Specifically, I'm adding data layers to a Mapbox GL JS map and looping through them.
On each iteration, I save the canvas element and transform it to a blob before calling URL.createObjectURL(blob) and setting that as the source to a new image. After the loop is finished I generate a gif using gifshot (https://github.com/yahoo/gifshot) and the images I previously created.
This process works perfectly in all browsers (mobile too!) EXCEPT on iPhone ios. On ios the gif has weird stutters and transparency issues. I have tried other gif creation libraies but all have the same issue on ios. Could it be a memory problem or something? I'm at my wit's end on this, so any help is greatly appreciated!
This is the code inside each loop:
var cv = map.getCanvas()
var oneImage = new Image();
cv.toBlob(function(blob) {
url = URL.createObjectURL(blob);
oneImage.src = url
images_arr.push(oneImage)
i++;
setTimeout(function(){
gifLoop(images_arr);
},1000)
})
and this is the code I call when the loop is finished:
var w = window.innerWidth;
var h = window.innerHeight;
recalculated_size = calculateAspectRatioFit(w, h, maxWidth, maxHeight)
w = recalculated_size.width
h = recalculated_size.height
gifshot.createGIF({
'images': images_arr,
'gifWidth': w,
'gifHeight':h,
},function(obj) {
if(!obj.error) {
var image = dataURItoBlob(obj.image)
image = URL.createObjectURL(image);
var animatedImage = document.getElementById('gif');
animatedImage.src = image
var link = $('#gif-link');
link.attr('href',image);
filename = curr_layer_id + '_' + curr_time +'.gif'
link.attr('download', filename);
}
});
I am working with a single canvas that allows the user to click on a window pane in a window image. The idea is to show where the user has clicked. The image will then be modified (by drawing a grill on the window) and then saved to in JPEG. I am saving the canvas image prior to the click function because I don't want the selection box to show in the final image. However, Firefox often displays a blank canvas when restoring the canvas where IE and Chrome do not. This works perfectly in Chrome and IE. Any suggestions? Does Firefox have a problem with toDataURL()? Maybe some async issue going on here? I am also aware that saving a canvas in this fashion is memory intensive and there may be a better way to do this but I'm working with what I have.
Code:
/**
* Restores canvas from drawingView.canvasRestorePoint if there are any restores saved
*/
restoreCanvas:function()
{
var inverseScale = (1/drawingView.scaleFactor);
var canvas = document.getElementById("drawPop.canvasOne");
var c = canvas.getContext("2d");
if (drawingView.canvasRestorePoint[0]!=null)
{
c.clearRect(0,0,canvas.width,canvas.height);
var img = new Image();
img.src = drawingView.canvasRestorePoint.pop();
c.scale(inverseScale,inverseScale);
c.drawImage(img, 0, 0);
c.scale(drawingView.scaleFactor, drawingView.scaleFactor);
}
},
/**
* Pushes canvas into drawingView.canvasRestorePoint
*/
saveCanvas:function()
{
var canvas = document.getElementById("drawPop.canvasOne");
var urlData = canvas.toDataURL();
drawingView.canvasRestorePoint.push(urlData);
},
EXAMPLE OF USE:
readGrillInputs:function()
{
var glassNum = ir.get("drawPop.grillGlassNum").value;
var panelNum = ir.get("drawPop.grillPanelNum").value;
drawingView.restoreCanvas();
drawEngine.drawGrill(glassNum, panelNum,null);
drawingView.saveCanvas();
},
sortClick:function(event)
{
..... //Sorts where user has clicked and generates panel/glass num
.....
drawingView.showClick(panelNum, glassNum);
},
showClick:function(panelNum, glassNum)
{
var glass = item.panels[panelNum].glasses[glassNum];
var c = drawEngine.context;
drawingView.restoreCanvas();
drawingView.saveCanvas();
c.strokeStyle = "red";
c.strokeRect(glass.x, glass.y, glass.w, glass.h);
},
By just looking at the code setting the img.src is an async action to retrieve the image, so when you try to draw it 2 lines later to the canvas, it probably hasn't been loaded yet (having it in cache will make it return fast enough that it might work).
You should instead use an img.onload function to draw the image when it has loaded.
restoreCanvas:function()
{
var inverseScale = (1/drawingView.scaleFactor);
var canvas = document.getElementById("drawPop.canvasOne");
var c = canvas.getContext("2d");
if (drawingView.canvasRestorePoint[0]!=null)
{
c.clearRect(0,0,canvas.width,canvas.height);
var img = new Image();
img.onload = function() {
c.scale(inverseScale,inverseScale);
c.drawImage(img, 0, 0);
c.scale(drawingView.scaleFactor, drawingView.scaleFactor);
};
img.src = drawingView.canvasRestorePoint.pop();
}
},
I'm working on a multi part html questionnaire style form that has a lot of text questions along with a few images. On questions that are images the user is selects the image, i create a canvas element and display the resized image in it underneath the file input.
if (window.FileReader)
{
var file = element.files[0];
var $input = $(element);
var $fileName = file.name;
var reader = new FileReader();
reader.onload = function(e) {
var img = document.createElement("img");
img.src = e.target.result;
var dataID = $input.data("questionId");
var canvasID = "canvas_" + dataID;
$("#"+canvasID).remove();
var canvas = document.createElement("canvas");
canvas.setAttribute("id", canvasID);
canvas.setAttribute("height", "200");
canvas.setAttribute("width", "200");
var heightWidth = getHeightWidth(img);
canvas.height = heightWidth[0];
canvas.width = heightWidth[1];
var ctx = canvas.getContext("2d");
ctx.drawImage(img,0,0, canvas.width, canvas.height);
var sectionID = "section_" + dataID;
$("#" + sectionID).append(canvas);
$("#file_title-" + dataID).val($fileName);
}
reader.readAsDataURL(file);
}
else
{
alert("This browser does not support image uploading.");
}
This works fine in chrome but not in safari (safari 8.x) on desktop or iOS. The problem in my code is that on Safari it returns height=0 width=0 from getHeightWidth() which gives me think the img isn't ready to be handled yet. This theory is further validated because if i change to a new picture and change back to the original it displays properly.
I'm really not sure where to start, any help debugging this would be greatly appreciated. Thanks everyone
The code assumes the image loading is synchronous, but it's asynchronous and should be assumed so even with data-URIs. If the image hasn't loaded properly its width and height attributes will be 0.
You can solve this by adding an onload handler for img, then move the code for detecting and setting size inside that handler (remember also to add an onerror handler as well in case the image file is corrupted).
I am having problems running the CamanJS script on mobile devices, i.e. iPad and iPhone's Safari / Chrome, and I've been trying to resolve it for days.
The test script is very simple:
1) Accepts browser file selection of image
2) Gets the image source using FileData, then drawing it into a canvas, then instantiate a Caman("#sample") object
3) Run some filter (either within onLoad of that image, or manually by clicking a button)
It works perfectly fine on all desktop browsers and the filters are also successfully applied, but when I try it on mobile devices like iOS Safari, the moment I try to instantiate the Caman object, my existing canvas #sample goes blank and reverts to the original canvas default background color, with no image loaded at all. I've tried instantiating the Caman object before image is drawn on canvas, image onLoad, or on demand after the canvas image is successfully drawn, but the end result is still the same - the canvas goes blank.
Below is my sample code, can someone please advise? Thank you for your kind assistance.
<script>
var caman = null;
function handleUpload(evt) {
var target = (evt.target) ? evt.target : evt.srcElement;
var files = target.files; // FileList object
var field = target.id;
var curCount = target.id.replace(/\D+/, "");
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
renderImage(e.target.result);
};
})(f);
reader.readAsDataURL(f);
}
}
function renderImage(imagedata) {
var canvas = document.getElementById("sample");
var ctx = canvas.getContext("2d");
// Render Preview
var previewImage = new Image();
previewImage.src = imagedata;
previewImage.onload = function() {
ctx.drawImage(previewImage, 0, 0, previewImage.width, previewImage.height);
caman = Caman("#sample", function () { this.sunrise().render(); });
};
}
function testProcess() {
//caman = Caman("#sample", function () { this.sunrise().render(); });
if (caman) {
caman.sunrise().render();
}
}
</script>
<form>
<input id="photo" name="photo" value="" type=file size="30" maxlength="50">
</form>
<canvas id="sample" width=300 height=300 style="background-color: #aaaaaa;"></canvas>
<br><br>Test Process<br><br>
<script>
document.getElementById('photo').addEventListener('change', handleUpload, false);
</script>
I had the same problem: worked on Chrome and Safari on my Mac, but did not work on Chrome or Safari on the iPhone 5s running iOS7. I solved by adding the data-caman-hidpi-disabled attribute to my canvas tag.
Try this:
<canvas id="sample" width=300 height=300 style="background-color: #aaaaaa;" data-caman-hidpi-disabled="true"></canvas>
According to the CamanJS website:
If a HiDPI display is detected, CamanJS will automatically switch to
the HiDPI version if available unless you force disable it with the
data-caman-hidpi-disabled attribute.
http://camanjs.com/guides/#BasicUsage
So i am getting to know Canvas element and i made simple Canvas based gallery to get me started.
I use setInterval to update src of my Image and than onLoad to draw it in canvas. Problem is that it works in Chrome but not in Safari or IE.
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var img = new Image();
img.src = "http://lorempixel.com/g/400/400";
img.onload = function() {
console.log('new image time');
context.drawImage(img, 0, 0);
};
setInterval(function(){
img.src = "http://lorempixel.com/g/400/400";
}, 4000);`
I made a fiddle: http://jsfiddle.net/lukaMis/T92TW/3/
So why doesn't setInterval run in Safari?
So
I found out it was catching of the browser problem. Browser catche request for img.src and it did not work. If if append timestamp to request it works:
_time = Date.now();
img.src = "http://lorempixel.com/g/400/400" + "?" + _time;
fiddle: http://jsfiddle.net/T92TW/5
Luka