AdBlock Detected!
Our website is made possible by displaying ads to our visitors. Please supporting us by whitelisting our website. Learn More

How to create an image editor using cropper.js

Hello friends, today in this blog, we will learn how to create an image editor using cropper.js. In our previous blog, we saw what are the top 5 programming languages to learn in 2023. You can check my other javascript projects after reading this blog.

In today's digital age, images are an essential part of our lives. Whether it's for personal use, social media, or business, images play a crucial role in conveying information and emotions. With the rise of social media platforms like Instagram and Snapchat, image editing has become an even more popular pastime. However, the options for editing images can be limited, and often the software can be expensive or difficult to use.

This is where Cropper.js comes in. Cropper.js is a powerful JavaScript library that allows you to easily create your own custom image editor. With Cropper.js, you can add various features like cropping, resizing, filtering, and more, to your image editor. In this blog post, we will take you through the step-by-step process of creating an image editor using Cropper.js. We'll cover everything from setting up the HTML and CSS files to adding functionality like image upload and download and customizing the interface to make it your own.

By the end of this blog post, you'll have a functional image editor that you can use to edit images for personal use or even integrate into your website or web application. So let's get started on this exciting journey of creating your very own image editor with Cropper.js!

Let's Set up the Project

Step by step guide to set up basic file structures for the project.
  1.  Create a new folder for your project and name it something descriptive.
  2. Inside the project folder, create a new file called index.html. This will be your main HTML file.
  3. Open index.html in a code editor such as Visual Studio Code.
  4. Inside the head section of index.html, create a new link element that links to your CSS file. The link element should look like this: "<link rel="stylesheet" href="styles.css">" Make sure to replace styles.css with the name of your CSS file.
  5. Save the changes to index.html.
  6. In the same project folder, create a new file called styles.css. This will be your main CSS file.
  7. Open styles.css in a code editor.
  8. Write your CSS rules inside styles.css.
  9. Save the changes to styles.css.
  10. In the head section of index.html, create a new script element that links to your JavaScript file. The script element should look like this: "<script src="script.js"></script>" Make sure to replace script.js with the name of your JavaScript file.
  11. Save the changes to index.html.
  12. In the same project folder, create a new file called script.js. This will be your main JavaScript file.
  13. Open script.js in a code editor.
  14. Write your JavaScript code inside script.js.
  15. Save the changes to script.js.
Now you have successfully created a basic HTML, CSS, and JavaScript file and linked them together. Any changes you make to your CSS or JavaScript files will be reflected in your index.html file when you refresh the page.


You may like these:

Here's the good news: you don't have to write all the code of this project from scratch! I have created a GitHub repository that contains all the HTML, CSS, and JavaScript code needed to build the app. You can check it out and use it as a starting point for your own project.

HTML Code

