Cloudinary Blog

Rotating Images in JavaScript: Three Quick Tutorials

Rotating Images in JavaScript: Three Quick Tutorials

With JavaScript (JS), you can create cool image animations, which are difficult to do with Cascading Style Sheets (CSS). This article describes how to—

  • Dynamically rotate or flip images with JS.
  • Automatically rotate and remove image backgrounds with Cloudinary.

Here are the topics:

Dynamically Rotating Images With JS

To rotate images with JS, edit the CSS transform property. See the procedure below.

Rotating Images With a Click

First, define the image element in your HTML source and create a clickable element, which can be a button or the image itself. For example:

HTML

<img class="rotate" src="image.jpg"/>

JS file or <script> element

Next, define a rotational variable to maintain the image rotation, enabling multiple rotations, as here:

const current_rotation = 0;

Finally, add an event listener to the image (see the code below). In the listener function, incrementing the rotation with positive numbers rotates the image in a clockwise direction; doing that with negative numbers results in a counterclockwise rotation.

Copy to clipboard
document.querySelector(".rotate").addEventListener('click', function(){
    current_rotation += 90;
document.querySelector(".rotate").style.transform = 'rotate(' + current_rotation + 'deg)';
});

Customizing Rotations

When applying rotations, you can add CSS properties to animate rotations or set up rotations around a specific point of the image.

Animations

To animate rotations, apply the CSS transition property to specify which other property is transitioned and when. For example, the following code causes the rotation to occur in half a second with a slow start.

Copy to clipboard
.rotate {
    transition: transform 0.5s ease-in;
}

Rotation point

By default, the image rotates around its center point. To have the image rotate around another point, specify that point with the transform-origin property in CSS.

If manually defined, the center point is at 50% 50%. You can alter the x and y values for 2D images, and the z value for 3D images. For example:

To set the origin in the upper-right corner:

Copy to clipboard
.rotate {
    transform-origin: 100% 0%;
}

To set the origin in the upper-left corner:

Copy to clipboard
.rotate {
    transform-origin: 0% 0%;
}

For more cool tricks, see our articles on resizing with JavaScript and with CSS.

Flipping Images With JS

Flipping or mirroring images is a common task. Displaying mirrored images with 'transform: scaleX(-1')in CSS is just an effect, not a permanent change. To persistently flip an image for static use, create a canvas in JS to transform and output the image after flipping.

The code examples below are adapted from a tutorial by Rik Schennink.

HTML

First, define the image element:

<img src="image.jpg" class="image-flip"/>

JS file or <script> element

Next, create a reference to your image for transformations with a canvas:

const inputImage = document.querySelector('.image-flip');

Add logic to ensure that the flipping occurs at the right time. The code below first checks if image loading is complete and, if so, the flip function runs. Otherwise, the function waits till loading is done before flipping the image.

Copy to clipboard
if (inputImage.complete) {
  flipImage();
}
else {
  inputImage.onload = flipImage;
}

Now create a function that flips the image—in effect, create a canvas, set it to the same size as the image, and define your drawing context. You can then flip the image with ctx.scale(), draw the image on the canvas with ctx.drawImage, and display the output image with insertBefore() on the appropriate Document Object Model (DOM) element. Here’s the code:

Copy to clipboard
function flipImage() {

  const outputImage = document.createElement("canvas");
  outputImage.width = inputImage.naturalWidth;
  outputImage.height = inputImage.naturalHeight;

  const ctx = outputImage.getContext("2d");

  // Flip the image by scaling negatively to the left
  ctx.scale(-1, 1);

  // Draw the image on the canvas
  // Starts at [-width, 0] because the flip scaled negatively
  ctx.drawImage(inputImage, -outputImage.width, 0);

  // Display the output image after the input image in your client
inputImage.parentNode.insertBefore(outputImage, inputImage.nextElementSibling);
}

For details on transforming images with CSS, see this article on CSS image effects.

Dynamically Rotating Images With Cloudinary

A cloud-based service for managing images and videos, Cloudinary offers a generous free-forever subscription plan. While on that platform, you can upload your images, apply built-in effects, filters, and modifications, including automated image rotations that are difficult or impossible to produce with CSS and JS.

