HTML5 globalCompositeOperation vs clip - html

I have a large source image and I want to display a small section of it inside a circle, with leaving the part of the canvas outside of the circle transparent.
The Mozilla guide to Compositing with HTML5 covers two topics: globalCompositeOperation and clip. It looks like both of these will let me do what I want, so I'm wondering what the drawbacks are of each, and which I should use.
I could set globalCompositeOperation to source-atop (or source-in, but that seems buggy in WebKit). Then have the destination canvas be transparent with a black circle, and simply draw the source image over that. This will ensure that only the circle part will be filled in.
Or, I could draw a circular path and use clip to define a clipping region, then draw the source image over that, which should also ensure only the circle part will be filled in (in fact, Mozilla's page above even has an example of doing pretty much that with stars).
Will both of these techniques work as I say they will, or am I missing something?
If so, are there any major gotchas with either of these techniques which makes one clearly better than the other?
If not, which one has better performance in general?
I would (purely speculatively) imagine the globalCompositeOperation would have better performance, since it is applying the operation on a per-pixel level, whereas the clip operation needs to do polygon intersection. But that's just a hunch.

As of March, globalCompositeOperation did not work the same on all browsers.
Clip does... except the anti-aliasing, actually, which is sadly different per browser.
In my opinion the appropriate thing to do here is use clip. Using source-atop may work for your very specific situation, but it isn't very extensible as you described it. If you ever want to change any of it, like say have a background behind your circle, you'll run into trouble if you do it the globalComposite way.
And the tests are in: Clip is faster in every browser I tested, and massively faster in Firefox. See the results or try for yourself here

Related

Is drawing to the canvas optimized based on what's already there?

If I draw an image to the canvas and the pixels end up being mostly the same as what's already there, will this be faster than if I draw an image where all the pixels end up changing?
Unfortunately no, everything drawn to canvas is drawn using compositing (Porter-Duff) and blending rules regardless of what already is there before it (the same math is applied).
There is some form of dependency though as the existing content may influence the look on the final outcome of these operations, but not in a performance sense. Say various blending modes, global alpha, and of course compositing modes themselves etc.
The cost of checking what to draw and not would most likely outweight the cost of just drawing the content, and it would need to implement a somewhat complex mechanism to consider the various methods that can be used to draw - ie. not so useful for performance.
A browser vendor may chose to optimize for specific cases, but in general and regardless of existing content: everything passes through blending mode, composition and finally alpha blending with the background, at context level - this produces the bitmap used for the next step (or that we can extract as an image). Then something similar at element/DOM level so that the canvas and its content blends in with the rest of the page/DOM content, but where the alpha channel can be considered in a special way:
One exception in regards to performance, also in general, is when the browser need to composite and alpha blend the canvas element itself with the background (ie. everything behind the element). If the alpha channel is disabled for the canvas element, the browser can optimize this step which gives us a little more performance to draw from.
To disable the alpha channel for the 2D context you simply pass in the option:
var ctx = canvas.getContext("2d", {alpha: false});
The two actions will take exactly the same amount of time, because they are both doing the same action. The result of the pixels does not change the speed of how long it will take to execute the code :)
It doesn't matter if the pixels change or not, the pixels refresh either way.

Adobe Flash CC HTML5 Publishing Canvas Drawing Inaccuracy

