Today, I went through the implementation and functionality of a simple yet powerful image editor built with HTML, CSS, and JavaScript. The editor allows users to apply basic filters, rotate, and flip an image. It also supports loading an image from the user's device and saving the edited image.
The HTML structure is divided into several key sections: the filter options, rotation and flip options, an image preview area, and control buttons.
<div class="container disable"> <h2>Easy Image Editor</h2> <div class="wrapper"> <div class="editor-panel"> <!-- Filters Section --> <div class="filter"> <label class="title">Filters</label> <div class="options"> <button id="brightness" class="active">Brightness</button> <button id="saturation">Saturation</button> <button id="inversion">Inversion</button> <button id="grayscale">Grayscale</button> </div> <!-- Slider for Filter Adjustments --> <div class="slider"> <div class="filter-info"> <p class="name">Brighteness</p> <p class="value">100%</p> </div> <input type="range" value="100" min="0" max="200"> </div> </div> <!-- Rotate & Flip Section --> <div class="rotate"> <label class="title">Rotate & Flip</label> <div class="options"> <button id="left"><i class="fa-solid fa-rotate-left"></i></button> <button id="right"><i class="fa-solid fa-rotate-right"></i></button> <button id="horizontal"><i class="bx bx-reflect-vertical"></i></button> <button id="vertical"><i class="bx bx-reflect-horizontal"></i></button> </div> </div> </div> <!-- Image Preview Section --> <div class="Easy Image Editor: Tutorial and Documentation"> <img src="image-placeholder.svg" alt="Easy Image Editor: Tutorial and Documentation"> </div> </div> <!-- Controls Section --> <div class="controls"> <button class="reset-filter">Reset Filters</button> <div class="row"> <input type="file" class="file-input" accept="image/*" hidden> <button class="choose-img">Choose Image</button> <button class="save-img">Save Image</button> </div> </div> </div>
The JavaScript code handles the logic behind loading an image, applying filters, rotating and flipping the image, and saving the edited image.
const fileInput = document.querySelector(".file-input"), filterOptions = document.querySelectorAll(".filter button"), filterName = document.querySelector(".filter-info .name"), filterValue = document.querySelector(".filter-info .value"), filterSlider = document.querySelector(".slider input"), rotateOptions = document.querySelectorAll(".rotate button"), previewImg = document.querySelector(".Easy Image Editor: Tutorial and Documentation img"), resetFilterBtn = document.querySelector(".reset-filter"), chooseImgBtn = document.querySelector(".choose-img"), saveImgBtn = document.querySelector(".save-img"); let brightness = "100", saturation = "100", inversion = "0", grayscale = "0"; let rotate = 0, flipHorizontal = 1, flipVertical = 1;
const loadImage = () => { let file = fileInput.files[0]; if(!file) return; previewImg.src = URL.createObjectURL(file); previewImg.addEventListener("load", () => { resetFilterBtn.click(); // Reset filters when a new image is loaded document.querySelector(".container").classList.remove("disable"); }); }
const applyFilter = () => { previewImg.style.transform = `rotate(${rotate}deg) scale(${flipHorizontal}, ${flipVertical})`; previewImg.style.filter = `brightness(${brightness}%) saturate(${saturation}%) invert(${inversion}%) grayscale(${grayscale}%)`; }
filterOptions.forEach(option => { option.addEventListener("click", () => { document.querySelector(".active").classList.remove("active"); option.classList.add("active"); filterName.innerText = option.innerText; if(option.id === "brightness") { filterSlider.max = "200"; filterSlider.value = brightness; filterValue.innerText = `${brightness}%`; } else if(option.id === "saturation") { filterSlider.max = "200"; filterSlider.value = saturation; filterValue.innerText = `${saturation}%` } else if(option.id === "inversion") { filterSlider.max = "100"; filterSlider.value = inversion; filterValue.innerText = `${inversion}%`; } else { filterSlider.max = "100"; filterSlider.value = grayscale; filterValue.innerText = `${grayscale}%`; } }); }); const updateFilter = () => { filterValue.innerText = `${filterSlider.value}%`; const selectedFilter = document.querySelector(".filter .active"); if(selectedFilter.id === "brightness") { brightness = filterSlider.value; } else if(selectedFilter.id === "saturation") { saturation = filterSlider.value; } else if(selectedFilter.id === "inversion") { inversion = filterSlider.value; } else { grayscale = filterSlider.value; } applyFilter(); }
rotateOptions.forEach(option => { option.addEventListener("click", () => { if(option.id === "left") { rotate -= 90; } else if(option.id === "right") { rotate += 90; } else if(option.id === "horizontal") { flipHorizontal = flipHorizontal === 1 ? -1 : 1; } else { flipVertical = flipVertical === 1 ? -1 : 1; } applyFilter(); }); });
const resetFilter = () => { brightness = "100"; saturation = "100"; inversion = "0"; grayscale = "0"; rotate = 0; flipHorizontal = 1; flipVertical = 1; filterOptions[0].click(); applyFilter(); }
const saveImage = () => { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); canvas.width = previewImg.naturalWidth; canvas.height = previewImg.naturalHeight; ctx.filter = `brightness(${brightness}%) saturate(${saturation}%) invert(${inversion}%) grayscale(${grayscale}%)`; ctx.translate(canvas.width / 2, canvas.height / 2); if(rotate !== 0) { ctx.rotate(rotate * Math.PI / 180); } ctx.scale(flipHorizontal, flipVertical); ctx.drawImage(previewImg, -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height); const link = document.createElement("a"); link.download = "image.jpg"; link.href = canvas.toDataURL(); link.click(); }
filterSlider.addEventListener("input", updateFilter); resetFilterBtn.addEventListener("click", resetFilter); saveImgBtn.addEventListener("click", saveImage); fileInput.addEventListener("change", loadImage); chooseImgBtn.addEventListener("click", () => fileInput.click());
the slider.
This simple image editor provides essential tools to modify and enhance images. The structure is designed to be easy to understand and extendable, allowing for the addition of more features like additional filters or advanced editing tools. Thanks for reading. Unto the next…
Check it out here
https://app.marvelly.com.ng/100daysofMiva/day-5/
Source code
https://github.com/Marvellye/100daysofMiva/tree/main/Projects/Day_5-Image-Editor
The above is the detailed content of Easy Image Editor: Tutorial and Documentation. For more information, please follow other related articles on the PHP Chinese website!