Stop canvas flicker on re-render - html

I have written a jQuery plugin that will render four polygons onto a canvas and fill them with an image.
When you mouse over a polygon it is moved to a separate top layer and re-rendered so it expands and then contracts if you mouse out.
Is there any way to do this so that it doesn't flicker?
I've had a look a this question but don't quite understand what the accepted answer is doing (I know it draws the image on a seperate layer but I don't know how it checks if this has finished rendering before using it) or how to include it in my jsfiddle code

As it turns out it was because I was making a new image object everytime I made the drawing:
var imageObj = new Image();
imageObj.src = polyArray[4];
imageObj.onload = function () {
poly.setFillPatternImage(imageObj);
stage.draw();
}
I changed this so that these objects were created and cached into an array and then re-used. This enabled the re-rendering to run a lot faster and removed the flickering:
http://jsfiddle.net/peteng/KAkvX/10/

Related

Flash var Loader issue - animation changing

So, I've use a loader action script for a few banners I've been working on, and usually things go relatively smoothly (for Flash). However, the animation changes once I guide the image to the code. Has this happened to any one else? Below is the code I am using:
var imageLoader:Loader = new Loader();
var image:URLRequest = new URLRequest("http://972b6ac7e316515e1890-2848ccf658e0edc35f614dd3380d9fcb.r27.cf2.rackcdn.com/Background_othersizes.png");
imageLoader.load(image);
addChild (imageLoader);
I assume you have created animation in the Flash IDE with static image (linked from the library), and now you try to add image in runtime. Loading of the image is asynchronous process, so I would recommend account it in your animation and logic.
Also place in your MovieClip where image will be loaded, transparent shape as a background, of the same size as image, so environment will be aware of display object size, and all your transformations over MovieClip will be accounted accordingly. Also check placement and scaling of the image.

How to cache a whole layer right before dragstart and revert it back on dragend?

I'm currently trying to speed my web app for mobile devices a little bit up, but now I'm stuck at the most important part - caching. How is it possible to cache a entire layer right before the user starts to drag it and revert it back to usable Kinetic.Nodes when the drag-action has stopped?
At the moment I start caching on
stage.on('mousedown touchstart', function(){ // CACHING})
but the problem here is, that the user has to perform a second mousedown touchstart event to "grab" the cached image, which, of course, starts a new caching.
In this case my questions would be:
How can I pass the mousedown touchstart event to the cached image,
so the user can drag it with one fluent movement?
How can I speed up caching? (It takes 1-2 seconds for the cached image to appear. Is it useful to cache it in a setInterval after every, lets say 4 secs, and use this precached image or causes that a too high performance drain?)
I highly appreciate any kind of suggestions regarding my problem or further tips&tricks to speed up things.
Based on this statement:
stage.on('mousedown touchstart', function(){ // CACHING})
I'm assuming that on mousedown touchstart you call layer.toImage() or stage.toImage() and you want to drag the new image on that one click/tap.
You can invoke the drag event on the new generated image by using the .startDrag() function: Kinetic.Shape#startDrag
You can then invoke .stopDrag() on mouseup touchend to stop the drag. Kinetic.Shape#stopDrag
Something like:
var image, ox, oy;
stage.on('mousedown touchstart', function(){
// CACHING
stage.toImage({
width: stage.getWidth(),
height: stage.getHeight(),
callback: function(img) {
var image = new Kinetic.Image({
image: img,
draggable: true
});
ox = image.getX();
oy = image.getY();
image.startDrag();
}
});
});
stage.on('mouseup touchend', function(){
image.stopDrag();
//Calculate dx, dy to update nodes.
var newX = image.getX();
var newY = image.getY();
var dx = newX-ox;
var dy = newY-oy;
var children = layer.getChildren();
for (var i=0; i<children.length; i++) {
children.setX(children.getX()+dx);
children.setY(children.getY()+dy);
}
image.hide(); //or remove() or destroy()
layer.draw();
});
Note you need to update your original nodes after dragging the cached layer.
Another Note I haven't tested the code but I believe you could do something along the lines of what I've got up there.
Small UPDATE: You also should probably hide() the original layer while dragging the cached layer image! :) And then show() it again when you hide the cached image layer.
Honestly I'm not sure how you would speed up that cache time unless you can predict when the user needs to click/tap the stage to move. I think your suggestion would cost more performance than it would save.
I'm guessing that the desktop caches the image faster than on your mobile? It might fall into just being a limitation of KineticJS performance on Mobile vs Desktop...
UPDATE
Okay, I have an idea for #2, it's not exactly a fix but it might work better for you.
Separate your stage mousedown event with your touchstart event. mousedown will be the same but touchstart we want to handle differently.
On stage touchstart we want to drag the entire stage like normal, but meanwhile run the code for the original mousedown to cache the layer.
When the cached image finishes loading (takes 1-2 seconds you say), use .stopDrag() on the original stage and hide it. At this moment you want to store the current x and y values of the stage, so that you can still calculate dx,dy. Then immediately call .startDrag() on the new cached image and continue on like we did for mousedown.
How to know when the cached image finishes loading? I think that's what the toImage() callback function is for. If not, than hopefully a javascript onload event will work to determine when the image finishes generating.
The end result will be that you'll get your slow choppy drag on the stage for touch events UNTIL the image is cached. Then we flip the switch and stop dragging the stage, start dragging the cached image, and then revert/update the stage on touchend.
Hope that works as a semi-solution to your problem...
ANOTHER UPDATE
Okay here's another idea that actually might help your performance!
If your stage isn't modifying nodes very often, you can pre-cache the stage image so that it's already generated, and .hide() it. Then when you need to drag it, you just need to set the x,y of the cached image to match the stage's current x,y and then .show() the cached image. This will eliminate the time needed to wait/load the cached image when you first start dragging.
If you do happen to add a node or move a node or anything, after that cache the image. Hopefully this is manageable as we don't want to cache the image too often (drains performance). Again the cached image will be ready for your stage.drag event beforehand.
The goal is to have the stage cached before you do mousedown touchstart and start dragging. Hopefully this helps.

html5 canvas animation. moving an images gives flickering or a trail

I've seen other posts about this but I can't find anything to help me out.
I'm drawing an image on the canvas which moves, when it moves it leaves a trail of itself behind which hasn't been cleared. If I draw this image on top of another I get no trail but the image on top flickers. I don't think clearRect will work for me.
Can I save the canvas state between the image animation? Or should I be using a second canvas?
I'm not quite sure how to proceed, any advice would be great
* added examples - jsfiddle.net/zE67k/2 with an image and flicker. jsfiddle.net/zE67k/3 without an image and trail. this is just an example, I'm trying to achieve this with a background image to the canvas also.
* I also tried placing one canvas on top of another and I still get the flicker, I think the problem is where I place the clearRect. It does work if I put the clearRect just before the eye is drawn, but the way this code draws and updates the eyes does so one at a time, therefore the previous eye is cleared leaving only one. I'm trying it from this tutorial http://astronautz.com/wordpress/html5-eyes-that-follow-the-mouse/
You should save the clean canvas before drawing the other image ontop and restore that saved clean state before drawing the moved image again. You can use an additional canvas to save a clean state:
// create clean buffer
var buffer = document.createElement('canvas'),
canvas = document.getElementById('myCanvas');
buffer.width = canvas.width;
buffer.height = canvas.height;
// draw "background"/clean state to canvas
drawBackground(canvas);
// save clean state
buffer.getContext('2d').drawImage(canvas);
Then whenver you want to draw / move your other image/item simply restore the clean state:
canvas.getContext('2d').drawImage(buffer);
drawObject(canvas, x, y, w, h);

Multiple clicking regions on HTML5 canvas?

I'm messing around with HTML5 canvas and clipping. I am wondering how I can get the user to click on the canvas, have it clip a circle, and then repeat. So essentially, the user can click multiple times and there will be multiple clips.
I tried a couple solutions that were slightly similar to what I want but it isn't working.
Here is the clipping code:
context.save();
context.beginPath();
context.arc(mouseX,mouseY,50,50,Math.PI*2,true);
context.globalCompositeOperation = 'destination-out';
context.clip();
context.closePath();
var img = new Image();
img.src = canvasSnowflake.toDataURL();
context.drawImage(canvasSnowflake, 0, 0);
context.restore();
you can view the entire thing in action here: http://jsfiddle.net/cnbishop/8FzuB/. right now you can click one time and the clip works, but you can get a new clip if you click on the canvas again. Is this even possible?
Everytime the user clips you'll need to save this action somehow in JS. Next time the user clicks, you retrieve the past clipping, apply it and then apply the new clip action.
Basically, you need to reapply all the clipping actions in the history in the same order as they were executed as Canvas is unable to "remember" its previous rendering.
Did I interpret your question correctly?

Clearing canvas causes the old content to re-appear on the next draw

I have a clear button which seems to work..but actually its not. When I click back on the canvas I can see the drawing.
There is no problem in the way you are clearing the canvas, the problem lies in your logic.
Everytime you click or move the mouse the addClick method is called, which populates the arrays clickX, clickY and clickDrag with the coordinates; and then the redraw method is called which plots the points on the canvas.
So when you clear the canvas you are failing to reset these arrays, so when the redraw method is called again (after clearing the canvas), the old points get plotted too.
So try emptying the arrays clickX, clickY and clickDrag as shown below, when you clear your canvas; so that the old points are not considered when you start fresh.
clickX = [];
clickY = [];
clickDrag = [];