I've seen this "The Scale of the Universe 2" and I just want to know if this can be done with javascript or jQuery or with HTML5 Canvas.
If you click an item (example the "Human") , an info will pop out beside it.
I searched for 3 days here if someone has a similar question. But I only saw Google Map like behavior where you can zoom in on the map cursor position.
Actually I want to make a "Timeline" like effect or, like the "Time Machine" Recovery on Mac OS X.
Fixed position of zoom. Not like a google map zoom, that you can pan and zoom anywhere.
Can I put (example "The human") images and text on a div?
Are there available articles/tutorials about this?
Options:
Javascript
jQuery
HTML5 Canvas and CSS3 Transform and scrolling it to Z-axis so you can zoom in/out.
Flash/Flex (Well I don't want to use lots of resources on CPU because I need it in a large resolution or in full screen.
It is possible to implement an infinite zoom in HTML canvas, this is the source code of a proof of concept that I implemented and here you can test it live.
It is actually quite tricky to implement, and most probably you'll need to use big decimals.
The approach I followed uses the same coordinate space as d3-zoom. Basically, you have three coordinates, x, y and k. K is the zoom. If k is 2 it means that you have doubled everything.
Now, if you want to do infinite zoom, it is very easy to reach k = 64, but that is already outside of float64 precision and you'll have a lot of artifacts, where translating in the image is not smooth, or you don't zoom in where you want.
One way to avoid those artifacts is to use coordinates that have infinite length, for example BigIntegers. To make my implementation easy and compatible with d3-zoom, I used big decimals instead, but I had to implement my own library of BigDecimals, basically infinite precission on the integer part and 32bits of precision on the decimal part. Of course, you also need to adapt the zooming library to support BigDecimals. Moreover, in the case of d3-zoom, a lot of calculations where done in the initial coordinate space (k=1) but division of floats will always have an error and it is also perceivable once you are deep enough. To avoid that you need to do all computations locally.
It might sound like a lot of hassle to insist on using the d3-zoom library, but zooming UX is actually tricky, specially if you combine that at different k, you'll need to consider scrolling, zooming on the phone, double tapping...
In case you want to use SVG transformations, then you'll need to fake it. You'll introduce nodes when they are barely visible, allow to scale them. However, most probably you'll also need to fake it when they are too big to avoid artifacts there.
There is no infinite zoom. However you can zoom in/out of an SVG image in HTML5 canvas.
SVG supports affine tranformation. You can set the required zoom/pan in the affine transform and show the relavant areas. The behavior/listener can be implemented in Javascript and the SVG can be rendered on HTML5 canvas.
As a starting point you can look at this example: http://www.html5canvastutorials.com/labs/html5-canvas-scaling-a-drawing-with-plus-and-minus-buttons/
This is totally doable in HTML5. Actually, any system able to display and zoom images should be able to. It's not one big image being zoomed, it's a big amount of images being zoomed (for instance the initial human is an image, which is scaled and moved out when you zoom in or out). The idea is splendid, but I don't really see any technical performance in it. As long as you correctly limit the number of images being resized and bitmapped, it should keep a decent FPS rate.
Related
I'm animating a sprite on a pixel grid. I have a few options, with pros and cons for each. I have a fair amount of javascript experience (six years), but none with this kind of thing. The problem is I don't know how expensive each option will be.
The sprite needs to render quite fast, and be inexpensive enough to have at least five running at the same time while running collision detection.
Ideally, I would like to use a grid of elements inside of a wrapper, rendering colour and alpha channels to each element from a multidimensional array.
The major pro here is that I can run pixel-by-pixel collision detection and click past the transparent parts of the sprite. With any image-based sprite, the onClick event will fire even if I click on a transparent pixel (I'll have to do a lot of work to pass clicks through transparent pixels, and it might be quite expensive).
The next option is to use css sprites. css-tricks.com/css-sprites/
This would be easy peasy, but as mentioned previously, onClicks won't pass through the transparent pixels. I can probably force it, but again, it may be expensive, and take a lot of time to impliment.
Another option is animated gifs, but they are huge, limited in the colour department, and hard to control animation-wise. I'd rather not go there.
And then there's the html5 canvas element, which I don't know very much about and would like to stay away from if at all possible. I don't know how any of my code would even work in relation to the canvas element and I doubt it would do what I want in the long-run.
So which is the best for performance? Would the first (and most preferable) be a viable option? Or have I missed something out?
With today's browsers you will be fine on desktop computers for building a sprite out of positioned pixel sub-elements (as long as they aren't too complicated or large), and just to be safe I'd limit yourself to about 10 active sprites. With Mobile things might get a bit slow and clunky, but considering you seem to be designing a game that requires precision "onclicks" I doubt that this will be a problem.
Your most flexible bet is to use HTML5 Canvas, as you have already worked out, but it will involve quite a bit more JavaScript coding. But this sytem will allow you to apply a number of effects to your sprites and will allow you to use pixel perfect detection by using getImageData (which allows you to read the exact pixel colour at any pixel offset).
getPixel from HTML Canvas?
If you wanted to avoid the techinical problems and challenges of having a full screen canvas system (which can be tricky), you can actually create as many smaller Canvas elements and move them around as your sprites (with the ease of HTML Elements).. Then all you have to do is design the code that draws your animation frames, and also tells if the mouse has hit or not hit the sprite using the aforementioned method (along with a click handler and some code to calculate where the user has clicked relative to your canvas elements position). Obviously, it would be best to do this in a generalised way so your code can be applied to all your sprites :)
To draw your images on the canvas you can use a spritesheet as you were mentioning in your question, and use the rather flexible drawImage() method which supports a slicing mode. This just needs to be tied up to a setInterval or requestAnimationFrame style game loop.
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images
http://www.playmycode.com/blog/2011/08/building-a-game-mainloop-in-javascript/
UPDATE - for those who wish to be very optimal
If you wish to take a more optimal route - which is a little bit more involved again - you can do the following. This method benefits if you have many sprites that are exactly the same with only a few (20 or 30) frames of animation:
Power your sprites by normal DIVs with a background image sprite sheet that you shift the background position of. This is the most optimal you can be, save having static images as sprites, because the browser does all the work.
for each sprite type draw your spritesheet on a hidden canvas element that is big enough to incorporate your whole spritesheet.
When a user clicks on one of your DIV sprites, take the background position as coordinates, invert them, and you should then know where on your canvas element (looked up by sprite's type) the pixel data resides.
Use the getPixelData method on your hidden canvas to work out if the user has clicked on the sprite or not.
The above means you only have one canvas element in use - per sprite type, the browser handles all the graphics for you and you get pixel perfect collisions with an onclick.
Hope the above makes sense?
How about splitting your image spirit into 30x30 cells and only have elements where the cell is opaque and leave a gap where the cell is transparent so that clicks fall through. You lose a bit of accuracy in where the cells can be clicked though.
I'm trying to visualize some data on an HTML canvas and I'm facing an issue similar to this one. That is, the size of my data doesn't exactly match the size of my canvas.
In one instance I'd like to plot a 1024 point signal on a canvas that's 100px wide. (E.g., an audio waveform.)
In another instance I'd like to show a 1024 by 5000 point matrix on a canvas that's 100 px high by by 500 px wide. (E.g., an audio spectrogram.)
In both cases, I'll need to resample my data so that it fits on the canvas. Does anyone know of a library/toolkit/function in Javascript that can do this?
** EDIT **
I'm aware that there are many techniques I could use here. One possibility is to simply discard or duplicate data points. This would do in a pinch, but discarding/duplication is known to produce results that tend to look "jagged" or "blocky" (see here and here). I'd prefer to use a slightly more sophisticated algorithm that outputs smoother images such as Lanczos, bilinear or bicubic resampling. Any of these would meet my needs.
My question isn't about which algorithm to use, though, it's about whether any of them have been implemented in open-source javascript libraries. Surprisingly, I haven't been able to find much in JS. Coding my own resampling function is obviously an option, but I wanted to check with the SO community first to make sure I wasn't re-inventing the wheel.
(This answer gives a code listing that's very close to what I want, except that it operates directly on the canvas objects rather than the data arrays, and it forces the aspect ratios of the input and output to be the same. If nothing else is available, I can definitely work with this, but I was hoping for a solution that's a bit more general and flexible, along the lines of Matlab's resample.)
use canvas scale
ctx.scale(xscale,yscale);
you can determine the scaling by calculating the rate between your canvas and the data
ctx.scale(canvas_x/data_x,canvas_y/data_y)
I'm investigating the possibility of producing a game using only HTML's canvas as the display media. To take an example task I need to do, I need to construct the game environment from a number of isometric tiles. Of course, working in 2D means they by necessity come in rectangular packages so there's a large overlap between tiles.
I'm old enough that the natural solution to this problem is to call BitBltMasked. Oh wait, no, an HTML canvas doesn't have something as simple and as pleasing as BitBlt. It seems that the only way to dump pixel data in to a canvas is either with drawImage() which has no useful drawing modes that ignore the alpha channel or to use ImageData objects that have the image data in an array.. to which every. access. is. bounds. checked. and. therefore. dog. slow.
OK, that's more of a rant than a question (things the W3C like tend to provoke that from me), but what I really want to know is how to draw fast to a canvas? I'm finding it very difficult to ditch the feeling that doing 100s of drawImages() a second where every draw respects the alpha channel is inherently sinful and likely to make my application perform like arse in many browsers. On the other hand, the only way to implement BitBlt proper relies heavily on a browser using a hotspot-like execution technique to make it run fast.
Is there any way to draw fast across every possible implementation, or do I just have to forget about performance?
This is a really interesting problem, and there's a few interesting things you can do to solve it.
First, you should know that drawImage can accept a Canvas, not just an image. The "sub-Canvas"es don't even need to be in the DOM. This means that you can do some compositing on one canvas, then draw it to another. This opens a whole world of optimization opportunities, especially in the context of isometric tiles.
Let's say you have an area that's 50 tiles long by 50 tiles wide (I'll say meters for the sake of my own sanity). You might divide the area into 10x10m chunks. Each chunk is represented by its own Canvas. To draw the full scene, you'd simply draw each of the chunks' Canvas objects to the main canvas that's shown to the user. If only four chunks (a 20x20m area), you would only perform four drawImage operations.
Of course, each of those individual chunks will need to render its own Canvas. On game ticks where nothing happens in the chunk, you simply don't do anything: the Canvas will remain unchanged and will be drawn as you'd expect. When something does change, you can do one of a few things depending on your game:
If your tiles extend into the third dimension (i.e.: you have a Z-axis), you can draw each "layer" of the chunk into its own Canvas and only update the layers that need to be updated. For example, if each chunk contains ten layers of depth, you'd have ten Canvas objects. If something on layer 6 was updated, you would only need to re-paint layer 6's Canvas (probably one drawImage per square meter, which would be 100), then perform one drawImage operation per layer in the chunk (ten) to re-draw the chunk's Canvas. Decreasing or increasing the chunk size may increase or decrease performance depending on the number of update you make to the environment in your game. Further optimizations can be made to eliminate drawImage calls for obscured tiles and the like.
If you don't have a third dimension, you can simply perform one drawImage per square meter of a chunk. If two chunks are updated, that's only 200 drawImage calls per tick (plus one call per chunk visible on the screen). If your game involves very few updates, decreasing the chunk size will decrease the number of calls even further.
You can perform updates to the chunks in their own game loop. If you're using requestAnimationFrame (as you should be), you only need to paint the chunk Canvas objects to the screen. Independently, you can perform game logic in a setTimeout loop or the like. Then, each chunk could be updated in its own tick between frames without affecting performance. This can also be done in a web worker using getImageData and putImageData to send the rendered chunk back to the main thread whenever it needs to be updated, though making this work seamlessly will take a good deal of effort.
The other option that you have is to use a library like pixi.js to render the scene using WebGL. Even for 2D, it will increase performance by decreasing the amount of work that the CPU needs to do and shifting that over to the GPU. I'd highly recommend checking it out.
I know that GameJS has blit operations, and I certainly assume any other html5 game libraries do as well (gameQuery, LimeJS, etc etc). I don't know if these packages have addressed the specific array-bounds-checking concern that you had, but in practice their samples seem to work plenty fast on all platforms.
You should not make assumptions about what speedups make sense. For example, the GameJS developer reports that he was going to implement dirty rectangle tracking but it turned out that modern browsers do this automatically---link.
For this reason and others, I suggest to get something working before thinking about the speed. Also, make use of drawing libraries, as the authors have presumably spent some time optimizing performance.
I have no personal knowledge about this, but you can look into the appMobi "direct canvas" HTML element which is allegedly a much faster version of normal canvas, link. I'm confused about whether this works in all browsers or just webkit browsers or just appMobi's own special browser.
Again, you should not make assumptions about what speedups make sense without a very deep knowledge of web browser internal processes. That webpage about "direct canvas" mentions a bunch of things that slow down canvas-drawing: "Reflowing text, mapping hot spots, creating indexes for reference links, on and on." Alpha-blending and array-bounds-checking are not mentioned as prominent causes of slowness!
Unfortunately, there's no way around the alpha composition overhead. Clipping may be one solution, but I doubt there would be much, if any, performance gain. Not to mention how complicated such a route would be to implement on irregular shapes.
When you have to draw the entire display, you're going to have to deal with the performance hit. Although afterwards, you have a whole screen's worth of pre-calculated alpha imagery and you can draw this image data at an offset in one drawImage call. Then, you would only have to individually draw the new tiles that are scrolled into view.
But still, the browser is having to redraw each pixel at a different location in the canvas. Which is quite expensive. It would be nice if there was a method for just scrolling pixels, but no luck there either.
One idea that comes to mind is that you could implement multiple canvases, translating each individual canvas instead of redrawing the pixels. This would allow the browser to decide how to redraw those pixels, in a more native way, at least in theory anyway. Then you could render the newly visible tiles on a new, or used/cached, canvas element. Positioning it to match up with the last screen render.
But that's just my two blits... I mean bits... duh, I mean cents :]
Morning,
Over the past few months I have been tinkering with the HTML5 Canvas API and have had quite a lot of fun doing so.
I've gradually created a number of small games purely for teaching myself the do's and don'ts of game development. I am at a point where I am able to carry out basic collision detection, i.e. collisions between circles and platforms (fairly simple for most out there but it felt like quite an achievement when you first get it working, and even better when you understand what is actually going on). I know pixel collision detection is not for every game purely because in many scenarios you can achieve good enough results using the methods discussed above and this method is obviously quite expensive on resources.
But I just had a brainwave (It is more than likely somebody else has thought of this and I am way down the field but I've googled it and found nothing)....so here goes....
Would it possible to use/harness the "globalCompositeOperation" feature of canvas. My initial thoughts were to set its method to "xor" and then check the all pixels on the canvas for transparency, if a pixel is found there must be a collision. Right? Obviously at this point you need to work out which objects the pixel in question is occupied by and how to react but you would have to do this for other other techniques.
Saying that is the canvas already doing this collision detection behind the scenes in order to work out when shapes are overlapping? Would it be possible to extend upon this?
Any ideas?
Gary
The canvas doesn't do this automatically (probably b/c it is still in its infancy). easeljs takes this approach for mouse enter/leave events, and it is extremely inefficient. I am using an algorithmic approach to determining bounds. I then use that to see if the mouse is inside or outside of the shape. In theory, to implement hit detection this way, all you have to do is take all the points of both shapes, and see if they are ever in the other shape. If you want to see some of my code, just let me know
However, I will say that, although your way is very inefficient, it is globally applicable to any shape.
I made a demo on codepen which does the collision detection using an off screen canvas with globalCompositeOperation set to xor as you mentioned. The code is short and simple, and should have OK performance with smallish "collision canvases".
http://codepen.io/sakri/pen/nIiBq
if you are using a Xor mode fullscreen ,the second step is to getImageData of the screen, which is a high cost step, and next step is to find out which objects were involved in the collision.
No need to benchmark : it will be too slow.
I'd suggest rather you use the 'classical' bounding box test, then a test on the inner BBOxes of objects, and only after you'd go for pixels, locally.
By inner bounding box, i mean a rectangle for which you're sure to be completely inside your object, the reddish part in this example :
So use this mixed strategy :
- do a test on the bounding boxes of your objects.
- if there's a collision in between 2 BBoxes, perform an inner bounding box test : we are sure there's a collision if the sprite's inner bboxes overlaps.
- then you keep the pixel-perfect test only for the really problematic cases, and you need only to draw both sprites on a temporary canvas that has the size of the bigger sprite. You'll be able to perform a much much faster getImageData. At this step, you know which objects are involved in the collision.
Notice that you can draw the sprites with a scale, on a smaller canvas, to get faster getImageData at the cost of a lower resolution.
Be sure to disable smoothing, and i think that already a 8X8 canvas should be enough (it depends on average sprite speed in fact. If your sprites are slow, increase the resolution).
That way the data is 8 X 8 X 4 = 256 bytes big and you can keep a good frame-rate.
Rq also that, when deciding how you compute the inner BBox, you can allow a given number of empty pixels to get into that inner BBox, trading accuracy for speed.
I'm finishing up a drawing application that uses OpenGL ES 2.0 (WebGL) and JS. Things work pretty well unless I draw with very quick movements. See the image below:
This loop was drawn with a smooth motion, but because JS was only able to get mouse readings at specific locations, the result is faceted. This happens to a certain degree in Photoshop if you have mouse smoothing turned off, though obviously much less because PS has the ability to poll at a much higher rate.
So, I would like to implement some mouse smoothing, but I'm concerned about making sure it's very efficient so that it doesn't bog down the actual pixel drawing operations. I was originally thinking about using the mouse locations that JS is able to grab to generate splines and interpolate between readings to give a smoother result. I'm not sure if this is the best approach, though. If it is, how do I make sure I sample the correct locations on the intermediate spline? Most of the spline equations I've found don't have uniformly-distributed values for t = [0, 1].
Any help/guidance/advice would be very appreciated. Thanks!
Catmull-Rom might be a good one to try, if you haven't already.
http://www.mvps.org/directx/articles/catmull/
I'd pick a minimum segment length and divide up segments that are over that into 1+segmentLength/minSegmentLength sub-segments.