Is it possible to create an application using Kinetic.js where you create a shape, then scale it as you move the mouse around? I couldn't find anything in the Kinetic APIs, so I am mixing in "raw" JQuery. In particular, I use $("canvas").last().mousemove function, but it turns out this is actually very slow.
Here is the JSFiddle.
Any tips on making it faster?
I don't think the Kinetic.js has support for layer.on("mousemove", fn), because it seems to only apply to shapes.
yes. You would do something like this:
$('#container').on('mousemove', function(evt) {
shape.setScale(someValue);
layer.batchDraw();
});
In other words, attach a mousemove listener to the container div element (the one you pass into the Kinetic stage). set the shape scale with the setScale() method. Use batchDraw() instead of draw() so that the draw operation hooks into the KineticJS animation engine for much better performance. Otherwise, if you use draw(), you'll be redrawing the entire layer each time a mousemove event is detected, which could be hundreds of thousands of times per second depending on the browser
Related
I have a webgl canvas. It is being continuously updated (simulation).
Now I want to freeze the current content of the canvas. I am continuously getting updates for the simulation which I need to keep feeding to the visualizer. So my idea of achieving this is to clone the exact state of the current webgl canvas on to a new one, and hide the current one, which continues to get updated. Then I can remove the frozen one and the live simulation is being shown again.
I haven't been able to achieve this, and examples I've found on the web like this one:Any way to clone HTML5 canvas element with its content?
only apply to 2D canvases.
Google search didn't help much either.
This one:
how to copy another canvas data on the canvas with getContex('webgl')?
seemed promising but I haven't been able to figure out how to apply it.
Cloning the canvas appear to me to be an heavy and weird solution.
The simplest way to achieve what you want to do is to prevent the frame buffer to be presented (swapped, then cleared) to HTML canvas. Do do so, you simply have to avoid calling any gl.clear, gl.drawArrays or gl.drawElements during your loop.
For example suppose you have two functions, one running your simulation, the other your GL draw:
function simulate() {
// update simulation here
}
function draw() {
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
// do drawing stuff here
gl.drawArrays(gl.TRIANGLES, 0, 12345);
// etc...
}
From this point, if you want to "freeze" the canvas content, you simply have to stop calling the "draw" function within your global loop. For example:
function loop() {
simulate();
if(!freeze) draw();
requestAnimationFrame(loop);
}
You may uses other methods to achieve the same effect. For example, you can draw your scene to a texture, then draw the texture on the canvas. By this way, you also can control when the texture is cleared and drawn again, while it still rendered in the canvas.
However, to implements the render-to-texture method, you will have some more heavy modification to done in your code: you'll need an additionnal shader to draw the texture on screen, and take some time to play with frameBuffer and renderBuffer objects.
I am making a game in AS3 for a school project (using the AIR api). I have about a year's worth of experience in AS3, so i would say i'm proficient but not an expert. Anyway, i have never attempted to do sprite animations in AS3 and i'm not quite sure how to approach it.
If i create a list of bitmaps and call addChild() and removeChild() to display each frame of the animation, it would affect the framerate as these functions are not very efficient (i have tried this before and it tanked my framerate if i had too many animations going at once). I have also tried creating a list of BitmapData objects, adding a bitmap to the display list, and then pointing it to a different BitmapData each frame, but this does not seem to work at all.
So what is the best way to do this? In XNA, for example, i would create a sprite class that draws to the screen using a sprite batch, then i would create a list of sprite objects and cycle through them to create the animation. Is there any way to achieve a similar result in actionscript?
First (simple) method: you can just use multi-frame MovieClip for animation. Put an image in each frame, put a MovieClip on the stage and that's all. You can control this animation using play(), stop(), gotoAndPlay(), gotoAndStop(). It will work without much problems for a generic platform game (I did that myself long ago).
Second (advanced) method: use bitmap blitting. For each animation, create a bitmap image that holds each frame of the animation. Use this image as a source for copying pixels into your current animated object. You just need to copy a particular rectangle area inside a source bitmap that corresponds to the current frame.
The actual blitting happens here
destinationBitmapData.copyPixels(sourceBitmapData, areaRectangle, destinationPoint);
Where destinationBitmapData is your "canvas" that you're blitting to; sourceBitmapData is the source image holding all animation frames; areaRectangle is the Rectangle inside the source image defining which area to copy; destinationPoint is left-top coordinate of the copy area in your canvas.
The destination canvas can be just one small object (like your game character that is moving around) or the entire game screen with all objects. I.e. instead of blitting and adding each object separately, you can just have one big canvas and blit any necessary parts directly to it.
That said, there is already a number of various ready-made engines that use blitting and even advanced techniques like 3D acceleration for 2D sprites.
One of them is Starling.
I know there is this question which suggests looping through all canvas elements on each mouse move.
However, is there a more effective way than looping through all the elements?
I have quite a few elements on the canvas and looping through them all on each mouse move could be very, very slow.
Yes, you have to loop through all of your elements.
That's how nearly all hit testing/object picking works.
Now there are a lot of optimizations you can do, like making sure that the mouse coordinate is in the rectangular bounds of the object before you test its real bounds (unless they're all rectangles, which would make everything convenient and fast, even if there are 10,000 objects). If you have a million objects, you could also split up their location into quadrants, or otherwise add a layer of isolation.
But at the end of the day you need to loop through every relevant object and ask if its bounds intersect the mouse point. There's no way of getting around that. It ought to be fast, and if you've implemented something that is very slow then you should post it so we can take a look and give you pointers.
If you need to see a live example I made a simple tutorial on picking and moving shapes in a canvas exactly for explaining situations like this.
Looping through 10000 of elements is still no effort in javascript.
However you might consider looping throught them with some interval not on every mousemove.
var mouseX, mouseY;
$(document).on("mousemove", function(e) {
mouseX = e.pageX;
mouseY = e.pageY;
/* dont do any probing there */
});
setInterval(function() {
checkCollision();
}, 25);
I'm working on a game that allows players to click on a card and drag it across the screen in any random direction. There are a total of 64 100x80 overlapping cards on a 800x800 canvas at any one time and each one is a procedural draw. As some of you probably suspect, canvas doesn't like redrawing that entire canvas for every move. To work around this, I'm utilizing a buffer canvas to draw the card and then attempting to paint that buffer canvas to the main canvas using drawImage(). To ensure there is no drawing buildup, I clear the region of the canvas associated with where I plan to drawImage() using a clearRect().
The problem I'm experiencing is that because the (x,y) coordinates used for the clearRect() and drawImage() are coming from the location of the mouse, if the user moves too fast, the coordinates will differ from the time drawImage() was last executed to the time clearRect() is called during the next draw sequence. The result is residual draw from the last sequence - proportionate to how fast the card is being dragged.
I tried maintaining the (x,y) coordinates from the drawImage() and using those (instead of the current mouse location) for the clearRect() in the next sequence. However, now instead of residual draw being shown, residual we have residual clear (erase).
Thoughts on how I can address this?
NOTE: My animation rate is handled using RequestAnimationFrame and not SetInterval().
Assuming your canvas is static during the drag drop operation, a pretty easy way to get a good increase in performance would be to just cache the rendering.
In other words, when a drag drop operation begins, save the current canvas into another one. Stop all rendering except for the one involved with dragging the card. Now, whenever you need to repaint, simply repaint from your copy-canvas. Since you're basically just copying from one to another, it should be pretty fast.
On each processing cycle, you would take the current position of the dragged card, fill that with data from the copy, then redraw the dragged card in the new position.
Other approaches you could try would be to use some kind of a placeholder for the drag. For example, consider using a same-sized DIV which you display while dragging. This should have the benefit of not requiring to touch the canvas while dragging and thus also run a better performance for it.
Im looking for an easy to use method of assigning drag behavior to multiple objects (images, shapes etc) in canvas. Does anyone have a good way or know of any libraries for dragging objects around? Thanks
Creating your own mouse events takes a little work - ideally you should either create or use some kind of mini-library. I'm thinking of creating something like this in the near future. Anyway, I created a drag and drop demo on jsFiddle showing how to drag images - you can view it here.
You can create draggable images like this:
var myImage = new DragImage(sourcePath, x, y);
Let me know if you have any questions about this. Hope it helps.
EDIT
There was a bug when dragging multiple images. Here is a new version.
Another thing you might want to check out is easeljs it sort of in the style of AS3... mouseEvents dragging etc...
The HTML Canvas—unlike SVG or HTML—uses a non-retained (or immediate) graphics API. This means that when you draw something (like an image) to the canvas no knowledge of that thing remains. The only thing left is pixels on the canvas, blended with all the previous pixels. You can't really drag a subset of pixels; for one thing, the pixels that were 'under' them are gone. What you would have to do is:
Track the mousedown event and see if it's in the 'right' location for dragging. (You'll have to keep track of what images/objects are where and perform mouse hit detection.)
As the user drags the mouse, redraw the entire canvas from scratch, drawing the image in a new location each time based on the offset between the current mouse location and the initial mousedown location.
Some alternatives that I might suggest:
SVG
Pure HTML
Multiple layered canvases, and drag one transparent canvas over another.
The HTML Canvas is good for a lot of things. User interaction with "elements" that appear to be distinct (but are not) is not one of those things.
Update: Here are some examples showing dragging on the canvas:
http://developer.yahoo.com/yui/examples/dragdrop/dd-region.html
http://www.redsquirrel.com/dave/work/interactivecanvas/
http://langexplr.blogspot.com/2008/11/using-canvas-html-element.html
None of these have created a separate library for tracking your shapes for you, however.
KineticJS is one such Javascript Library that u can use exclusively for animations
Heres the Link html5canvastutorials
Canvas and jCanvas
You're definitely gonna want to check out jCanvas. It's a super clean wrapper for Canvas, which kicks open a lot of doors without adding code complexity. It makes things like this a breeze.
For example, here's a little sandbox of something close to what you're after, with dragging and redrawing built right in:
Drawing an Arrow Between Two Elements.
I ventured down the road of doing everything with DIVs and jQuery but it always fell short on interactivity and quality.
Hope that helps others, like me.
JP
As you create new objects whether they are windows, cards, shapes or images to be draggable, you can store them in an array of "objects currently not selected". When you click on them or select them or start dragging them you can remove them from the array of "objects not selected". This way you can control what can move in the event of a particular mousedown event or mousemove event by checking if it isn't selected. If it is selected it will not be in the "not selected" array and you can move the mouse pointer over other shapes while dragging shapes without them becoming dragged.
Creating arrays of objects you would like to drag also helps with hierarchy. Canvas draws the pixels belonging to the foremost object last. So if the objects are in an array you simply switch their instance as in element in the array say from objectArray[20] to objectArray[4] as you iterate through the array and draw the objects stored in the array elements you can change whether other objects are seen on top or behind other objects.