Canvas drawImage using data URL - javascript

I'll start with the script:
function saveInstance() {
_savedInstance = document.getElementById('canvasID').toDataURL();
}
function restoreInstance() {
ctx.drawImage(_savedInstance,0,0);
}
The purpose is to save an instance of the canvas and re-apply it later [Similar to how ctx.save() saves the style and transformations].
However, I got the error that says incompatible types (Uncaught Error: TYPE_MISMATCH_ERR: DOM Exception 17). Is there any canvas method that will allow me to use the data URL string to re-draw the instance?
**If there's a better way to implement this save/restore idea I have, that'd also be much appreciated.
-Firstmate

Yes, you can create an image element with its source as _savedInstance and then draw it to the canvas.
var img = new Image();
img.src = _savedInstance;
ctx.drawImage(img,0,0);

Related

Suggestions for efficient methods to hold HTML Canvas Image Data in memory?

I'm currently in the process of writing a point and click adventure game using TypeScript and Electron (outside of work FWIW). Now that I have the basic structure with some user input and graphics routines up and running, I've turned my attention to optimising what I have so I can leave it in the background and move on to the next stage in the process.
Right now I merely create a new Image() object with its "src" attribute set to my desired PNG, and hold the resulting HTMLImageElement in memory. I then draw the element to the canvas using drawImage on every frame.
Throwing PNGs to the canvas every frame feels wrong and inneficient. What would be the best way to hold image data in memory to draw it to the Canvas as efficiently as possible?
Right now, TS classes that implement my IDrawable interface look like this.
private Sprite: HTMLImageElement;
public GetImage()
{
return this.Sprite;
}
public LoadImage(src: string)
{
var image = new Image();
image.src = src;
this.Sprite = image;
}

Does THREE have a utility for loading canvases in an async manner?

I have a canvas with some pictures and I would like to load it onto a texture much like an image with ImageUtils. As you know canvas has no 'onfinished' rendering callback so I am at the mercy of THREE here. I have come across this but this seems to be tightly coupled with AJAX.
You can read the image from the canvas as a data url:
var canvas = document.getElementById("canvas");
var dataURL = canvas.toDataURL();
After you execute drawImage on the canvas, the image data is already going to be inside there.
These data urls then can be used as textures in Three.js.
var texture = THREE.ImageUtils.loadTexture(dataURL);
Update
You could also try this for debugging:
var texture = THREE.ImageUtils.loadTexture(dataURL, undefined, function(texture){
// Handler for onLoad, this returns the img
console.log(texture);
},
function(event){
// Handler for onError, it returns the error event
console.log(event);
});

KineticJS: How to convert a Stage into a HTML5 Canvas Element?

I have a KineticJS stage with a lot of layers.
I found this post: How to copy a kineticjs stage to another canvas
It says that I get a canvas element from a layer as
var canvasElement = layer.getCanvas().getElement();
Is it also possible to export a stage into a canvas?
In your use case you can do this:
In hard way you can create custom canvas element (or Kinetic.Layer), then conver Stage to Image, draw the image to canvas (layer) then pass it to plugin.
But this way should also work. I just saw plugin source. It is very simple (js part). I edited it:
stage.toDataURL({
callback : function(data) {
var imageData = data.replace(/data:image\/png;base64,/,'');
return cordova.exec(function() {
// done callback
}, function() {
// fail callback
}, "Canvas2ImagePlugin","saveImageDataToLibrary",[imageData])
}
});

Save Canvas between pageloads

Ive been trying to make the canvas save between page refreshes using html5 local storage, but the canvas always gets back to blank when i refresh the page.
HTML
<canvas onload="loadCanvas()" onClick="canvas(event)" id="myCanvas" width="400" height="400">
Your browser does not support the canvas element
</canvas>
Javascript:
function saveCanvas() {
var c = document.getElementById("myCanvas"),
ctx = c.toDataURL();
if (typeof (localStorage) !== "undefined") {
localStorage.setItem('myCanvas', ctx);
} else {
document.getElementById("save").innerHTML.dataURL = "Local Storage not supported";
}
}
function loadCanvas() {
var image = localStorage.getItem('myCanvas');
document.getElementById('myCanvas').src = image;
}
saveCanvas function gets called when something has been drawed in the canvas
Anyone knows what the problem is?
It has been solved, onLoad did not work in canvas
localStorage can only save so much, ie. in most browsers 5 mb and in others less.
Another caveat is that each char stored takes 2 bytes due to unicoding so the storage is in reality only half of this in the practical sense. There is no guarantee about size as this is not defined by the standard - 5 mb is only a suggestion so browsers can use any size.
You are getting the image as a PNG as this is the default format of toDataURL(). If the produced data-uri is too large (which is likely here as base-64 adds 33% to the size + a small header) the save will truncate or fail depending on the browser.
This is most likely (as you don't state size of canvas or the resulting data-uri) why your canvas is blank when you try to reload the data-uri as it would be invalid.
You can try to save as JPEG instead:
dataUri = c.toDataURL('image/jpeg', 0.5); /// 0.5 is quality, higher is better
If this does not work then you will need to look into other local storage mechanisms such as Indexed DB (where you can request a storage quota) or File API (but this is only supported in Chrome at this moment). There is also the deprecated Web SQL which will be around for still a while.
Update
Also try to move your onload from canvas element to window:
window.onload = function() {
var image = localStorage.getItem('myCanvas');
document.getElementById('myCanvas').src = image;
}
Note: you cannot set a src on a canvas element (as the ID from your code here suggest as well as your example code show). You need an image element for that. When you set a src on an image you also need to use the onload handler on the image, so an example could be:
window.onload = function() {
var img = new Image;
img.onload = function() {
var ctx = document.getElementById('myCanvas').getContext('2d');
ctx.drawImage(img, 0, 0);
/// call next step here...
}
img.src = localStorage.getItem('myCanvas');
}
Usually I suggest (and others did too in this thread) people store their drawings as points and shape types in an array as objects which then is serialized to a string which you instead store in localStorage. It involves a little bit more code in the render stage (which you need anyways to update canvas when it is blanked for some reason) but is worth it.

Graphics BitMapFill TypeError

I'm working with the easeljs javascript to make a sort of game.
I'm using this example: http://www.createjs.com/#!/EaselJS/demos/game
As you can see there are spacerocks. This are graphics objects:
this.graphics.beginStroke("#FFFFFF");
I would like to fill the background with an image like this:
var bitmap = new createjs.Bitmap("http://nielsvroman.be/twitter/root/easeljs/image.png");
this.graphics.beginBitmapFill(bitmap, "no-repeat");
But I always get this error:
Uncaught TypeError: Type error
Does anybody know what I'm doing wrong?
Use a reference to an HTML Image, and not a Bitmap instance.
var image = new Image();
image.srce = "http://nielsvroman.be/twitter/root/easeljs/image.png";
this.graphics.beginBitmapFill(image, "no-repeat");
Note that you have to ensure the image is loaded, otherwise it may not show up on the first stage update. You can either tick the stage, or listen for image onload, and refresh the stage then.
image.onload = function() {
stage.update();
}

Categories