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

49,235

Solution 1

  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.

Solution 2

You need to set the scale of the canvas as well as inverting the width.

drawToCanvas : function(v, context, width, height){
    context.save();
    context.scale(-1, 1);
    context.drawImage(v, 0, 0, width*-1, height);
    context.restore();
}

There are probably some performance issues with this but for me that was not an issue.

Solution 3

If you just flip it horizontally it will get off of bounds... so use translate to adjust its position:

ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
ctx.drawImage(img, 0, 0);

For a shorter code you can remove the translate and use the image size as negative offset in the second parameter of the drawImage (x coordinate):

ctx.scale(-1, 1);
ctx.drawImage(img, canvas.width * -1, 0);

If you want to restore the context later, add save/restore before and after it all:

ctx.save();
ctx.scale(-1, 1);
ctx.drawImage(img, canvas.width * -1, 0);
ctx.restore();

Solution 4

You don't need to redraw the entire image when creating a reflection. An original reflection simply shows the bottom part of the image. This way you are redrawing a smaller part of the image which provides better performance and also you don't need to create linear gradient to hide the lower part of the image (since you never draw it).

 var img = new Image();
 img.src = "//vignette2.wikia.nocookie.net/tomandjerryfan/images/9/99/Jerry_Mouse.jpg/revision/latest?cb=20110522075610";
 img.onload = function() {
   var thumbWidth = 250;
   var REFLECTION_HEIGHT = 50;
   var c = document.getElementById("output");
   var ctx = c.getContext("2d");
   var x = 1;
   var y = 1;

	//draw the original image
   ctx.drawImage(img, x, y, thumbWidth, thumbWidth);
	ctx.save();
	//translate to a point from where we want to redraw the new image
   ctx.translate(0, y + thumbWidth + REFLECTION_HEIGHT + 10);
   ctx.scale(1, -1);
   ctx.globalAlpha = 0.25;
   
   //redraw only bottom part of the image
   //g.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
   ctx.drawImage(img, 0, img.height - REFLECTION_HEIGHT, img.width, REFLECTION_HEIGHT, x, y, thumbWidth, REFLECTION_HEIGHT);

   // Revert transform and scale
  ctx.restore();

 };
 body {
   background-color: #FFF;
   text-align: center;
   padding-top: 10px;
 }
<canvas id="output" width="500" height="500"></canvas>

Share:
49,235
Jem
Author by

Jem

Updated on January 22, 2022

Comments

  • Jem
    Jem over 2 years

    I'm trying to flip/mirror an image as I paint it on an HTML canvas; I found a game tutorial showing a sprite sheet per direction a character has to face, but this doesn't seem quite right to me. Especially since each frame has a different size.

    What would be the best technique to reach this goal?

    I tried to call the setScale(-1, 1); on my canvas with no success. Maybe that isn't meant for this.

    Thanks