Skip to content

Instantly share code, notes, and snippets.

@MohammadTaseenKhan
Created February 6, 2022 06:20
Show Gist options
  • Save MohammadTaseenKhan/09bce63cfbc03e4298ead7cb8065210a to your computer and use it in GitHub Desktop.
Save MohammadTaseenKhan/09bce63cfbc03e4298ead7cb8065210a to your computer and use it in GitHub Desktop.
Image Upload Editor

Image Upload Editor

Sometime you need a small image editor in your website while uploading profile pic that needs re-size or cropping . This small editor solves this problem. On clicking open editor button, a image editor opens. Editor asks for an image, and then you can re-size,crop and download the same. It also has an optional feature to submit the edited image to server.

A Pen by Mofid Ansari on CodePen.

License.

<!-- Main Wrapper -->
<div class="wrapper">
<!-- Open Modal Button -->
<div class="change-icon"><a href="#" data-toggle='modal' data-target='#image-editor'><span class="change-icon-text">Open Editor</span><span class="icon-container"><i class="fa fa-picture-o"></i><i class="fa fa-crop"></i><i class="fa fa-download"></i></span></a></div>
<!-- Editor Modal-->
<div id="image-editor" class="modal fade editor-modal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h2 class="modal-title">Edit Your Image</h2>
</div>
<div class="modal-body">
<div class="editor-wrapper">
<div class="editor-container">
<div class="editor">
<div class="resize-container">
<span class="resize-handle resize-handle-nw"></span>
<span class="resize-handle resize-handle-ne"></span>
<img class="resize-image" src="" alt="">
<span class="resize-handle resize-handle-se"></span>
<span class="resize-handle resize-handle-sw"></span>
</div>
<div class="overlay">
<div class="overlay-inner"></div>
</div>
<div class="overlay overlay-preview">
<div class="overlay-inner"></div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="upload">
<form action="#" method="POST" role="form">
<input type="file" acccept="images/" class="form-control" id="uploaded-img" placeholder="Input field" accept="image/*">
<div class="upload-button">
<label for="uploaded-img">
<span class="label-text">Choose an Image</span><span class="upload-icon"><i class="fa fa-upload"></i></span>
</label>
</div>
<div class="edit-button">
<button class="btn form-control preview-crop">Preview</button>
<button type="submit" class="js-crop btn form-control" data-dismiss="modal">Download</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- Reference -->
<cite class="reference">Code Reference from <a href="https://tympanus.net/codrops/2014/10/30/resizing-cropping-images-canvas/" title="ref">Codrops</a></cite>
</div>
$('document').ready(function () {
// Resizes and crops image
var resizableImage = function (image_target_init) {
var $container,
$orig_src = new Image(),
image_target = $(image_target_init).get(0),
$event_state = {},
$constrain = true,
$min_width = 350,
$min_height = 350,
$max_width = 1200,
$max_height = 1200,
$intial_width = 450,
$intial_height = 450,
$resize_canvas = document.createElement('canvas');
// Wraps the image into container and adds Handles and intial calls for action
init = function () {
$orig_src.src = image_target.src;
initialResize();
$container = $(image_target).parent('.resize-container');
if (!$container.hasClass("resizing-the-image")) {
$container.addClass("resizing-the-image");
$container.on('mousedown touchstart', '.resize-handle', startResize);
$container.on('mousedown touchstart', 'img', startMoving);
$('.js-crop').on('click', crop);
}
};
// Resizing Before Loading
initialResize = function () {
var height, width;
if (image_target.height > $intial_height && image_target.width > $intial_width) {
height = $intial_height;
width = height * (image_target.width / image_target.height);
if (width < $min_width) {
width = $intial_width;
height = width * (image_target.height / image_target.width);
}
resizeImage(width, height);
} else if (image_target.height > $intial_height) {
height = $intial_height;
width = height * (image_target.width / image_target.height);
if (width < $min_width) {
width = $intial_width;
height = width * (image_target.height / image_target.width);
}
resizeImage(width, height);
} else if (image_target.width > $intial_width) {
width = $intial_width;
height = width * (image_target.height / image_target.width);
if (height < $min_height) {
height = $intial_height;
width = height * (image_target.width / image_target.height);
}
resizeImage(width, height);
}
};
// Starts the Resizing Process
startResize = function (e) {
console.log("start resize");
e.preventDefault();
e.stopPropagation();
saveEventState(e);
$(document).on('mousemove touchmove', resizing);
$(document).on('mouseup touchend', endResize);
};
// Stops The Resizing Process
endResize = function (e) {
console.log("end Resize");
e.preventDefault();
$(document).off('mouseup touchend', endResize);
$(document).off('mousemove touchmove', resizing);
};
// saving current Event State
saveEventState = function (e) {
$event_state.container_width = $container.width();
$event_state.container_height = $container.height();
$event_state.container_left = $container.offset().left;
$event_state.container_top = $container.offset().top;
$event_state.mouse_x = (e.clientX || e.pageX || e.originalEvent.touches[0].clientX) + $(window).scrollLeft();
$event_state.mouse_y = (e.clientY || e.pageY || e.originalEvent.touches[0].clientY) + $(window).scrollTop();
$event_state.evnt = e;
};
// Actual resizing
resizing = function (e) {
var mouse = {},
width,
height, left, top,
offset = $container.offset();
mouse.x = (e.clientX || e.pageX || e.originalEvent.touches[0].clientX) + $(window).scrollLeft();
mouse.y = (e.clientY || e.pageY || e.originalEvent.touches[0].clientY) + $(window).scrollTop();
if ($($event_state.evnt.target).hasClass('resize-handle-se')) {
width = mouse.x - $event_state.container_left;
height = mouse.y - $event_state.container_top;
left = $event_state.container_left;
top = $event_state.container_top;
console.log("se");
} else if ($($event_state.evnt.target).hasClass('resize-handle-sw')) {
width = $event_state.container_width - (mouse.x - $event_state.container_left);
height = mouse.y - $event_state.container_top;
left = mouse.x;
top = $event_state.container_top;
console.log("sw");
} else if ($($event_state.evnt.target).hasClass('resize-handle-nw')) {
width = $event_state.container_width - (mouse.x - $event_state.container_left);
height = $event_state.container_height - (mouse.y - $event_state.container_top);
left = mouse.x;
top = mouse.y;
if ($constrain || e.shiftKey) {
top = mouse.y - ((width / $orig_src.width * $orig_src.height) - height);
}
console.log("nw");
} else if ($($event_state.evnt.target).hasClass('resize-handle-ne')) {
width = mouse.x - $event_state.container_left;
height = $event_state.container_height - (mouse.y - $event_state.container_top);
left = $event_state.container_left;
top = mouse.y;
if ($constrain || e.shiftKey) {
top = mouse.y - ((width / $orig_src.width * $orig_src.height) - height);
}
console.log("ne");
}
if ($constrain || e.shiftKey) {
height = width / $orig_src.width * $orig_src.height;
}
// console.log(width+','+height);
if (width > $min_width && height > $min_height && width < $max_width && height < $max_height) {
resizeImage(width, height);
console.log(height, width);
$container.offset({
'left': left,
'top': top
});
}
};
// Saving The Image after resizing
resizeImage = function (width, height) {
$resize_canvas.width = width;
$resize_canvas.height = height;
$resize_canvas.getContext('2d').drawImage($orig_src, 0, 0, width, height);
$(image_target).attr('src', $resize_canvas.toDataURL("image/png"));
};
// starts moving the image
startMoving = function (e) {
e.preventDefault();
e.stopPropagation();
saveEventState(e);
$(document).on('mousemove touchmove', moving);
$(document).on('mouseup touchend', endMoving);
console.log("Move");
};
// Stops moving the image
endMoving = function (e) {
e.preventDefault();
$(document).off('mouseup touchend', endMoving);
$(document).off('mousemove touchmove', moving);
};
// Actual Moving
moving = function (e) {
var mouse = {};
e.preventDefault();
e.stopPropagation();
mouse.x = (e.clientX || e.pageX) + $(window).scrollLeft();
mouse.y = (e.clientY || e.pageY) + $(window).scrollTop();
$container.offset({
'left': mouse.x - ($event_state.mouse_x - $event_state.container_left),
'top': mouse.y - ($event_state.mouse_y - $event_state.container_top)
});
};
// Croping image and saving it
crop = function (e) {
e.preventDefault();
var crop_canvas,
left = $('.overlay').offset().left - $container.offset().left,
top = $('.overlay').offset().top - $container.offset().top,
width = $('.overlay').width(),
height = $('.overlay').height();
crop_canvas = document.createElement('canvas');
crop_canvas.width = width;
crop_canvas.height = height;
crop_canvas.getContext('2d').drawImage(image_target, left, top, width, height, 0, 0, width, height);
$('.editor-modal').removeClass('editing-Image');
window.open(crop_canvas.toDataURL("image/png"));
// postImage();
};
// optional:posts the cropped image to server
/* function postImage() {
var $img = $('.pic img').attr('src');
console.log("Before:" + $img.length);
$.post('API/upload_pic.php', {
'img': $img
}, function (data) {
console.log("After:" + data);
$('.overlay-preview').fadeOut(50);
})
}*/
// Initial call
init();
};
// Loading Uploaded Image
function loaduploadedImage($image) {
if ($image.files && $image.files[0]) {
$imageFile = new Image();
$imageFile.onload = function () {
var $this = this;
var height, width;
// To check for Image of low resolution
if ($this.height < 350 || $this.width < 350) {
alert("Image should be greater than 350px*350px");
return;
}
$('.editor-modal').addClass('editing-Image');
$('.resize-image').attr('src', $this.src);
resizableImage($('.resize-image'));
};
var reader = new FileReader();
$imageFile.src = window.URL.createObjectURL($image.files[0]);
}
}
// Validation For Image
function isImage(file) {
var name, extension, $file = $(file);
if (file.files) {
name = $file.val().toLowerCase();
extension = name.substring(name.lastIndexOf('.'));
if (['.png', '.jpeg', '.gif', '.jpg', '.bmp'].indexOf(extension) >= 0) {
console.log("Valid image file");
return 1;
}
alert("Not a Valid Image file");
return 0;
}
}
// Preview the Edited Image;
$('.preview-crop').on('click', function (e) {
e.preventDefault();
e.stopPropagation();
var $this = $(this);
if (!$this.hasClass('preview')) {
$this.addClass('preview');
$this.text("Cancel Preview");
$('.overlay-preview').fadeIn(100);
} else {
$this.removeClass('preview');
$this.text("Preview");
$('.overlay-preview').fadeOut(50);
}
});
// Event Triggers on file upload
$('body').on('change', '#uploaded-img', function () {
var $this = this;
if (isImage($this)) {
loaduploadedImage($this);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
%vertical_align {
justify-content: center;
align-items: center;
}
$primary_color: rgb(244, 67, 54);
html,body{
height: 100%;
width: 100%;
.wrapper{
display: flex;
@extend %vertical_align;
height: 100%;
}
}
.editor-wrapper {
display: flex;
justify-content: center;
.editor-container {
display: flex;
flex-direction: column;
.editor {
text-align: center;
display: block;
width: 500px;
height: 500px;
line-height: 500px;
position: relative;
.resize-container {
position: relative;
display: inline-flex;
cursor: move;
margin: 0 auto;
line-height: normal;
vertical-align: middle;
img {
display: block;
}
&:hover,
&:active {
img {
outline: 2px dashed $primary_color;
}
}
}
}
}
}
.upload {
display: flex;
background-color: $primary_color;
color: white;
padding: 20px;
form {
@extend %vertical_align;
display: flex;
justify-content: space-between;
width: 100%;
input {
display: none;
}
.edit-button {
display: none;
}
button {
border: 0;
padding: 10px 15px;
box-sizing: content-box;
width: auto;
height: auto;
border-radius: 0;
color: $primary_color;
font-weight: bold;
}
.upload-button {
label {
cursor: pointer;
}
.upload-icon {
display: inline-block;
background-color: $primary-color;
color: white;
border: 2px solid white;
padding: 8px 12px;
}
.label-text {
display: inline-block;
color: $primary_color;
background-color: white;
padding: 10px 15px;
margin: 0;
&:hover {
color: #333;
}
}
}
}
}
%extend_1 {
position: absolute;
display: block;
width: 10px;
height: 10px;
background: $primary_color;
z-index: 999;
}
.resize-handle-nw {
@extend %extend_1;
top: -5px;
left: -5px;
cursor: nw-resize;
}
.resize-handle-sw {
@extend %extend_1;
bottom: -5px;
left: -5px;
cursor: sw-resize;
}
.resize-handle-ne {
@extend %extend_1;
top: -5px;
right: -5px;
cursor: ne-resize;
}
.resize-handle-se {
@extend %extend_1;
bottom: -5px;
right: -5px;
cursor: se-resize;
}
$overlay_height: 350px;
$overlay_width: 350px;
.overlay {
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
z-index: 999;
width: $overlay_width;
height: $overlay_height;
border: solid 2px rgba(222, 60, 80, 0.9);
box-sizing: content-box;
pointer-events: none;
vertical-align: middle;
display: inline-block;
&:after,
&:before {
content: '';
position: absolute;
display: block;
width: $overlay_width+4px;
height: $overlay_height/5;
border-left: dashed 2px rgba(222, 60, 80, 0.9);
border-right: dashed 2px rgba(222, 60, 80, 0.9);
box-sizing: border-box;
}
&:before {
top: 0;
margin-left: -2px;
margin-top: -40px;
}
&:after {
bottom: 0;
margin-left: -2px;
margin-bottom: -40px;
}
}
.overlay-inner {
&:after,
&:before {
content: '';
position: absolute;
display: block;
width: $overlay_width/4;
height: $overlay_height + 4px;
border-top: dashed 2px rgba(222, 60, 80, 0.9);
border-bottom: dashed 2px rgba(222, 60, 80, 0.9);
box-sizing: border-box;
}
&:before {
left: 0;
margin-left: -40px;
margin-top: -2px;
}
&:after {
right: 0;
margin-right: -40px;
margin-top: -2px;
}
}
.overlay-preview {
display: none;
border: 0;
&:before,
&:after {
height: 90px;
background-color: white;
border: 0;
left: -150px;
width: 650px;
z-index: 9999;
}
&:before {
margin-top: -90px;
}
&:after {
margin-bottom: -90px;
}
.overlay-inner {
&:before,
&:after {
background-color: white;
border: 0;
width: 150px;
z-index: 9999;
}
&:before {
margin-left: -150px;
}
&:after {
margin-right: -150px;
}
}
}
.editor-modal {
.modal-header {
display: none;
text-align: center;
background-color: $primary-color;
color: white;
border-bottom: 0;
.close {
color: white;
opacity: 0.8;
}
.close:focus,
.close:hover {
color: white;
opacity: 1;
}
}
.modal-body {
display: none;
border: 2px solid $primary_color;
border-top: 0;
border-bottom: 0;
overflow: hidden;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAACgAgMAAADm7QMnAAAADFBMVEWIiIixsbGxsbGxsbF0SLUbAAAABHRSTlP/bytS3QghxwAAAEVJREFUeAFjYA3FAA4Mq17tWrcalVhBtOBK7IL/McFf4rUPZYtGLRq1aNSiUYtGLSJcoYzWR4PBolGLRi0atWjUotH6CAA67a9q5+gpSAAAAABJRU5ErkJggg==");
}
.modal-footer {
padding: 0;
border: 0;
}
}
.editing-Image {
&.editor-modal {
.modal-header {
display: block;
}
.modal-body {
display: block;
}
}
.upload {
form {
.edit-button {
display: block;
}
}
}
}
.btn.active.focus,
.btn.focus,
.btn:active.focus,
.btn:focus,
.btn:active:focus {
outline: transparent;
}
.btn.active.focus,
.btn.focus,
.btn:active.focus,
.btn:focus,
.btn:active:focus,
{
outline: transparent;
background-color: whitesmoke;
}
.change-icon{
a{
&:hover{
opacity: 0.90;
}
display: flex;
flex-direction:column-reverse;
text-decoration: none;
border-radius: 5px;
.change-icon-text{
padding: 17px 30px;
background-color: $primary_color;
color: white;
border-radius: 0 0 10px 10px;
}
.icon-container{
display: flex;
justify-content: space-around;
border: 3px solid $primary_color;
padding: 20px 20px;
color:$primary_color;
background-color: white;
border-radius: 10px 10px 0 0;
}
}
}
.reference{
right: 10px;
bottom: 10px;
position: absolute;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment