How to Split an Image Into Pieces Using JavaScript
In this Javascript Tutorial, we will see how to create a responsive Image Slicer web application using pure HTML, CSS, and JavaScript.
When a user selects an image and specifies the number of slices, our JavaScript handles all the functionality including file reading, image processing, and dynamic grid generation.
Project Source Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"> <!-- Set character encoding -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Slicer</title>
<style>
:root{
--primary-color:#3498db;
--secondary-color:#2ecc71;
--background-color:#f4f6f8;
--text-color:#2c3e50;
--card-background:#fff;
--slice-background:#ecf0f1;
--input-background:#e0e5ec;
--shadow-color:rgba(0,0,0,0.1);
}
*{ box-sizing:border-box; margin: 0; padding: 0; }
body{
font-family: 'Courier New', Courier, monospace;
background-color: var(--background-color);
color: var(--text-color);
display: flex; justify-content: center;
align-items: center;
min-height: 100vh; padding: 20px;
}
.container{
background-color: var(--card-background);
padding: 40px; border-radius: 20px;
box-shadow: 0 10px 30px var(--shadow-color);
max-width: 800px; width: 100%;
text-align: center;
}
h1{
margin-bottom: 30px; font-size: 36px; font-weight: 700;
color: var(--primary-color);
}
.file-input-wrapper{
position: relative; display: inline-block;
margin-bottom: 30px
}
.file-input-wrapper input[type="file"]{
position: absolute; left: -9999px;
}
.file-input-wrapper label{
display: inline-block; padding: 12px 24px;
color: #fff; background-color: var(--primary-color);
font-size: 16px; font-weight: 600;
border-radius: 30px; cursor: pointer;
transition: all 0.3s ease;
}
.file-input-wrapper label:hover{
background-color: var(--secondary-color);
transform: translateY(-2px);
box-shadow: 0 4px 10px var(--secondary-color);
}
.slice-input{
display: flex; justify-content: center;
align-items: center; margin-bottom: 30px;
}
.slice-input label{
margin-right: 15px; font-weight: 600; font-size: 18px;
}
.slice-input input{
width: 80px; padding: 10px; border: none; border-radius: 15px;
background-color: var(--input-background);
color: var(--text-color); font-size: 18px;
text-align: center; transition: all 0.3s ease;
}
.slice-input input:focus{
outline: none; box-shadow: 0 0 0 2px var(--primary-color);
}
.slice-container{
display: grid; grid-gap: 5px; margin-top: 30px;
}
.slice{
position: relative; border-radius: 5px;
background-color: var(--slice-background);
box-shadow: 0 4px 10px var(--shadow-color);
overflow: hidden; transition: all 0.3s ease;
}
.slice img{
width: 100%; height: auto; object-fit: cover; display: block;
}
@keyframes fadeInUp{
from{ opacity: 0; transform: translateY(20px); }
to{ opacity: 1; transform: translateY(0); }
}
.slice{ animation: fadeInUp 0.5s ease forwards; }
</style>
</head>
<body>
<div class="container">
<h1>Image Slicer</h1>
<div class="file-input-wrapper">
<input type="file" id="fileInput" accept="image/*">
<label for="fileInput">Choose an image</label>
</div>
<div class="slice-input">
<label for="sliceNumber">Slices:</label>
<input type="number" id="sliceNumber" min="2" max="100" value="4">
</div>
<div class="slice-container" id="sliceContainer"></div>
</div>
<script>
// Get DOM elements
const fileInput = document.getElementById('fileInput');
const sliceNumber = document.getElementById('sliceNumber');
const sliceContainer = document.getElementById('sliceContainer');
let currentImage = null;
// Add event listeners to handle user interactions
fileInput.addEventListener("change", handleFileUpload);
fileInput.addEventListener("change", handleSliceNumberChange);
sliceNumber.addEventListener("change", handleSliceNumberChange);
/**
* Handles the file upload and slicing process
* @param {Event} event - The change event from the file input
*/
function handleFileUpload(event){
// Gets the first uploaded file
const file = event.target.files[0];
if(file){
// Creates a new FileReader to read the file
const reader = new FileReader();
// Executes when file reading is complete
reader.onload = function(e){
// Creates a new Image object
const img = new Image();
// Sets the image source to the loaded file
img.src = e.target.result;
// Executes when the image is fully loaded
img.onload = function(){
// Stores the loaded image for later use
currentImage = img;
// Calls function to slice the image based on the input value
sliceImage(img, parseInt(sliceNumber.value));
}
}
reader.readAsDataURL(file);
}
}
/**
* Handles changes in the number of slices
*/
function handleSliceNumberChange(){
// Checks if there is a currently loaded image
if(currentImage){
// Re-slices the current image based on the new number
sliceImage(currentImage, parseInt(sliceNumber.value));
}
}
/**
* Slices the image into a grid of smaller images
* @param {Image} image - The image to be sliced
* @param {number} slices - The number of slices per side (e.g., 4 for a 4x4 grid)
*/
function sliceImage(image, slices){
// Clears previous slices from the container
sliceContainer.innerHTML = '';
// Sets up the grid layout for the slices
sliceContainer.style.gridTemplateColumns = `repeat(${slices}, 1fr)`;
// Creates a new canvas element to draw slices
const canvas = document.createElement('canvas');
// Gets the 2D drawing context for the canvas
const ctx = canvas.getContext('2d');
// Calculates the width of each slice
const sliceWidth = image.width / slices;
// Calculates the height of each slice
const sliceHeight = image.height / slices;
// Sets the canvas width to the slice width
canvas.width = sliceWidth;
// Sets the canvas height to the slice height
canvas.height = sliceHeight;
// Loop through each row and column to create individual slices
for(let row = 0; row < slices; row++){
for(let col = 0; col < slices; col++){
// Clears the canvas for the next slice
ctx.clearRect(0, 0, sliceWidth, sliceHeight);
// Draws the current slice from the original image onto the canvas
ctx.drawImage(image, col * sliceWidth, row * sliceHeight,
sliceWidth, sliceHeight, 0, 0, sliceWidth, sliceHeight);
// Creates an image element for the slice
const sliceImage = document.createElement('img');
// Converts the canvas to a Data URL and sets it as the image source
sliceImage.src = canvas.toDataURL();
// Creates a div to hold the slice image
const sliceDiv = document.createElement('div');
// Assigns the 'slice' class for styling
sliceDiv.className = 'slice';
// Sets a delay for each slice's animation for a staggered effect
sliceDiv.style.animationDelay = `${(row * slices + col) * 0.05}s`;
// Appends the image to the slice div
sliceDiv.appendChild(sliceImage);
// Appends the slice div to the main slice container
sliceContainer.appendChild(sliceDiv);
}
}
}
</script>
</body>
</html>
OUTPUT: