Zoom is not working only zoom out is working i wanted the canvas to fit the viewport maybe something related to that not sure
<!DOCTYPE html> <html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Cropper</title>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css">
<style>
body,
html {
height: 100%;
margin: 0;
padding: 0;
background: black;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.controls {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
pointer-events: none;
/* Allows clicks to pass through */
}
.controls button,
.controls select {
pointer-events: auto;
/* Re-enable pointer events for controls */
background-color: black; /* Set button background to black */
color: white; /* Set text color to white */
}
.top-right {
position: absolute;
top: 10px;
right: 10px;
}
.top-left {
position: absolute;
top: 10px;
left: 10px;
}
.bottom-left {
position: absolute;
bottom: 10px;
left: 10px;
}
.bottom-right {
position: absolute;
bottom: 10px;
right: 10px;
}
.image-container-wrapper {
/* width: 80%; */
/* height: 80%; */
max-width: 90vw;
max-height: 90vh;
display: flex;
justify-content: center;
align-items: center;
overflow: visible;
/* Important to make sure that anything beyond the bounds is hidden */
}
.image-container {
position: relative;
width: 100%;
height: 100%;
}
canvas {
width: 100%;
/* Might restrict enlargement depending on parent's fixed dimensions */
height: 100%;
display: block;
}
.overlay {
position: absolute;
border: 2px solid yellow;
cursor: move;
touch-action: none;
z-index: 1;
}
.corner {
position: absolute;
width: 15px;
height: 15px;
background-color: yellow;
border-radius: 50%;
}
.corner.top-left {
top: -7.5px;
left: -7.5px;
}
.corner.top-right {
top: -7.5px;
right: -7.5px;
}
.corner.bottom-left {
bottom: -7.5px;
left: -7.5px;
}
.corner.bottom-right {
bottom: -7.5px;
right: -7.5px;
}
.overlay-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
pointer-events: none;
}
</style> </head>
<body>
<div class="controls">
<select id="shapeSelect" onchange="selectShape()" class="top-left">
<option value="rectangle" selected>Rectangle</option>
<option value="circle">Circle</option>
</select>
<button id="cropButton" class="top-right">Crop</button>
<div class="bottom-left">
<button onclick="rotateImage(-90)"><i class="fas fa-undo"></i></button>
<button onclick="rotateImage(90)"><i class="fas fa-redo"></i></button>
</div>
<div class="bottom-right">
<button onclick="zoomImage(1.2)"><i class="fas fa-search-plus"></i></button>
<button onclick="zoomImage(0.8)"><i class="fas fa-search-minus"></i></button>
</div>
</div>
<div class="image-container-wrapper">
<div class="image-container">
<div class="overlay-background"></div>
<canvas id="canvas"></canvas>
<div class="overlay">
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
</div>
</div>
</div>
<!-- <div id="croppedImagePreview"></div> -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const imageObj = new Image();
const overlay = document.querySelector('.overlay');
const overlayBackground = document.querySelector('.overlay-background');
let selectedShape = "rectangle";
let angle = 0;
let zoomFactor = 1; // Initial zoom factor
imageObj.onload = function () {
drawRotatedImage();
};
imageObj.crossOrigin = "Anonymous";
imageObj.src = 'rope41.png'; // Update image URL
window.selectShape = function () {
selectedShape = document.getElementById("shapeSelect").value;
overlay.style.borderRadius = selectedShape === "circle" ? "50%" : "0%";
};
window.rotateImage = function (deg) {
angle = (angle + deg) % 360;
drawRotatedImage();
// This should be done after redrawing the image and possibly resizing the overlay.
setTimeout(function () {
initializeOverlay();
}, 100); // Delay might be needed for the DOM updates to settle
}
window.zoomImage = function (factor) {
zoomFactor *= factor;
console.log("Zoom Factor: " + zoomFactor);
drawRotatedImage();
}
function drawRotatedImage() {
const radians = angle * Math.PI / 180;
const sin = Math.abs(Math.sin(radians));
const cos = Math.abs(Math.cos(radians));
const imageWidth = cos * imageObj.width + sin * imageObj.height;
const imageHeight = sin * imageObj.width + cos * imageObj.height;
const scaleX = (window.innerWidth / imageWidth) * zoomFactor;
const scaleY = (window.innerHeight / imageHeight) * zoomFactor;
const scaleToFit = Math.min(scaleX, scaleY);
console.log("Canvas dimensions: " + canvas.width + " x " + canvas.height);
const canvasWidth = imageWidth * scaleToFit;
const canvasHeight = imageHeight * scaleToFit;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx.setTransform(scaleToFit, 0, 0, scaleToFit, canvasWidth / 2, canvasHeight / 2);
ctx.rotate(radians);
ctx.drawImage(imageObj, -imageObj.width / 2, -imageObj.height / 2);
ctx.setTransform(1, 0, 0, 1, 0, 0);
initializeOverlay();
}
function initializeOverlay() {
const containerRect = document.querySelector('.image-container-wrapper').getBoundingClientRect();
overlay.style.width = `${containerRect.width - 4}px`;
overlay.style.height = `${containerRect.height - 4}px`;
overlay.style.top = '0px';
overlay.style.left = '0px';
setupOverlayInteractions(containerRect.width - 4, containerRect.height - 4);
}
function setupOverlayInteractions(width, height) {
if ($.data(overlay, 'ui-resizable')) {
$(overlay).resizable('destroy');
}
if ($.data(overlay, 'ui-draggable')) {
$(overlay).draggable('destroy');
}
// Set up resizable
$(overlay).resizable({
containment: "parent",
handles: 'n, e, s, w, ne, se, sw, nw',
minWidth: 50,
minHeight: 50,
resize: function (event, ui) {
updateOverlayBackground(ui.position, ui.size);
}
});
// Set up draggable
$(overlay).draggable({
containment: "parent",
drag: function (event, ui) {
updateOverlayBackground(ui.position, { width: ui.helper.width(), height: ui.helper.height() });
}
});
updateOverlayBackground({ top: '0px', left: '0px' }, { width, height });
}
function updateOverlayBackground(position, size) {
const left = parseFloat(position.left) || 0;
const top = parseFloat(position.top) || 0;
const width = parseFloat(size.width) || 0;
const height = parseFloat(size.height) || 0;
overlayBackground.style.clipPath = `polygon(
0 0,
0 100%,
${left}px 100%,
${left}px ${top}px,
${left + width}px ${top}px,
${left + width}px ${top + height}px,
${left}px ${top + height}px,
${left}px 100%,
100% 100%,
100% 0
)`;
}
document.getElementById('cropButton').addEventListener('click', function () {
const canvasRect = canvas.getBoundingClientRect();
const bounds = overlay.getBoundingClientRect();
const scaleX = canvas.width / canvasRect.width;
const scaleY = canvas.height / canvasRect.height;
const cropX = (bounds.left - canvasRect.left) * scaleX;
const cropY = (bounds.top - canvasRect.top) * scaleY;
const cropWidth = bounds.width * scaleX;
const cropHeight = bounds.height * scaleY;
const croppedCanvas = document.createElement("canvas");
const croppedCtx = croppedCanvas.getContext("2d");
croppedCanvas.width = cropWidth;
croppedCanvas.height = cropHeight;
croppedCtx.drawImage(canvas, cropX, cropY, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);
// const imgPreview = document.getElementById('croppedImagePreview');
// imgPreview.innerHTML = '';
const img = new Image();
img.src = croppedCanvas.toDataURL("image/png");
console.log("Base64", img.src);
// imgPreview.appendChild(img);
});
});
</script> </body>
</html>