English 中文(简体)
How to flip images horizontally with HTML5
原标题:

In IE, I can use:

<img src="http://example.com/image.png" style="filter:FlipH">

to implement an image flip horizontally.

Is there any way to flip horizontally in HTML5? (maybe by using canvas?)

thanks all :)

最佳回答
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/

问题回答

You don t need HTML5, it can be done with CSS same as in IE:

-moz-transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
-o-transform: scale(-1, 1);
transform: scale(-1, 1);
filter: FlipH;

I like Eschers function above. I have made it a little neater and better. I have added flop (vertically) besides flip. Also a possibility to draw/rotate around the center of the image instead of top left. Finally, the function does not require all arguments. img, x and y are required but the rest are not.

If you were using something like context.drawImage(...), you can now just use drawImage(...) and add the rotate/flip/flop functionality explained here:

function drawImage(img, x, y, width, height, deg, flip, flop, center) {

context.save();

if(typeof width === "undefined") width = img.width;
if(typeof height === "undefined") height = img.height;
if(typeof center === "undefined") center = false;

// Set rotation point to center of image, instead of top/left
if(center) {
    x -= width/2;
    y -= height/2;
}

// Set the origin to the center of the image
context.translate(x + width/2, y + height/2);

// Rotate the canvas around the origin
var rad = 2 * Math.PI - deg * Math.PI / 180;    
context.rotate(rad);

// Flip/flop the canvas
if(flip) flipScale = -1; else flipScale = 1;
if(flop) flopScale = -1; else flopScale = 1;
context.scale(flipScale, flopScale);

// Draw the image    
context.drawImage(img, -width/2, -height/2, width, height);

context.restore();
}

Examples:

var myCanvas = document.getElementById("myCanvas");
var context = myCanvas.getContext("2d"); // i use context instead of ctx

var img = document.getElementById("myImage"); // your img reference here!

drawImage(img, 100, 100); // just draw it 
drawImage(img, 100, 100, 200, 50); // draw it with width/height specified
drawImage(img, 100, 100, 200, 50, 45); // draw it at 45 degrees
drawImage(img, 100, 100, 200, 50, 0, true); // draw it flipped
drawImage(img, 100, 100, 200, 50, 0, false, true); // draw it flopped
drawImage(img, 100, 100, 200, 50, 0, true, true); // draw it flipflopped
drawImage(img, 100, 100, 200, 50, 45, true, true, true); // draw it flipflopped and 45 degrees rotated around the center of the image :-)

Mirror an image or rendering using the canvas.

Note. This can be done via CSS as well.


Mirroring

Here is a simple utility function that will mirror an image horizontally, vertically or both.

function mirrorImage(ctx, image, x = 0, y = 0, horizontal = false, vertical = false){
    ctx.save();  // save the current canvas state
    ctx.setTransform(
        horizontal ? -1 : 1, 0, // set the direction of x axis
        0, vertical ? -1 : 1,   // set the direction of y axis
        x + (horizontal ? image.width : 0), // set the x origin
        y + (vertical ? image.height : 0)   // set the y origin
    );
    ctx.drawImage(image,0,0);
    ctx.restore(); // restore the state as it was when this function was called
}

Usage

mirrorImage(ctx, image, 0, 0, true, false); // horizontal mirror
mirrorImage(ctx, image, 0, 0, false, true); // vertical mirror
mirrorImage(ctx, image, 0, 0, true, true);  // horizontal and vertical mirror

Drawable image.

Many times you will want to draw on images. I like to call them drawable images. To make an image drawable you convert it to a canvas

To convert an image to canvas.

function makeImageDrawable(image){
    if(image.complete){ // ensure the image has loaded
        var dImage = document.createElement("canvas"); // create a drawable image
        dImage.width = image.naturalWidth;      // set the resolution
        dImage.height = image.naturalHeight;
        dImage.style.width = image.style.width; // set the display size
        dImage.style.height = image.style.height; 
        dImage.ctx = dImage.getContext("2d");   // get drawing API
                                                // and add to image
                                                // for possible later use
        dImage.ctx.drawImage(image,0,0);
        return dImage;
    }
    throw new ReferenceError("Image is not complete.");
 }

Putting it all together

 var dImage = makeImageDrawable(image);  // convert DOM img to canvas
 mirrorImage(dImage.ctx, dImage, 0, 0, false, true); // vertical flip
 image.replaceWith(dImage);  // replace the DOM image with the flipped image
 