Also with Cloudinary, you can easily transform images programmatically with SDKs or URL parameters. Cloudinary applies changes dynamically, leaving your original images intact. That means you can modify images on the fly as your site design evolves and as you support more devices and screen sizes—a huge convenience and time saver.

Below are two ways in which to rotate images with Cloudinary.

Automatically Flip Videos

To automatically rotate and flip videos, set the angle parameter ('a_') with a numerical value. To mirror videos, set the 'vflip' (for vertical flips) or hflip (for horizontal flips) parameter. Here’s an example of a video mirrored vertically:

Ruby:
Copy to clipboard
cl_video_tag("dog", :transformation=>[
  {:angle=>"vflip"},
  {:width=>500, :crop=>"scale"}
  ])
PHP v1:
Copy to clipboard
cl_video_tag("dog", array("transformation"=>array(
  array("angle"=>"vflip"),
  array("width"=>500, "crop"=>"scale")
  )))
PHP v2:
Copy to clipboard
(new VideoTag('dog.mp4'))
  ->rotate(Rotate::mode(RotationMode::verticalFlip()))
  ->resize(Resize::scale()->width(500));
Python:
Copy to clipboard
CloudinaryVideo("dog").video(transformation=[
  {'angle': "vflip"},
  {'width': 500, 'crop': "scale"}
  ])