Just paste this code into HTML File which you have created.

 <!DOCTYPE html>  
 <html lang="en">  
 <head>  
   <!-- --------------------- Created By InCoder --------------------- -->  
   <meta charset="UTF-8">  
   <meta http-equiv="X-UA-Compatible" content="IE=edge">  
   <meta name="viewport" content="width=device-width, initial-scale=1.0">  
   <title>Image Editor - InCoderWeb</title>  
   <link rel="stylesheet" href="main.css">  
   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">  
   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.css">  
 </head>  
 <body>  
   <div class="header">  
     <div class="title">Image Editor</div>  
     <div class="options">  
       <input type="file" hidden>  
       <button class="inBtn openNewFile" title="Open Image File"><i class="fa-solid fa-file-image"></i></button>  
       <a href="https://github.com/InCoderWeb" target="_blank" title="Github Profile"><button class="inBtn"><i class="fa-brands fa-github"></i></button></a>  
       <button class="inBtn outputDownloadBtn hide"><i class="fa-solid fa-download"></i></button>  
     </div>  
   </div>  
   <div class="mainContainer">  
     <div class="dragOrDropContainer">  
       <div class="icon"><i class="fa-solid fa-cloud-arrow-up"></i></div>  
       <div class="text">Drag & Drop to Upload File</div>  
     </div>  
     <div class="editorOptions">  
       <div class="sideBar active">  
         <button class="sidebarToggleBtn"><i class="fa-solid fa-chevron-left"></i></button>  
         <div class="preview">  
           <p>Preview</p>  
           <div class="previewImage"></div>  
         </div>  
         <div class="options">  
           <div class="zoom">  
             <p>Zoom In / Zoom Out</p>  
             <div class="btnWrapper">  
               <button class="optionBtn zoomIn"><i class="fa-solid fa-magnifying-glass-plus"></i></button>  
               <button class="optionBtn zoomOut"><i class="fa-solid fa-magnifying-glass-minus"></i></button>  
             </div>  
           </div>  
           <div class="rotate">  
             <p>Rotate Image</p>  
             <div class="btnWrapper">  
               <button class="optionBtn rotateLeft"><i class="fa-solid fa-rotate-left"></i></button>  
               <button class="optionBtn rotateRight"><i class="fa-solid fa-rotate-right"></i></button>  
             </div>  
           </div>  
           <div class="flip">  
             <p>Flip Image</p>  
             <div class="btnWrapper">  
               <button class="optionBtn flipLeftRight"><i class="fa-solid fa-arrows-left-right"></i></button>  
               <button class="optionBtn flipUpDown"><i class="fa-solid fa-arrows-up-down"></i></button>  
             </div>  
           </div>  
           <div class="aspectRatio">  
             <p>Aspect Ratio</p>  
             <div class="btnWrapper">  
               <button class="optionBtnSqr">16:9</button>  
               <button class="optionBtnSqr">4:5</button>  
               <button class="optionBtnSqr">1:1</button>  
               <button class="optionBtnSqr">2:3</button>  
               <button class="optionBtnSqr">Free</button>  
             </div>  
           </div>  
           <div class="dragMode">  
             <p>Drag Mode</p>  
             <div class="btnWrapper">  
               <button class="optionBtn dragModeBtn"><i class="fa-solid fa-crop-simple"></i></button>  
               <button class="optionBtn dragModeBtn"><i class="fa-solid fa-arrows-up-down-left-right"></i></button>  
             </div>  
           </div>  
           <div class="controlCropper">  
             <p>Control Cropper</p>  
             <div class="btnWrapper">  
               <button class="optionBtn cropperClear"><i class="fa-solid fa-bars-staggered"></i></button>  
               <button class="optionBtn cropperCrop"><i class="fa-solid fa-crop-simple"></i></button>  
             </div>  
           </div>  
         </div>  
       </div>  
     </div>  
   </div>  
   <script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.js"></script>  
   <script src="script.js"></script>  
 </body>  
 </html>  


