HTML Canvas: How to draw a flipped/mirrored image?
You can do this by transforming the context with
myContext.scale(-1,1)
before drawing your image, howeverThis is going to slow down your game. It's a better idea to have a separate, reversed sprite.
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.
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/
Flipping and mirroring an image multiple times on a canvas
Flipping an image horizontally (left to right) involves:
translate to the horizontal middle of the image. This sets the rotation point as the horizontal middle of the image. It does this by moving the canvas's [0,0] origin horizontally to the middle of the image.
context.translate(x+img.width/2,0);
Use scale to flip the image horizontally. This causes the image to be drawn as a horizontal mirror of itself.
context.scale(-1,1);
drawImage the image offset by half the image's width. This offset is necessary because
context.translate
has moved the [0,0] to the midpoint of the image so the image must be pulled leftward so that it's drawn at the desired X location.context.drawImage(img,-img.width/2,y);
Here's example 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/car1.png";function start(){ drawImageExtended(img,50,50); drawImageExtended(img,50,92,true);}
function drawImageExtended(img,x,y,flipHorizontally){ if(flipHorizontally){ ctx.translate(x+img.width/2,0); ctx.scale(-1,1); ctx.drawImage(img,-img.width/2,y); }else{ ctx.drawImage(img,x,y); }}
body{ background-color: ivory; }#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>
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
How to horizontally flip an image:
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.Flip horizontally using
context.scale(-1,1);
Draw the image: `context.drawImage(img,0,0);
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 & Rotate images on HTML5 Canvas
value: function drawRotatedImage(canvas, image, angle, mirrorImage) {
var context = canvas.getContext('2d');
if (angle > 0) {
context.rotate(angle * (Math.PI / 180));
}
if (mirrorImage === true) {
if (angle > 0) {
context.scale(-1, 1);
context.drawImage(image, -image.width, -image.height, image.width, image.height);
}
}
if (mirrorImage === true) {
if (angle < 1) {
context.scale(-1, 1);
context.drawImage(image, -image.width, 0, image.width, image.height);
}
} else {
context.drawImage(image, 0, angle === 0 ? 0 : -image.height);
}
return canvas;
}
getusermedia - Mirror image instead of flip
The arguments to CanvasContext2d.setTransform are
setTransform(scaleX, skewX, skewY, scaleY, translateX, translateY)
You are setting scaleY
to -1 and translating by height on the Y axis. So indeed, you flipped vertically.
To flip horizontally, you'd do
ctx.setTransform(-1,0,0,1,canvas.width,0);
const vid = document.createElement('video');const ctx = canvas.getContext('2d');// gUM has problems with StackSnippet's overprotected iframes// so we'll use a normal video insteadvid.src = 'https://upload.wikimedia.org/wikipedia/commons/transcoded/a/a4/BBH_gravitational_lensing_of_gw150914.webm/BBH_gravitational_lensing_of_gw150914.webm.480p.webm';vid.play() .then(() => { canvas.width = vid.videoWidth; canvas.height = vid.videoHeight; drawloop(); });
function drawloop() { if (inp.checked) { ctx.setTransform(-1, 0, 0, 1, canvas.width, 0); } else { ctx.setTransform(1, 0, 0, 1, 0, 0); } ctx.drawImage(vid, 0, 0); requestAnimationFrame(drawloop);}
canvas { width: 100%;}
<label>flip horizontally<input type="checkbox" id="inp"></label><br><canvas id="canvas"></canvas>
Flip a sprite in canvas
You can transform the canvas drawing context without flipping the entire canvas.
c.save();
c.scale(-1, 1);
will mirror the context. Draw your image, then
c.restore();
and you can draw normally again. For more information, see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Transformations
Related Topics
Calculate Position of Selected Text JavaScript/Jquery
Center Flex Item in Container, When Surrounded by Other Flex Items
Duplicating an Element (And Its Style) with JavaScript
How to Properly Escape Attribute Values in CSS/Js Attribute Selector [Attr=Value]
Use CSS (And Maybe JavaScript) to Make an Element Be Square (Or Maintain a Specific Aspect Ratio)
Best Way to Make Bootstrap Responsive Based on Parent Div
Jquery Animate a -Webkit-Transform
Change CSS of the Add Form Using Jqgrid
How to Make a Rotated Element Height:100% of Its Parent
How to Remove the Parent Element Using Plain JavaScript
Sticky Header Flickering on Safari Desktop Only When Anchor Scrolling
Convert CSS Text to JavaScript Object
Is There a Performance Difference Between the Sx Prop and the Makestyles Function in Material Ui
How to Avoid Animation Artifacts on My Touch-Draggable Border-Radius Element on iPad