Node.js:
Copy to clipboard
cloudinary.video("dog", {transformation: [
  {angle: "vflip"},
  {width: 500, crop: "scale"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .angle("vflip").chain()
  .width(500).crop("scale")).videoTag("dog");
JS:
Copy to clipboard
cloudinary.videoTag('dog', {transformation: [
  {angle: "vflip"},
  {width: 500, crop: "scale"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("dog", {transformation: [
  {angle: "vflip"},
  {width: 500, crop: "scale"}
  ]})
React:
Copy to clipboard
<Video publicId="dog" >
  <Transformation angle="vflip" />
  <Transformation width="500" crop="scale" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="dog" >
  <cld-transformation angle="vflip" />
  <cld-transformation width="500" crop="scale" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="dog" >
  <cl-transformation angle="vflip">
  </cl-transformation>
  <cl-transformation width="500" crop="scale">
  </cl-transformation>
</cl-video>
.NET:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Angle("vflip").Chain()
  .Width(500).Crop("scale")).BuildVideoTag("dog")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .angle("vflip").chain()
  .width(500).crop("scale")).resourceType("video").generate("dog.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setAngle("vflip").chain()
  .setWidth(500).setCrop("scale")).generate("dog.mp4")

cloudinary.videoTag('dog', {angle: “vflip”, width: 500}).toHtml();

If the angle skews the display with bounding boxes around the video, select the color of the boxes and display a blurred version of the video in that space. See this example of a video with white bounding boxes.

Ruby:
Copy to clipboard
cl_video_tag("dog", :transformation=>[
  {:angle=>45},
  {:width=>500, :crop=>"scale"}
  ])
PHP v1:
Copy to clipboard
cl_video_tag("dog", array("transformation"=>array(
  array("angle"=>45),
  array("width"=>500, "crop"=>"scale")
  )))
PHP v2:
Copy to clipboard
(new VideoTag('dog.mp4'))
  ->rotate(Rotate::byAngle(45))
  ->resize(Resize::scale()->width(500));
Python:
Copy to clipboard
CloudinaryVideo("dog").video(transformation=[
  {'angle': 45},
  {'width': 500, 'crop': "scale"}
  ])
Node.js:
Copy to clipboard
cloudinary.video("dog", {transformation: [
  {angle: 45},
  {width: 500, crop: "scale"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .angle(45).chain()
  .width(500).crop("scale")).videoTag("dog");
JS:
Copy to clipboard
cloudinary.videoTag('dog', {transformation: [
  {angle: 45},
  {width: 500, crop: "scale"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("dog", {transformation: [
  {angle: 45},
  {width: 500, crop: "scale"}
  ]})
React:
Copy to clipboard
<Video publicId="dog" >
  <Transformation angle="45" />
  <Transformation width="500" crop="scale" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="dog" >
  <cld-transformation angle="45" />
  <cld-transformation width="500" crop="scale" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="dog" >
  <cl-transformation angle="45">
  </cl-transformation>
  <cl-transformation width="500" crop="scale">
  </cl-transformation>
</cl-video>
.NET:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Angle(45).Chain()
  .Width(500).Crop("scale")).BuildVideoTag("dog")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .angle(45).chain()
  .width(500).crop("scale")).resourceType("video").generate("dog.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setAngle(45).chain()
  .setWidth(500).setCrop("scale")).generate("dog.mp4")

cloudinary.videoTag('dog', {angle: 20, width: 500}).toHtml();

Automatically Rotate Images and Remove Backgrounds

By leveraging Cloudinary’s machine-learning features, you can remove image backgrounds and rotate the image itself. That’s a neat way for creating product mockups or customizing images.

To remove the background, use Cloudinary’s AI Removal Background add-on with which you can upload images with Ruby, PHP, Python, Java, .NET, or Node.js, and assign output URLs. Below is an example in Node.js:

Copy to clipboard
cloudinary.v2.uploader.upload("baseball.jpg", 
  { public_id: "baseball_no_bg",
    background_removal: "cloudinary_ai",
    notification_url: "https://mysite.example.com/hooks" }),
  function(error, result){console.log(result);});

These:

Become These!

Baseball player - original

baseball player - no background

Afterwards, you can flip or rotate the backgroundless image as you desire. The example below rotates it by 60 degrees clockwise.

Ruby:
Copy to clipboard
cl_image_tag("docs/rmv_bgd/baseball.png", :angle=>60)
PHP v1:
Copy to clipboard
cl_image_tag("docs/rmv_bgd/baseball.png", array("angle"=>60))
PHP v2:
Copy to clipboard
(new ImageTag('docs/rmv_bgd/baseball.png'))
  ->rotate(Rotate::byAngle(60));
Python:
Copy to clipboard
CloudinaryImage("docs/rmv_bgd/baseball.png").image(angle=60)
Node.js:
Copy to clipboard
cloudinary.image("docs/rmv_bgd/baseball.png", {angle: 60})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().angle(60)).imageTag("docs/rmv_bgd/baseball.png");
JS:
Copy to clipboard
cloudinary.imageTag('docs/rmv_bgd/baseball.png', {angle: 60}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/rmv_bgd/baseball.png", {angle: 60})
React:
Copy to clipboard
<Image publicId="docs/rmv_bgd/baseball.png" >
  <Transformation angle="60" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/rmv_bgd/baseball.png" >
  <cld-transformation angle="60" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/rmv_bgd/baseball.png" >
  <cl-transformation angle="60">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Angle(60)).BuildImageTag("docs/rmv_bgd/baseball.png")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().angle(60)).generate("docs/rmv_bgd/baseball.png");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setAngle(60)).generate("docs/rmv_bgd/baseball.png")!, cloudinary: cloudinary)
baseball

Copy to clipboard
cloudinary.imageTag('baseball.png', {transformation: [
  {width: 500 },
  {angle: 60 }
  ]}).toHtml();

Ruby:
Copy to clipboard
cl_image_tag("docs/rmv_bgd/baseball.png", :width=>500, :angle=>60, :crop=>"scale")
PHP v1:
Copy to clipboard
cl_image_tag("docs/rmv_bgd/baseball.png", array("width"=>500, "angle"=>60, "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new ImageTag('docs/rmv_bgd/baseball.png'))
  ->rotate(Rotate::byAngle(60))
  ->resize(Resize::scale()->width(500));
Python:
Copy to clipboard
CloudinaryImage("docs/rmv_bgd/baseball.png").image(width=500, angle=60, crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("docs/rmv_bgd/baseball.png", {width: 500, angle: 60, crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(500).angle(60).crop("scale")).imageTag("docs/rmv_bgd/baseball.png");
JS:
Copy to clipboard
cloudinary.imageTag('docs/rmv_bgd/baseball.png', {width: 500, angle: 60, crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/rmv_bgd/baseball.png", {width: 500, angle: 60, crop: "scale"})
React:
Copy to clipboard
<Image publicId="docs/rmv_bgd/baseball.png" >
  <Transformation width="500" angle="60" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/rmv_bgd/baseball.png" >
  <cld-transformation width="500" angle="60" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/rmv_bgd/baseball.png" >
  <cl-transformation width="500" angle="60" crop="scale">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(500).Angle(60).Crop("scale")).BuildImageTag("docs/rmv_bgd/baseball.png")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(500).angle(60).crop("scale")).generate("docs/rmv_bgd/baseball.png");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(500).setAngle(60).setCrop("scale")).generate("docs/rmv_bgd/baseball.png")!, cloudinary: cloudinary)
baseball

Learning More About Cloudinary

Besides image rotations, Cloudinary offers a multitude of robust tools for web developers, including the following:

  • Automated image uploads. You can upload images at scale anywhere from a browser, mobile app, or application back-end directly to the cloud.
  • Generous image storage. Cloudinary accords you up to 25 GB free managed, secure, and cloud-based storage space with multiregion backup, revision history, and disaster recovery.
  • Seamless asset management. You can efficiently manage your image library on Cloudinary by performing tasks like searching, organizing, and tagging files; controlling access; and monitoring usage and performance.
  • Effective image transformations. You can transform, enhance, transcode, crop, scale, and enhance images with a URL-based API or with SDKs that support all popular programming languages.
  • Automated image optimization. Cloudinary automatically selects the optimal quality and encoding settings for images, adapts the settings to any resolution or pixel density, and scales or crops images to focus on the important regions.
  • Responsive images. Cloudinary automatically scales images in an art-directed manner, cropping them to fit different resolutions and viewports.
  • Reliable and fast image delivery. Cloudinary delivers images through Content Delivery Networks (CDNs)—Akamai, Fastly, and CloudFront—with no integration or management on your part.

Do give Cloudinary a try. To start, sign up for a free account.

Checking Out the Details of CSS Image Transformations

Want to learn more about CSS image transformations? These articles are an excellent resource:

Recent Blog Posts

Our $2B Valuation

By
Blackstone Growth Invests in Cloudinary

When we started our journey in 2012, we were looking to improve our lives as developers by making it easier for us to handle the arduous tasks of handling images and videos in our code. That initial line of developer code has evolved into a full suite of media experience solutions driven by a mission that gradually revealed itself over the course of the past 10 years: help companies unleash the full potential of their media to create the most engaging visual experiences.

Read more
Direct-to-Consumer E-Commerce Requires Compelling Visual Experiences

When brands like you adopt a direct–to-consumer (DTC) e-commerce approach with no involvement of retailers or marketplaces, you gain direct and timely insight into evolving shopping behaviors. Accordingly, you can accommodate shoppers’ preferences by continually adjusting your product offering and interspersing the shopping journey with moments of excitement and intrigue. Opportunities abound for you to cultivate engaging customer relationships.

Read more
Automatically Translating Videos for an International Audience

No matter your business focus—public service, B2B integration, recruitment—multimedia, in particular video, is remarkably effective in communicating with the audience. Before, making video accessible to diverse viewers involved tasks galore, such as eliciting the service of production studios to manually dub, transcribe, and add subtitles. Those operations were costly and slow, especially for globally destined content.

Read more
Cloudinary Helps Minted Manage Its Image-Generation Pipeline at Scale

Shoppers return time and again to Minted’s global online community of independent artists and designers because they know they can count on unique, statement-making products of the highest quality there. Concurrently, the visual imagery on Minted.com must do justice to the designs into which the creators have poured their hearts and souls. For Minted’s VP of Engineering David Lien, “Because we are a premium brand, we need to ensure that every single one of our product images matches the selected configuration exactly. For example, if you pick an 18x24 art print on blue canvas, we will show that exact combination on the hero images in the PDF.”

Read more
Highlights on ImageCon 2021 and a Preview of ImageCon 2022

New year, same trend! Visual media will continue to play a monumental role in driving online conversions. To keep up with visual-experience trends and best practices, Cloudinary holds an annual conference called ImageCon, a one-of-a-kind event that helps attendees create the most engaging visual experiences possible.

Read more