I'll start with the pictures:
Comparison Of Different Publishing Methods From Flash CC
It seems like there is a huge difference between what's published by through Flash CC HTML5 with CreateJS and what's actually created on the program although they are exact copies (I'm not talking about the pose of the character)
The shapes making up the body parts are all triangles with a solid fill and no stroke.
However, in the HTML5 published versions it looks like all those shapes now have a thin transparent stroke around them in between each other.
Any explanation or official support is greatly appreciated!
UPDATE:
The accepted answer definitely improved some of the problem but unfortunately not enough.
Since it's a platform limitation, I decided to work around it by doubling up all the assets of every layer and minutely overlapping them as best as I can.
Here's a link of the work around being implemented if you wanted an update:
link
This is an unfortunate issue with Canvas. The SWF format actually draws lines with fills on both sides, which enables the SWF (and Flash/Animate IDE) to create seamless edges when drawing shapes with edges that line up. Canvas can not do that, so the antialiasing causes the effect you are seeing.
A possible approach would be to cache it at a larger size, and scale it down.
var bounds = character.nominalBounds; // Added by Flash export
character.cache(bounds.x, bounds.y, bounds.width, bounds.height, 2);
The last parameter is the cache scale factor (in this case it doubles the cache size). It will still draw at the expected scale though.
I made a quick sample to show the difference, and it does help. Note that caching is also a good way to get rid of aliasing on edges. You can download the sample here. Uses Adobe Animate 2016.
Plain shapes exported from Adobe Animate
Cached the shape container
Doubled the cache size
You also might want to consider dropping in a shape behind it that is closer to the color of the shapes, so if the edges show through, it is not the dark grey background.

Correct way to fill shape with image cropped from sprite

I am slightly confused about the "correct" way in KineticJS to fill a shape with partial images (crops) from a combined image file (sprite).
Seems like one can either use fillPatternImage with a defined offset, which seems to draw the complete image, albeit with the rest of the image invisible. I only got acceptable performance after I moved those shapes to an extra layer as my sprite is relatively large and the impact of not cropping correctly decreased the fps dramatically.
All alternatives that I have found use the attribute "fill" with another attribute "image" in it, but this seems to result in black background every time.
Using an Image-shape would help, but is rarely usable since my shapes are seldom rectangular.
Since the KineticJS-documentation does not mention specifying crop coordinates ("just" offset, w/o width and height), what is the absolute correct way to do it?
The absolute "absolute correct way" would depend on the platform and your particular code, but.
Have you looked at sprites? http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-sprite-tutorial/.
To mask simple animated sprites I'd use this in adition of plain javascript after each draw.
context.globalCompositeOperation = 'destination-in';
The performance of drawImage with composite operations is better than drawing shapes manually on webkit, at least.

How to undraw, hide, remove, or delete an image from an html canvas?

this.context.drawImage(myimage, 0, 0);
Putting the image on the canvas is pretty well covered all over the web.
But how do I remove it after it's there?
Canvas is an immediate drawing surface. This means that you execute a command on it (drawImage or fillRect) and it does that command, and it doesn't give a damn what has just done. There is no undoing of something.
You had a hard time searching for it because there's no such thing as "removing" for a Canvas. All it knows is that it has some pixels of some color from somewhere. It has no idea where.
To simplify a bit, there are generally two ways:
Clear the entire canvas, and draw everything all over again EXCEPT the one image you do not want drawn
Use two canvases, one that only has the image and one with all the other stuff. Clear this canvas with clearRect(0,0,width,height) and you're done.
You'll notice in 1. that you will probably have to start keeping track of the things that you draw on canvas if you want some of them selectively removed or repositioned. Instilling object persistence, or rather turning canvas from an immediate drawing surface to a retained drawing surface, is something that a lot of canvas libraries do. If you want to do it yourself, I've written a few tutorails to help people get started.
If you want to look into libraries, take a peek at easel.js. It's pretty learnable.
Option 1:
Draw a rectangle over it of the same color as the background.
Option 2 (works for non-trivial background, but slower):
Get the pixel data from the canvas before drawing the image, then redraw that pixel data to remove the image.
So I came up with a quick and easy way to clear my canvas. I just put my <canvas> tags in between <p> tags with an Id, then each time i needed my canvas cleared I just rerendered my <p> tags by changing the innerHTML, works like a charm.

Will avoid drawing half pixel in HTML5 canvas improve speed?

I am drawing a sprite (of a ball) on a canvas element. As the ball moves however, the x or y position of the ball may become a fraction, eg. (20.153; 63.638). When canvas is used to draw this image, it attempts to use transparent pixels to make the ball appear in it's position more accurately.
I was wondering whether I should use Math.round() before drawing the ball to avoid the transparent pixel stuff, and possibly speeding up the game a lot. Will this help much? The game is a sorta complex pong game.
The image below should help with my explanation:
At least this guy seems to believe so. As Gabe mentioned, it depends on the implementation.
Note that some sort anti-aliasing seems to kick in if you are using regular coords (1, 14, etc.). For this reason some guides (Dive Into HTML5 mainly) seem to suggest that you are better off by rending using half pixels (ie. 1.5, 14.5, etc.). I don't know if this makes any difference to performance, though. It's noticeable on render result at least.
You might also want to experiment with various layering schemes. See this question for more information. Depending on your situation you might want to treat your objects as separate canvases even and just offset them on top of the background.
Alternatively you could try to render it all on one canvas. In this case you have some extra stuff to keep track of. This library seems to handle all the bookkeeping for you.