
<!DOCTYPE html>
Select Areas Demo
.jcrop-selection {
background: rgba(255, 255, 0, 0.3);
/* Yellow highlight for the selection */
border: 1px dashed #999;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-jcrop/0.9.15/js/jquery.Jcrop.min.js"></script>
Save Selected Areas
Toggle Deselect Mode
<script>
jQuery(document).ready(function () {
var jcropApi;
var selectedAreas = []; // Array to store selected areas
var deselectModeActive = false; // Flag to indicate deselect mode
// Initialize Jcrop with multi-selection enabled
jQuery('#selectableImage').Jcrop({
multi: true,
onSelect: function (coords) {
// Handle selection based on deselect mode
if (deselectModeActive) {
removePart(coords);
} else {
selectedAreas.push(coords);
console.log('Selected areas:', selectedAreas);
drawOverlay(coords);
}
}
}, function () {
jcropApi = this;
});
// Save selected areas when the button is clicked
jQuery('#saveAreas').on('click', function () {
// Check if any area is selected
if (selectedAreas.length === 0) {
alert('No areas selected!');
return;
}
// Create an array to store base64 strings and area information for each area
var dataToSend = [];
var mainImage = jQuery('#selectableImage').attr('src').split('/').pop();
// Process each selected area
for (var i = 0; i < selectedAreas.length; i++) {
var area = selectedAreas[i];
// Create a new canvas for each selected area
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// Load the image
var image = new Image();
image.src = jQuery('#selectableImage').attr('src');
// Set canvas dimensions to match the selected area
canvas.width = area.w;
canvas.height = area.h;
// Draw the selected area on the canvas
ctx.drawImage(image, area.x, area.y, area.w, area.h, 0, 0, area.w, area.h);
// Convert canvas content to base64 string
var base64String = canvas.toDataURL('image/png');
// Store base64 string and area information in an object
var areaData = {
base64String: base64String,
area: area,
mainImg: mainImage
};
// Push the object to the data array
dataToSend.push(areaData);
}
// Send all base64 strings and area information to the server
jQuery.ajax({
type: 'POST',
url: 'http://localhost/snap-news/save.php',
contentType: 'application/json', // Set content type to JSON
data: JSON.stringify({ areas: dataToSend }), // Convert data to JSON string
success: function (response) {
console.log(response);
alert('Selected areas saved successfully!');
},
error: function (error) {
console.error(error);
alert('Error saving selected areas!');
}
});
});
// Toggle deselect mode when the button is clicked
jQuery('#toggleDeselectMode').on('click', function () {
deselectModeActive = !deselectModeActive;
if (deselectModeActive) {
alert('Deselect mode is ON. Click on selected areas to remove parts.');
} else {
alert('Deselect mode is OFF. Normal selection mode is active.');
}
});
function drawOverlay(coords) {
// Create a new div for the overlay
var overlay = document.createElement('div');
overlay.className = 'jcrop-selection';
overlay.style.position = 'absolute';
overlay.style.left = coords.x + 'px';
overlay.style.top = coords.y + 'px';
overlay.style.width = coords.w + 'px';
overlay.style.height = coords.h + 'px';
// Append the overlay to the container
jQuery('#selectableImage').parent().append(overlay);
}
function removePart(coords) {
// Remove part of the selected area in deselect mode
var newAreas = [];
for (var i = 0; i < selectedAreas.length; i++) {
var area = selectedAreas[i];
// Check if the clicked area intersects with any selected area
if (isIntersecting(coords, area)) {
// Split the area into non-overlapping parts
var splitAreas = splitArea(area, coords);
// Add the non-overlapping parts to the new areas array
newAreas = newAreas.concat(splitAreas);
} else {
// If there is no intersection, keep the area as it is
newAreas.push(area);
}
}
// Update the selected areas array
selectedAreas = newAreas;
// Redraw the overlays
jQuery('.jcrop-selection').remove();
for (var j = 0; j < selectedAreas.length; j++) {
drawOverlay(selectedAreas[j]);
}
}
function isIntersecting(coords1, coords2) {
// Check if two sets of coordinates are intersecting
return (
coords1.x < coords2.x + coords2.w &&
coords1.x + coords1.w > coords2.x &&
coords1.y < coords2.y + coords2.h &&
coords1.y + coords1.h > coords2.y
);
}
function splitArea(area, splitCoords) {
// Split an area into non-overlapping parts based on another set of coordinates
var splitAreas = [];
// Check and add the left part
if (splitCoords.x > area.x) {
splitAreas.push({
x: area.x,
y: area.y,
w: splitCoords.x - area.x,
h: area.h
});
}
// Check and add the right part
if (splitCoords.x + splitCoords.w < area.x + area.w) {
splitAreas.push({
x: splitCoords.x + splitCoords.w,
y: area.y,
w: area.x + area.w - splitCoords.x - splitCoords.w,
h: area.h
});
}
// Check and add the top part
if (splitCoords.y > area.y) {
splitAreas.push({
x: Math.max(splitCoords.x, area.x),
y: area.y,
w: Math.min(splitCoords.x + splitCoords.w, area.x + area.w) - Math.max(splitCoords.x, area.x),
h: splitCoords.y - area.y
});
}
// Check and add the bottom part
if (splitCoords.y + splitCoords.h < area.y + area.h) {
splitAreas.push({
x: Math.max(splitCoords.x, area.x),
y: splitCoords.y + splitCoords.h,
w: Math.min(splitCoords.x + splitCoords.w, area.x + area.w) - Math.max(splitCoords.x, area.x),
h: area.y + area.h - splitCoords.y - splitCoords.h
});
}
return splitAreas;
}
});
</script>
I need to subtract the deselection portion from the selected area of the image. In the above code, I tried but there is an issue that when I deselect the portion on the selected area, it adds a partition line when updating the coordinates after removing the deselection area and saves one area with different parts, which I do not need. Please guide me on how to solve this issue.