I'm trying to create a small 2D game in Javascript/Canvas which consists of several animated sprites. I'd like to cut down on the number of HTTP requests, so I combined each frame of animation (32px by 32px) into one image per sprite (say, 192px by 128px). Is there any way I can copy and crop these images clientside back into several smaller images? It would vastly simplify my rendering code and help reduce loading time due to network latency.
The HTML5 Canvas API provides a method called drawImage which allows you to crop the input image.
context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
For more information see the spec (that image is taken directly from the spec):
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#images
Have a look at Pixastic, specifically http://www.pixastic.com/lib/docs/actions/crop.
Just load the image in an img tag with style attribute display set to hidden. Then crop the image on an off screen canvas, then write that off screen canvas to your main canvas as required.
If you don't want to use canvas or 3rd party library, you could add the image to a div (with "overflow: hidden") of the size of the cropped version, and giving the image negative left and top margins.
Each one will carry the whole image around, but will just display a portion of it, which may -- or may not -- impact performance. I believe you may have to give the div element a position:relative as well to make IE happy.
Alternatively you could assign the image as a background of the div, and specify the backgroundPosition. I seem to remember this didn't work for something I did once, not sure why. (I think it had to do with opacity)
Related
I am working with fTelnet.js - I have gotten down to the this_Font.GetChar() code and have found all characters are from a Font Sprite, it getItemData(....) changes the color where The pixel is 0x80 and colors it foreground [r][g][b][alpha], or colors it background [r][g][b][alpha].
Since Unicode goes outside what is in its 40+ fonts - I need to cheat and .createElement("div"), .innerHTML = "\u#####"; then somehow take that as ImageData so I can patch the above logic and introduce unicode support to fTelnet's canvas routine.
Does anyone know what command(s) I am needed to do this? e.g. I have spent hours trying to resolve this via Google, HTML5 Context docs, without success... mainly not knowing what I am searching for ;-)
or as I re-read this... maybe a hidden canvas, do the ctx.strokeText("\u#####", 25, 50); and then copy from that CTX as a IMAGEDATA to the displayed? (what command would I look up then?)... I normally do not dabble in 2D/3D graphics world (obviously)...
Regards,
Generally, rendering HTML to canvas is not possible - and that seems to be by design (it would make issues like tainting much harder to navigate).
But stamping one canvas on top of another is simple - you can just use the standard #drawImage call, same as with any other image you would draw on canvas.
Actually, if you look at the API documentation and click through the definitions you will see that you can use drawImage to "stamp" any instance of svg or html image, a bitmap, offscreen canvas, video or audio tags.
I love the circular profile pictures, but I hate that you cant edit them. Say for example you dont want the circle in the middle and the standard size, but you want it smaller or something.
Explanation with pictures:
The 4 images, from bottom to top: input, image editor, moving circle, output
Now, I want that you put a normal image in and that there will be a black overlay with some kind of opacity. In the middle you'll have a transparent circle so you can select the part you want in the circle. Then you can press save and there will be a .png file made.
I was thinking of doing this with jQuery watermarks, but I couldn't figure it out. Anyone got a idea?
There are a couple of methods:
You can use CSS2/3 - with corner-radius (for newer browsers) or even just an overlay image, image can be cropped, and background can be scaled/moved via CSS background-position and background-size accordingly. To save the image, you'll need a minimalistic PHP script do do the same operation server-side (given the parameters) and output the image to user.
You can also use HTML5 canvas - specification involves a handy clip method (which is straightforward - limits drawn imagery to current path), and you can obtain the image data via toDataURL method of canvas element as long as image is uploaded to the same server (or cross-domain rules are done right). A minimal search on saving files from JS+HTML5 should further assist.
Sample jsfiddle - http://jsfiddle.net/u2A7t/
In general final quality is pretty decent unless there are some very subtle details in the image, like hair for example. Then downsized image results to an over sharped version of itself. What is the default algoritm used by canvas for image resizing?
Is there a way to achieve a better result?
According to test results and scattered information around the web, currently canvas uses Nearest Member. Although specs do not force any specific algorithm. There was a talk in Mozilla about switching to Bilinear instead, but it seems that it wasn't yet implemented in browser.
You generally just use drawImage to resize an image on the canvas. Here is an example from Mozilla:
// Width and height is the image's size on the target canvas.
drawImage(image, x, y, width, height)
For more examples, see here; in particular the "Slicing" section.
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 to take an image on a webpage, and then use javascript (or whatever would be best suited) to dynamically 'pixelate' it (e.g. into 20px squares). Then, as the user scrolls down the page, I need the image to gradually increase in resolution, till it is no longer pixelated.
Any ideas how I could go about doing this? I realise I could use php to resize an image and several times and just switch out the image, but that would require loading several extra images. Also, I know I could probably do the effect with flash & pixelbender, but I want to achieve it within the limitations of HTML5, CSS & Javascript if possible.
Appreciate any thoughts!
Update: Something like this, but with Javascript instead of Flash? http://www.reflektions.com/miniml/template_permalink.asp?id=390
You could render the picture in a hidden <canvas> element. Then use a derivation of the technique described here http://dev.opera.com/articles/view/html-5-canvas-the-basics/#pixelbasedmanipulation . To create a pixelated version of the image in a second <canvas> element using ever decreasing fillRect's. This way you even buffer the orginal image data.
edit: I would use 2 <canvas> elements so that you only have to fetch and draw the original image once. Perhaps you could buffer/cache this image in the same <canvas> element but by drawing it outside of the view port i am not sure if this is possible though.
I would use a calculation where you get the width in pixels divided by the square width and then the height divided by the square height. This would give you the lower resolution your looking for.
Then you can find a way to change the resolution to the result or grab the color of every pixel at position (height and width)/2 of the square your looking for. Then generate them into div tags or table with the appropriate color and size eventually resulting in the image its self.
I have a probably faster idea where you can have multiple versions of the image and change their z-index or their visibility as you scroll. Basically each image would have the different resolutions. If you have to do that to many images then this solution wont be as efficient as there would be lots of image editing but you can always do a batch edit.
Let me see If I can think of more ideas then I will edit.
Have a look at http://close-pixelate.desandro.com/
Explanation here: https://stackoverflow.com/a/8372981/22470
Not in a portable way.
That might be doable in Flash. Firefox JS extensions allow it to read images as JS arrays, Base64 strings etc. You might experiment with "1 DIV=1 pixel" hack, but it's hard to get any reasonable size of the image at any reasonable speed. If you feel really hyper, you could try creating base64-encoded images on the fly using the data: URI... many ways but none good...