Reputation: 6406
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
Upvotes: 49
Views: 66860
Reputation: 8457
If you just flip it horizontally using ctx.scale(-1, 1)
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) instead:
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();
Upvotes: 21
Reputation: 331
You need to set the scale of the canvas as well as inverting the width.
function drawToCanvas(img, context, width, height){
context.save();
context.scale(-1, 1);
context.drawImage(img, 0, 0, width*-1, height);
context.restore();
}
There are probably some performance issues with this but for me that was not an issue.
Upvotes: 33
Reputation: 397
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>
Upvotes: 4
Reputation: 303205
You can do this by transforming the context with myContext.scale(-1,1)
before drawing your image, however
This is going to slow down your game. It's a better idea to have a separate, reversed sprite.
Upvotes: 40