63

I need to rotate an image with javascript in 90-degree intervals. I have tried a few libraries like jQuery rotate and Raphaël, but they have the same problem - The image is rotated around its center. I have a bunch of content on all sides of the image, and if the image isn't perfectly square, parts of it will end up on top of that content. I want the image to stay inside its parent div, which has max-with and max-height set.

Using jQuery rotate like this (http://jsfiddle.net/s6zSn/1073/):

var angle = 0;
$('#button').on('click', function() {
    angle += 90;
    $("#image").rotate(angle);
});

Results in this:

How jQuery rotate works

And this is the result i would like instead:

How I would like it to work

Anyone have an idea on how to accomplish this?

6
  • 3
    Use CSS transforms to rotate the entire container around whatever point you like. Commented May 28, 2013 at 14:15
  • 1
    best way to go is using css3 keyframes i'm afraid Commented May 28, 2013 at 14:18
  • 1
    How to rotate an object back and forth around a specific point Commented May 28, 2013 at 14:27
  • FYI I've explained why this is happening over here Commented May 28, 2013 at 16:12
  • @DiederikEEn I'm afraid too ... Commented Sep 23, 2014 at 18:28

9 Answers 9

74

You use a combination of CSS's transform (with vendor prefixes as necessary) and transform-origin, like this: (also on jsFiddle)

var angle = 0,
  img = document.getElementById('container');
document.getElementById('button').onclick = function() {
  angle = (angle + 90) % 360;
  img.className = "rotate" + angle;
}
#container {
  width: 820px;
  height: 100px;
  overflow: hidden;
}
#container.rotate90,
#container.rotate270 {
  width: 100px;
  height: 820px
}
#image {
  transform-origin: top left;
  /* IE 10+, Firefox, etc. */
  -webkit-transform-origin: top left;
  /* Chrome */
  -ms-transform-origin: top left;
  /* IE 9 */
}
#container.rotate90 #image {
  transform: rotate(90deg) translateY(-100%);
  -webkit-transform: rotate(90deg) translateY(-100%);
  -ms-transform: rotate(90deg) translateY(-100%);
}
#container.rotate180 #image {
  transform: rotate(180deg) translate(-100%, -100%);
  -webkit-transform: rotate(180deg) translate(-100%, -100%);
  -ms-transform: rotate(180deg) translateX(-100%, -100%);
}
#container.rotate270 #image {
  transform: rotate(270deg) translateX(-100%);
  -webkit-transform: rotate(270deg) translateX(-100%);
  -ms-transform: rotate(270deg) translateX(-100%);
}
<button id="button">Click me!</button>
<div id="container">
  <img src="https://i.sstatic.net/zbLrE.png" id="image" />
</div>

Sign up to request clarification or add additional context in comments.

9 Comments

Add filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); for IE8 and IE7 support. rotation=1 for 90 deg, 2 for 180 deg, 3 for 270 deg.
Note that you should really apply this to the image container, if you want the border to work right.
Nopes ! this transform brings OP to the same problem. The transform is applied but not in the way OP wants
@OmShankar I think it still gives OP enough to go on.
This is almost working, however take a look that this: jsfiddle.net/bhN6e. I would like the text below the image to stay below the image, even after rotation. As it is right now, the image ends up on top of the text.
|
11
var angle = 0;
$('#button').on('click', function() {
    angle += 90;
    $('#image').css('transform','rotate(' + angle + 'deg)');
});

Try this code.

Comments

10

No need for jQuery and lot's of CSS anymore (Note that some browsers need extra CSS)

Kind of what @Abinthaha posted, but pure JS, without the need of jQuery.

let rotateAngle = 90;

function rotate(image) {
  image.setAttribute("style", "transform: rotate(" + rotateAngle + "deg)");
  rotateAngle = rotateAngle + 90;
}
#rotater {
  transition: all 0.3s ease;
  border: 0.0625em solid black;
  border-radius: 3.75em;
}
<img id="rotater" onclick="rotate(this)" src="https://upload.wikimedia.org/wikipedia/en/e/e0/Iron_Man_bleeding_edge.jpg"/>

4 Comments