More mirrors

If you wish to be able to mirror along an arbitrary line see the answer Mirror along line

One option is to horizontally flip the pixels of images stored in ImageData objects directly, e.g.

function flip_image (canvas) {
   	var context   = canvas.getContext ( 2d ) ;
   	var imageData = context.getImageData (0, 0, canvas.width, canvas.height) ;
   	var imageFlip = new ImageData (canvas.width, canvas.height) ;
   	var Npel      = imageData.data.length / 4 ;

   	for ( var kPel = 0 ; kPel < Npel ; kPel++ ) {
   	   	var kFlip      = flip_index (kPel, canvas.width, canvas.height) ;
   	   	var offset     = 4 * kPel ;
   	   	var offsetFlip = 4 * kFlip ;
   	   	imageFlip.data[offsetFlip + 0] = imageData.data[offset + 0] ;
   	   	imageFlip.data[offsetFlip + 1] = imageData.data[offset + 1] ;
   	   	imageFlip.data[offsetFlip + 2] = imageData.data[offset + 2] ;
   	   	imageFlip.data[offsetFlip + 3] = imageData.data[offset + 3] ;
   	}

   	var canvasFlip = document.createElement( canvas ) ;
   	canvasFlip.setAttribute( width , width) ;
   	canvasFlip.setAttribute( height , height) ;

   	canvasFlip.getContext( 2d ).putImageData(imageFlip, 0, 0) ;
   	return canvasFlip ;
}

function flip_index (kPel, width, height) {
   	var i     = Math.floor (kPel / width) ;
   	var j     = kPel % width ;
   	var jFlip = width - j - 1 ;
   	var kFlip = i * width + jFlip ;
   	return kFlip ;
}

For anyone stumbling upon this. If you want to do more complex drawing, the other scale-based answers don t all work. By complex i mean situations where things are more dynamic, like for games.

The problem being that the location is also flipped. So if you want to draw a small image in the top left corner of the canvas and then flip it horizontally, it will relocate to the top right.

The fix is to translate to the center of where you want to draw the image, then scale, then translate back. Like so:

if (flipped) {
  ctx.translate(x + width/2, y + width/2);
  ctx.scale(-1, 1);
  ctx.translate(-(x + width/2), -(y + width/2));
}
ctx.drawImage(img, x, y, width, height);

Here x and y are the location you want to draw the image, and width and height are the width and height you want to draw the image.

I came across this page, and no-one had quite written a function to do what I wanted, so here s mine. It draws scaled, rotated, and flipped images (I used this for rending DOM elements to canvas that have these such transforms applied).

var myCanvas = document.getElementById("myCanvas");
var ctx = myCanvas.getContext("2d");
var img = document.getElementById("myimage.jpg"); //or whatever
var deg = 13; //13 degrees rotation, for example
var flip = "true";

function drawImage(img, x, y, width, height, deg, flip){
    //save current context before applying transformations
    ctx.save();
    //convert degrees to radians
    if(flip == "true"){ 
        var rad = deg * Math.PI / 180;
    }else{
        var rad = 2*Math.PI - deg * Math.PI / 180;
    }
    //set the origin to the center of the image
    ctx.translate(x + width/2, y + height/2);
    //rotate the canvas around the origin
    ctx.rotate(rad);
    if(flip == "true"){
        //flip the canvas
        ctx.scale(-1,1);
    }
    //draw the image    
    ctx.drawImage(img, -width/2, -height/2, width, height);
    //restore the canvas
    ctx.restore();
}




相关问题
CSS working only in Firefox

I am trying to create a search text-field like on the Apple website. The HTML looks like this: <div class="frm-search"> <div> <input class="btn" type="image" src="http://www....

image changed but appears the same in browser

I m writing a php script to crop an image. The script overwrites the old image with the new one, but when I reload the page (which is supposed to pickup the new image) I still see the old one. ...

Firefox background image horizontal centering oddity

I am building some basic HTML code for a CMS. One of the page-related options in the CMS is "background image" and "stretch page width / height to background image width / height." so that with large ...

Separator line in ASP.NET

I d like to add a simple separator line in an aspx web form. Does anyone know how? It sounds easy enough, but still I can t manage to find how to do it.. 10x!

热门标签