CSS Code

 @import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");  
 /* --------------------- Created By InCoder --------------------- */  
 * {  
  margin: 0;  
  padding: 0;  
  box-sizing: border-box;  
  font-family: "Poppins", sans-serif;  
 }  
 body {  
  height: 100vh;  
  background: linear-gradient(to top left, #000000e6, #404040) no-repeat;  
 }  
 /* width */  
 ::-webkit-scrollbar {  
  width: 5px;  
 }  
 /* Track */  
 ::-webkit-scrollbar-track {  
  background: transparent;  
 }  
 /* Handle */  
 ::-webkit-scrollbar-thumb {  
  border-radius: 5rem;  
  background: #d0d0ce45;  
 }  
 /* Handle on hover */  
 ::-webkit-scrollbar-thumb:hover {  
  background: #555;  
 }  
 .header {  
  top: 0;  
  left: 0;  
  width: 100vw;  
  height: 3rem;  
  display: flex;  
  position: fixed;  
  padding-left: 1.5rem;  
  padding-right: 1.5rem;  
  align-items: center;  
  background: #232323;  
  justify-content: space-between;  
 }  
 .header .title {  
  color: #ffffff;  
 }  
 .header .options .inBtn {  
  border: 0;  
  width: 3rem;  
  height: 3rem;  
  font-size: 1.2rem;  
  cursor: pointer;  
  color: #ffffff;  
  margin-right: 0.5rem;  
  background: transparent;  
 }  
 .header .options .inBtn:hover {  
  background-color: #5903d8;  
 }  
 .mainContainer {  
  height: 100%;  
  width: 100vw;  
  display: flex;  
  align-items: center;  
  justify-content: center;  
 }  
 .dragOrDropContainer {  
  width: 80%;  
  height: 80%;  
  display: flex;  
  flex-direction: column;  
  align-items: center;  
  justify-content: center;  
 }  
 .dragOrDropContainer.hide {  
  display: none;  
 }  
 .dragOrDropContainer .icon {  
  height: 6.5rem;  
  font-size: 5rem;  
  color: #ffffff;  
 }  
 .dragOrDropContainer .text {  
  color: #ffffff;  
  text-align: center;  
  font-size: clamp(1rem, 8vw, 2rem);  
 }  
 .dragOrDropContainer.drag .icon {  
  animation: upload 1s infinite linear alternate;  
 }  
 @keyframes upload {  
  0% {  
   transform: translateY(0rem);  
  }  
  100% {  
   transform: translateY(-1rem);  
  }  
 }  
 .editorOptions .sideBar {  
  top: 4rem;  
  width: 15rem;  
  height: 80vh;  
  right: -15rem;  
  position: fixed;  
  overflow-y: hidden;  
  background: #181818;  
  border-top-left-radius: 0.5rem;  
  border-bottom-left-radius: 0.5rem;  
  transition: right 0.5s cubic-bezier(0, 0.81, 0, 0.95);  
 }  
 .editorOptions .sideBar.active {  
  right: 0;  
 }  
 .editorOptions .sideBar.active .sidebarToggleBtn {  
  right: 15rem;  
 }  
 .editorOptions .sideBar:hover {  
  overflow-y: auto;  
 }  
 .editorOptions .sideBar .preview {  
  padding-top: 0.6rem;  
  padding-left: 1rem;  
  padding-bottom: 0.5rem;  
  border-bottom: 1px solid #ffffff2b;  
 }  
 .editorOptions .sideBar .preview p {  
  color: #ffffffc7;  
 }  
 .editorOptions .sideBar .previewImage {  
  width: 90%;  
  height: 8rem;  
  overflow: hidden;  
  border-radius: 0.2rem;  
  border: 2px dashed #ffffff4a;  
 }  
 .editorOptions .sideBar .options .zoom,  
 .editorOptions .sideBar .options .flip,  
 .editorOptions .sideBar .options .aspectRatio,  
 .editorOptions .sideBar .options .dragMode,  
 .editorOptions .sideBar .options .controlCropper,  
 .editorOptions .sideBar .options .rotate {  
  padding-bottom: 0.6rem;  
  border-bottom: 1px solid #ffffff14;  
 }  
 .editorOptions .sideBar .options .zoom p,  
 .editorOptions .sideBar .options .flip p,  
 .editorOptions .sideBar .options .dragMode p,  
 .editorOptions .sideBar .options .aspectRatio p,  
 .editorOptions .sideBar .options .controlCropper p,  
 .editorOptions .sideBar .options .rotate p {  
  font-size: 0.8rem;  
  padding-top: 0.6rem;  
  padding-left: 1rem;  
  color: #ffffffc7;  
 }  
 .optionBtn,  
 .optionBtnSqr {  
  border: 0;  
  width: 2.5rem;  
  height: 2.5rem;  
  cursor: pointer;  
  font-size: 1rem;  
  border-radius: 50%;  
  color: #ffffffc7;  
  margin-right: 1rem;  
  background: #ffffff0f;  
  transition: all 0.2s ease-in-out;  
 }  
 .optionBtnSqr {  
  width: 3rem;  
  margin-right: 0.5rem;  
  margin-bottom: 0.5rem;  
  height: 2rem !important;  
  font-size: 0.9rem !important;  
  border-radius: 0.5rem !important;  
 }  
 .optionBtnSqr:hover,  
 .optionBtnSqr.selected {  
  background: #ffffff1f;  
 }  
 .optionBtn:hover,  
 .optionBtn.selected {  
  background: #ffffff1f;  
 }  
 .btnWrapper {  
  width: 100%;  
  margin-top: 0.5rem;  
  padding-left: 1rem;  
 }  
 .sidebarToggleBtn {  
  right: 0;  
  top: 5rem;  
  border: 0;  
  width: 2rem;  
  height: 2.5rem;  
  cursor: pointer;  
  position: fixed;  
  color: #ffffff;  
  background: #0000004d;  
  border-top-left-radius: 0.5rem;  
  border-bottom-left-radius: 0.5rem;  
  transition: right 0.5s cubic-bezier(0, 0.81, 0, 0.95);  
 }  
 #imageWorkSpace {  
  max-width: 100%;  
  max-height: 100%;  
 }  
 .cropper-drag-box {  
  opacity: 1!important;  
  background-color: #00000080!important;  
 }  
 .outputDownloadBtn.hide {  
  display: none;  
 }  