The original accepted answer still works better for my use case, since I need text to flow properly below the image, and adapt to the size of the image. jsfiddle.net/soqkrbut is an updated version of the original answer, that works exactly as I want. Using this code does not work, see jsfiddle.net/uzhoy6pm
Thanks for this; hate when jquery gets forced into a question I otherwise have.
I know it should be avoided but +1 for the Iron Man image.
I was ahead of my time (50+ hours in the game now :)
3

CSS can be applied and you will have to set transform-origin correctly to get the applied transformation in the way you want

See the fiddle:

http://jsfiddle.net/OMS_/gkrsz/

Main code:

/* assuming that the image's height is 70px */

img.rotated {
    transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -ms-transform: rotate(90deg);

    transform-origin: 35px 35px;
    -webkit-transform-origin: 35px 35px;
    -moz-transform-origin: 35px 35px;
    -ms-transform-origin: 35px 35px;
}

jQuery and JS:

$(img)
    .css('transform-origin-x', imgWidth / 2)
    .css('transform-origin-y', imgHeight / 2);

// By calculating the height and width of the image in the load function

// $(img).css('transform-origin', (imgWidth / 2) + ' ' + (imgHeight / 2) );

Logic:

Divide the image's height by 2. The transform-x and transform-y values should be this value

Link:

transform-origin at CSS | MDN

6 Comments

What if the image's size changes, or is just not fixed? That'd be a mess. Mind you, this is a mess with 180 and 270 rotations ;)
@Kolink. Cool. Anyways, you have jQuery and JS on the page. One can calculate and apply this CSS on the fly. I am editing the answer for JS. Thanks for pointing out !
Seems a bit over-convoluted. I prefer my solution :p It's completely independent of the image's size.
@Kolink, I am going per the concept as read from Mozilla DN. In your solution (which is good of course), you are doing an additional tranlate. This is cheating :) Also, conceptually, translating is what is achieved by using the transform-origin values - only that they translate the origin of the transform, rather than the element itself
The problem is that you can't have a single origin to handle all four positions. This is why I stuck with one origin and adjusted the position to place it correctly.
|
3

Hope this can help you!

<input type="button" id="left"  value="left" />
<input type="button" id="right" value="right" />
<img src="https://www.google.com/images/srpr/logo3w.png" id="image">

<script>
 var angle = 0;
    $('#left').on('click', function () {  
        angle -= 90;
        $("#image").rotate(angle);
    });

    $('#right').on('click', function () {  
        angle += 90;
        $("#image").rotate(angle);
    });
</script>

Try it

Comments

3

i have seen your running code .There is one line correction in your code.

Write:

$("#wrapper").rotate(angle); 

instead of:

$("#image").rotate(angle);

and you will get your desired output,hope this is what you want.

1 Comment

@Mikeys4u The library wasn't loading. This one works: jsfiddle.net/MQ3YF/112
3

I think this will work.

    document.getElementById('#image').style.transform = "rotate(90deg)";

Hope this helps. It's work with me.

Comments

2

You can always apply CCS class with rotate property - http://css-tricks.com/snippets/css/text-rotation/

To keep rotated image within your div dimensions you need to adjust CSS as well, there is no needs to use JavaScript except of adding class.

1 Comment

"CCS class with rotate property" - Both typo and conceptual error?
0

Based on Anuga answer I have extended it to multiple images.

Keep track of the rotation angle of the image as an attribute of the image.

function rotate(image) {
  let rotateAngle = Number(image.getAttribute("rotangle")) + 90;
  image.setAttribute("style", "transform: rotate(" + rotateAngle + "deg)");
  image.setAttribute("rotangle", "" + rotateAngle);
}
.rotater {
  transition: all 0.3s ease;
  border: 0.0625em solid black;
  border-radius: 3.75em;
}
<img class="rotater" onclick="rotate(this)" src="https://upload.wikimedia.org/wikipedia/en/e/e0/Iron_Man_bleeding_edge.jpg"/>
<img class="rotater" onclick="rotate(this)" src="https://upload.wikimedia.org/wikipedia/en/e/e0/Iron_Man_bleeding_edge.jpg"/>
<img class="rotater" onclick="rotate(this)" src="https://upload.wikimedia.org/wikipedia/en/e/e0/Iron_Man_bleeding_edge.jpg"/>

Edit

Removed the modulo, looks strange.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.