How to Flip Images Horizontally with HTML5

How to flip images horizontally with HTML5

canvas = document.createElement('canvas');
canvasContext = canvas.getContext('2d');

canvasContext.translate(width, 0);
canvasContext.scale(-1, 1);
canvasContext.drawImage(image, 0, 0);

Here's a snippet from a sprite object being used for testing and it produces the results you seem to expect.

Here's another site with more details. http://andrew.hedges.name/widgets/dev/

How to flip an image with the HTML5 canvas without scaling

Negative region does not seem to be supported (yet?), or this line may affect how the implementation is done, ref. step 4:

The image data must be processed in the original direction, even if
the dimensions given are negative.

In any case, we can't do much about it but to look at alternative ways -

This leaves you with some options though - I assume you want to avoid using save/restore, and you can -

Reset transformation

This is the fastest method, but you need to be aware of that it will reset any transformation. And this may be OK in most cases, so:

ctx.scale(-1, 1);
ctx.drawImage(image, -image.width, 0);
ctx.setTransform(1, 0, 0, 1, 0, 0);

The last call is resetting the transformation matrix using an identity matrix.

Reversing last transformation operation

If you depend on other transformations, you can simply reverse the last transformation operation. This is the second fastest option (it need to do a matrix multiplication internally):

ctx.scale(-1, 1);
ctx.drawImage(image, -image.width, 0);
ctx.scale(-1, 1); // revert scale only

Using save/restore

As you already know... but slow as it saves and restores the whole state of the canvas, not just the transformation.

Flipping manually

If there for some reason is a requirement not to use transformation at all, you can always flip it scanline by scanline. This is the second least efficient method but allows you to work without transformations, and it does allow you to do other things like displacing:

for(var x = 0; x < width; x++)
ctx.drawImage(img, x, 0, 1, height, width - x, 0, 1, height);

(width and height being the image's width and height).

Pixel manipulation

And the last, just for the record, is of course to get the pixel data and loop through, switch places etc. This is the slowest method and it depends on CORS requirement, and is not recommended for this.

How to horizontally flip an image

First, to remove your 2 unwanted image, just clear the canvas and redraw the desired images. You can clear the canvas using context.clearRect(0,0,canvas.width,canvas.height).

Flip image(s) horizontally

Sample Image

How to horizontally flip an image:

  1. Move (translate) the canvas origin to your desired X-coordinate plus the image width: context.translate(x+img.width,y); Adding the img.width is necessary because we are grabbing the left edge of the image and flipping it leftward. Without adding img.width, the img would be drawn leftward of the desired x-coordinate.

  2. Flip horizontally using context.scale(-1,1);

  3. Draw the image: `context.drawImage(img,0,0);

  4. Clean up by resetting transformations to their default values: context.setTransform(1,0,0,1,0,0);

Annotated code and a Demo:

var canvas=document.getElementById("canvas");var ctx=canvas.getContext("2d");var cw=canvas.width;var ch=canvas.height;
var img=new Image();img.onload=start;img.src="https://dl.dropboxusercontent.com/u/139992952/multple/sillouette2.png";function start(){
ctx.fillText('original',10,30); ctx.drawImage(img,10,30);
ctx.fillText('flipped',150,30); flipHorizontally(img,150,30);
}
function flipHorizontally(img,x,y){ // move to x + img's width ctx.translate(x+img.width,y);
// scaleX by -1; this "trick" flips horizontally ctx.scale(-1,1); // draw the img // no need for x,y since we've already translated ctx.drawImage(img,0,0); // always clean up -- reset transformations to default ctx.setTransform(1,0,0,1,0,0);}
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=300 height=300></canvas>

How to flip sprites horizontally with HTML5 Canvas?

You would save you a lot of time taking an Image editor and making all your sprites fit in same-sized areas along the whole sprite-sheet.

No need metadata weirdness, code is way simpler (a single w, a single h, x = w * i etc.

For example, your largest sprite is around 70px wide, so you should fit all your other sprites in one of such boxes :

empty sprite-sheet with border

Now, it seems that all your sprites share the same position of the front foot. So you should use it as the anchor point for aligning all your sprites.

Something like this :

sprite-sheet with sprites and border
Note how for all the sprites, the front foot is always at the same position relatively to its own box.

Now it's quite easy to code animation of this sprite-sheet, and even to flip it :

const ssheet = new Image();ssheet.src = 'https://i.stack.imgur.com/kXKIc.png'; // same without bordersssheet.onload = startSheetAnim;
function startSheetAnim(evt) { const ctx = c.getContext('2d'); const h = 49; const w = 70; let i = 0;
function anim() { ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, c.width, c.height); ctx.drawImage(ssheet, (i * w), 1, w, h, 0, 0, w, h ); // scale (flip-x) and translate ctx.setTransform(-1, 0, 0, 1, w * 2, 0); ctx.drawImage(ssheet, (i * w), 1, w, h, 0, 0, w, h );
i = (i + 1) % 12 setTimeout(anim, 100); } anim();}
<canvas id="c"></canvas>

HTML Canvas: How to draw a flipped/mirrored image?

  1. You can do this by transforming the context with myContext.scale(-1,1) before drawing your image, however

  2. This is going to slow down your game. It's a better idea to have a separate, reversed sprite.

How to horizontally flip images already on the canvas?

The webGL canvas can be used just like an image. You don't need to use the slow gl.readPixels and ctx.setImageData methods to move the image data

// where canvasGL is the webGL canvas and ctx is the 2D  canvas context
ctx.setTransform(1,0,0,-1,0,canvasGL.height);
ctx.drawImage(canvasGL,0,0);

Flip / mirror an image horizontally + vertically with css

Try this:

.img-hor-vert {
-moz-transform: scale(-1, -1);
-o-transform: scale(-1, -1);
-webkit-transform: scale(-1, -1);
transform: scale(-1, -1);
}

Updated fiddle: https://jsfiddle.net/7vg2tn83/1/

It wasn't working before because you were overriding the transform in your css. So instead of doing both, it just did the last one. Sort of like if you did background-color twice, it would override the first one.

How to rotate and mirror canvas element?

setTransform(1,0,0,-1,0,canvas.height);

Use setTransform it takes 6 numbers. The first 2 are the direction and scale of the x axis in pixels. By default it is 1,0. The next two are the direction and scale of the y axis. By default it is 0,1. The last two are the origin. Where on the canvas something will be drawn if you draw at 0,0. By default it is at 0,0 top left.

Rotating the canvas 180 will flip both the x and y axis. the x axis goes from 1,0 to -1,0 and y axis from 0,1 to 0,-1.

To mirror on the x axis just reverse x component of the x Axis thus the rotated -1,0 mirrors to 1,0.

Now we need to set the origin. The x axis moves from left to right as normal 1,0 so the x origin is on the left at 0. The y axis moves from bottom up thus the origin needs to be at the bottom of the canvas.

The result then is

ctx.setTransform(1,0,0,-1,0,canvas.height);
ctx.drawImage(0,0)

BTW rotate 180 then mirror X is the same as just mirror Y.



Related Topics



Leave a reply



Submit