Javascript Code

 // --------------------- Created By InCoder ---------------------  
 const openNewFile = document.querySelector('.openNewFile')  
 dragOrDropContainer = document.querySelector('.dragOrDropContainer')  
 dragBoxText = document.querySelector('.dragOrDropContainer .text')  
 fileInput = document.querySelector('.header .options input[type=file]')  
 sidebarToggleBtn = document.querySelector('.sidebarToggleBtn')  
 sideBar = document.querySelector('.sideBar')  
 outputDownloadBtn = document.querySelector('.outputDownloadBtn')  
 optionBtnSqr = document.querySelectorAll('.optionBtnSqr')  
 dragModeBtn = document.querySelectorAll('.dragModeBtn')  
 let file  
 openNewFile.addEventListener("click", () => {  
   fileInput.click()  
 })  
 fileInput.addEventListener('change', () => {  
   file = fileInput.files[0];  
   uploadFile()  
 })  
 const uploadFile = () => {  
   let fileType = file.type;  
   dragOrDropContainer.style.cursor = 'progress'  
   dragBoxText.innerText = 'Uploading file, Please Wait...'  
   let validExt = ["image/jpeg", "image/jpg", "image/png"];  
   if (validExt.includes(fileType)) {  
     let p = new Promise((resolve, reject) => {  
       let fileReader = new FileReader()  
       fileReader.onload = () => {  
         let fileURL = fileReader.result  
         let imageTag = `<img src="${fileURL}" id="imageWorkSpace" alt="image">`  
         dragOrDropContainer.innerHTML = imageTag  
         dragOrDropContainer.style.cursor = 'auto'  
         outputDownloadBtn.classList.remove('hide')  
         resolve(true)  
       }  
       fileReader.readAsDataURL(file)  
     }).then(() => {  
       let options = {  
         dargMode: "move",  
         preview: ".previewImage",  
         viewMode: 2,  
         modal: false,  
         background: false,  
         ready: () => {  
           // Zoom Image  
           document.querySelector('.zoomIn').onclick = () => cropper.zoom(0.1)  
           document.querySelector('.zoomOut').onclick = () => cropper.zoom(-0.1)  
           // Rotate Image  
           document.querySelector('.rotateLeft').onclick = () => cropper.rotate(90)  
           document.querySelector('.rotateRight').onclick = () => cropper.rotate(-90)  
           // Flip Image  
           let flipX = -1  
           flipY = -1  
           document.querySelector('.flipLeftRight').onclick = () => {  
             cropper.scale(flipX, 1)  
             flipX = -flipX  
           }  
           document.querySelector('.flipUpDown').onclick = () => {  
             cropper.scale(1, flipY)  
             flipY = -flipY  
           }  
           // set Aspect Ratio  
           optionBtnSqr[0].onclick = () => cropper.setAspectRatio(1.7777777777777777)  
           optionBtnSqr[1].onclick = () => cropper.setAspectRatio(1.4444444444444444)  
           optionBtnSqr[2].onclick = () => cropper.setAspectRatio(1)  
           optionBtnSqr[3].onclick = () => cropper.setAspectRatio(0.6666666666666666)  
           optionBtnSqr[4].onclick = () => cropper.setAspectRatio(0)  
           // Cropper Control  
           document.querySelector('.cropperClear').onclick = () => cropper.clear()  
           document.querySelector('.cropperCrop').onclick = () => cropper.crop()  
           // Drag Mode  
           dragModeBtn[0].onclick = () => {  
             dragModeBtn[0].classList.remove('selected')  
             dragModeBtn[0].classList.toggle('selected')  
             cropper.setDragMode("crop")  
           }  
           dragModeBtn[1].onclick = () => {  
             dragModeBtn[0].classList.remove('selected')  
             dragModeBtn[1].classList.toggle('selected')  
             cropper.setDragMode("move")  
           }  
           // download Image  
           outputDownloadBtn.onclick = () => {  
             outputDownloadBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i>'  
             setTimeout(() => {  
               cropper.getCroppedCanvas().toBlob((blob) => {  
                 let downloadURL = window.URL.createObjectURL(blob)  
                 let a = document.createElement('a')  
                 a.href = downloadURL  
                 a.download = `output-${Date.now()}.jpg`  
                 a.click()  
                 outputDownloadBtn.innerHTML = '<i class="fa-solid fa-download"></i>'   
               })  
             }, 2000)  
           }  
         }  
       }  
       let imageWorkSpace = document.querySelector('.dragOrDropContainer #imageWorkSpace')  
       let cropper = new Cropper(imageWorkSpace, options)  
     })  
   } else {  
     dragOrDropContainer.classList.remove("hide")  
     dragOrDropContainer.classList.remove("drag")  
     dragBoxText.innerText = "Drag & Drop to Upload File"  
     alert("This File is nat valid. Please choose another file and try again.")  
   }  
 }  
 sidebarToggleBtn.addEventListener("click", () => {  
   sideBar.classList.toggle('active')  
   if (sideBar.classList.contains('active')) {  
     sidebarToggleBtn.querySelector('i').classList.remove('fa-chevron-left')  
     sidebarToggleBtn.querySelector('i').classList.add('fa-chevron-right')  
   } else {  
     sidebarToggleBtn.querySelector('i').classList.remove('fa-chevron-right')  
     sidebarToggleBtn.querySelector('i').classList.add('fa-chevron-left')  
   }  
 })  
 dragOrDropContainer.addEventListener('dragover', (e) => {  
   e.preventDefault()  
   dragOrDropContainer.classList.add('drag')  
   dragBoxText.innerText = 'Release to Upload File'  
 })  
 dragOrDropContainer.addEventListener('dragleave', (e) => {  
   e.preventDefault()  
   dragOrDropContainer.classList.remove('drag')  
   dragBoxText.innerText = 'Drag & Drop to Upload File'  
 })  
 dragOrDropContainer.addEventListener('drop', (e) => {  
   e.preventDefault()  
   file = e.dataTransfer.files[0];  
   uploadFile()  
 })  


Here is the Final Output of this Code

Hurray! now you've created a Gradient Color Generator. You can download files by clicking on the download button after downloading file if you are facing any kind of problem feel free to ask me in the comment section and you can also contact me via e-mail. Thanks for giving your precious time for reading this blog. Here is the download button:-

Zip File's Password = InCoderWeb

2 Comments

  1. Hello, thank you very much. Great tool for editing images. One question: Is it possible to easily integrate canvas filters? I am thinking here of: Brightness, Contrast, Saturate and Greyscale. Can you perhaps give me a tip on how I could implement this?

    Many thanks and best regards

    ReplyDelete
    Replies
    1. Thank you, for your valuable comment. I'll try to implement these(Brightness, Contrast, Saturate and Greyscale) options in this. 😊

      Delete
Previous Post Next Post