我希望画布的高度和宽度在旋转图像时发生变化并相应地工作,并且叠加层也应适合旋转的画布,并且裁剪应相应地工作。
<!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">
<style>
html,
body {
background: black;
margin: 0;
padding: 0;
height: 90%;
}
.image-container {
position: relative;
min-height: 80%;
display: flex;
align-items: center;
justify-content: center;
margin: auto;
overflow: visible;
/* background-color: #f8f9fa; */
}
/* @media (max-width: 480px) {
.image-container {
min-height: 60vh;
}
} */
#canvas {
display: block;
max-width: 100%;
max-height: 100%;
margin: auto;
/* background-color: white; */
}
.main-div {
padding-top: 5%;
width: 100%;
height: 100%;
background: black;
}
.overlay {
position: absolute;
border: 2px solid yellow;
cursor: move;
touch-action: none;
z-index: 1;
}
.ui-resizable-handle {
background-image: none;
}
.corner {
position: absolute;
width: 15px;
height: 15px;
background-color: yellow;
border-radius: 50%;
}
.corner.top-left {
top: -5px;
left: -5px;
}
.corner.top-right {
top: -5px;
right: -5px;
}
.corner.bottom-left {
bottom: -5px;
left: -5px;
}
.corner.bottom-right {
bottom: -5px;
right: -5px;
}
.overlay-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
/* Default opacity for rectangle */
pointer-events: none;
}
.rotate-buttons {
margin-top: 10px;
}
</style>
</head>
<body>
<div class="main-div">
<button id="cropButton">Crop</button>
<select id="shapeSelect" onchange="selectShape()">
<option value="rectangle" selected>Rectangle</option>
<option value="circle">Circle</option>
</select>
<div class="rotate-buttons">
<button onclick="rotateClockwise()">Rotate Clockwise</button>
<button onclick="rotateCounterClockwise()">Rotate Counter Clockwise</button>
</div>
<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 id="croppedImagePreview"></div>
</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>
<!-- Include Touch Punch for touch support -->
<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');
const croppedCanvas = document.createElement("canvas");
const croppedCtx = croppedCanvas.getContext("2d");
let selectedShape = "rectangle";
let rotation = 0; // Initial rotation angle
// Define selectShape function to fix the Uncaught ReferenceError
window.selectShape = function() {
selectedShape = document.getElementById("shapeSelect").value;
console.log(selectedShape);
// Adjust overlay style based on selected shape
overlay.style.borderRadius = selectedShape === "circle" ? "50%" : "0%"; // Adjust border radius for circle
// Adjust overlay background opacity based on selected shape
if (selectedShape === "circle") {
overlayBackground.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; // 50% opacity for circle
} else {
overlayBackground.style.backgroundColor = "rgba(0, 0, 0, 0.7)"; // Higher opacity for rectangle
}
};
// Function to rotate the image clockwise
window.rotateClockwise = function() {
rotation += 90;
drawRotatedImage();
};
// Function to rotate the image counter-clockwise
window.rotateCounterClockwise = function() {
rotation -= 90;
drawRotatedImage();
};
function drawRotatedImage() {
const originalWidth = imageObj.naturalWidth;
const originalHeight = imageObj.naturalHeight;
const is90Or270 = Math.abs(rotation % 360) === 90 || Math.abs(rotation % 360) === 270;
// Set canvas size based on rotation
if (is90Or270) {
canvas.width = originalHeight;
canvas.height = originalWidth;
} else {
canvas.width = originalWidth;
canvas.height = originalHeight;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(rotation * Math.PI / 180);
ctx.drawImage(imageObj, -originalWidth / 2, -originalHeight / 2, originalWidth, originalHeight);
ctx.restore();
// Update the overlay to match the new dimensions
initializeOverlay();
}
imageObj.onload = function() {
const container = document.querySelector('.image-container');
const ratio = Math.min(container.clientWidth / imageObj.naturalWidth, container.clientHeight / imageObj.naturalHeight);
const imageWidth = imageObj.naturalWidth * ratio;
const imageHeight = imageObj.naturalHeight * ratio;
canvas.width = imageObj.naturalWidth;
canvas.height = imageObj.naturalHeight;
canvas.style.width = `${imageWidth}px`;
canvas.style.height = `${imageHeight}px`;
container.style.width = `${imageWidth}px`;
container.style.height = `${imageHeight}px`;
ctx.drawImage(imageObj, 0, 0, imageObj.naturalWidth, imageObj.naturalHeight);
initializeOverlay();
};
imageObj.crossOrigin = "Anonymous";
imageObj.src = 'rope41.png'; // Make sure the path is correct
function initializeOverlay() {
const container = document.querySelector('.image-container');
const ratio = Math.min(container.clientWidth / imageObj.naturalWidth, container.clientHeight / imageObj.naturalHeight);
const imageWidth = imageObj.naturalWidth * ratio;
const imageHeight = imageObj.naturalHeight * ratio;
var tempImageWidth = imageWidth - 4; //Adjusting width the initial overlay to fit properly in pixels
var tempImageHeight = imageHeight - 3; //Adjusting height the initial overlay to fit properly pixels
overlay.style.width = `${tempImageWidth}px`;
overlay.style.height = `${tempImageHeight}px`;
// Center the overlay
overlay.style.top = `${(container.clientHeight - imageHeight) / 2}px`;
overlay.style.left = `${(container.clientWidth - imageWidth) / 2}px`;
$(overlay).resizable({
containment: "parent",
handles: 'n, e, s, w, ne, se, sw, nw',
minWidth: 100, // Setting minimum width for resizing
minHeight: 100, // Setting minimum height for resizing
resize: function(event, ui) {
updateOverlayBackground(ui.position, ui.size);
}
}).draggable({
containment: "parent",
drag: function(event, ui) {
// Get the current dimensions using jQuery
const currentWidth = $(overlay).width();
const currentHeight = $(overlay).height();
// Create a size object to pass to the update function
const size = {
width: currentWidth,
height: currentHeight
};
updateOverlayBackground(ui.position, size);
}
});
updateOverlayBackground({
top: overlay.style.top,
left: overlay.style.left
}, {
width: tempImageWidth,
height: tempImageHeight
});
}
function updateOverlayBackground(position, size) {
// Corrected to ensure position and size are correctly parsed as numbers
const left = parseFloat(position.left) || 0; // Added default value to prevent undefined
const top = parseFloat(position.top) || 0; // Added default value to prevent undefined
const width = parseFloat(size.width) || 0; // Added default value to prevent undefined
const height = parseFloat(size.height) || 0; // Added default value to prevent undefined
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', cropImage);
function cropImage() {
const selectedShape = document.getElementById("shapeSelect").value;
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;
croppedCanvas.width = cropWidth;
croppedCanvas.height = cropHeight;
if (selectedShape === "rectangle") {
croppedCtx.drawImage(canvas, cropX, cropY, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);
} else if (selectedShape === "circle") {
let rx = cropWidth / 2; // Radius along x-axis
let ry = cropHeight / 2; // Radius along y-axis
let cx = rx; // Center along x-axis
let cy = ry; // Center along y-axis
croppedCtx.save(); // Save the current context state
croppedCtx.beginPath();
croppedCtx.translate(cx, cy); // Translate to the center of the ellipse
croppedCtx.scale(1, ry / rx); // Scale to make the circle an ellipse
croppedCtx.arc(0, 0, rx, 0, Math.PI * 2);
croppedCtx.closePath();
croppedCtx.restore(); // Restore the previous context state
croppedCtx.clip();
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(img.src);
imgPreview.appendChild(img);
}
});
</script>
</body>
</html>
旋转时,我需要画布也旋转,并在旋转的图像上进行裁剪。 我尝试根据旋转切换画布的高度和宽度,但没有成功。
<!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">
<style>
html,
body {
background: black;
margin: 0;
padding: 0;
height: 90%;
}
.image-container {
position: relative;
min-height: 80%;
display: flex;
align-items: center;
justify-content: center;
margin: auto;
overflow: visible;
/* background-color: #f8f9fa; */
}
/* @media (max-width: 480px) {
.image-container {
min-height: 60vh;
}
} */
#canvas {
display: block;
max-width: 100%;
max-height: 100%;
margin: auto;
/* background-color: white; */
}
.main-div {
padding-top: 5%;
width: 100%;
height: 100%;
background: black;
}
.overlay {
position: absolute;
border: 2px solid yellow;
cursor: move;
touch-action: none;
z-index: 1;
}
.ui-resizable-handle {
background-image: none;
}
.corner {
position: absolute;
width: 15px;
height: 15px;
background-color: yellow;
border-radius: 50%;
}
.corner.top-left {
top: -5px;
left: -5px;
}
.corner.top-right {
top: -5px;
right: -5px;
}
.corner.bottom-left {
bottom: -5px;
left: -5px;
}
.corner.bottom-right {
bottom: -5px;
right: -5px;
}
.overlay-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
/* Default opacity for rectangle */
pointer-events: none;
}
.rotate-buttons {
margin-top: 10px;
}
</style>
</head>
<body>
<div class="main-div">
<button id="cropButton">Crop</button>
<select id="shapeSelect" onchange="selectShape()">
<option value="rectangle" selected>Rectangle</option>
<option value="circle">Circle</option>
</select>
<div class="rotate-buttons">
<button onclick="rotateClockwise()">Rotate Clockwise</button>
<button onclick="rotateCounterClockwise()">Rotate Counter Clockwise</button>
</div>
<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 id="croppedImagePreview"></div>
</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>
<!-- Include Touch Punch for touch support -->
<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');
const croppedCanvas = document.createElement("canvas");
const croppedCtx = croppedCanvas.getContext("2d");
let selectedShape = "rectangle";
let rotation = 0; // Initial rotation angle
// Define selectShape function to fix the Uncaught ReferenceError
window.selectShape = function() {
selectedShape = document.getElementById("shapeSelect").value;
console.log(selectedShape);
// Adjust overlay style based on selected shape
overlay.style.borderRadius = selectedShape === "circle" ? "50%" : "0%"; // Adjust border radius for circle
// Adjust overlay background opacity based on selected shape
if (selectedShape === "circle") {
overlayBackground.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; // 50% opacity for circle
} else {
overlayBackground.style.backgroundColor = "rgba(0, 0, 0, 0.7)"; // Higher opacity for rectangle
}
};
// Function to rotate the image clockwise
window.rotateClockwise = function() {
rotation += 90;
drawRotatedImage();
};
// Function to rotate the image counter-clockwise
window.rotateCounterClockwise = function() {
rotation -= 90;
drawRotatedImage();
};
function drawRotatedImage() {
const originalWidth = imageObj.naturalWidth;
const originalHeight = imageObj.naturalHeight;
const is90Or270 = Math.abs(rotation % 360) === 90 || Math.abs(rotation % 360) === 270;
// Set canvas size based on rotation
if (is90Or270) {
canvas.width = originalHeight;
canvas.height = originalWidth;
} else {
canvas.width = originalWidth;
canvas.height = originalHeight;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(rotation * Math.PI / 180);
ctx.drawImage(imageObj, -originalWidth / 2, -originalHeight / 2, originalWidth, originalHeight);
ctx.restore();
// Update the overlay to match the new dimensions
initializeOverlay();
}
imageObj.onload = function() {
const container = document.querySelector('.image-container');
const ratio = Math.min(container.clientWidth / imageObj.naturalWidth, container.clientHeight / imageObj.naturalHeight);
const imageWidth = imageObj.naturalWidth * ratio;
const imageHeight = imageObj.naturalHeight * ratio;
canvas.width = imageObj.naturalWidth;
canvas.height = imageObj.naturalHeight;
canvas.style.width = `${imageWidth}px`;
canvas.style.height = `${imageHeight}px`;
container.style.width = `${imageWidth}px`;
container.style.height = `${imageHeight}px`;
ctx.drawImage(imageObj, 0, 0, imageObj.naturalWidth, imageObj.naturalHeight);
initializeOverlay();
};
imageObj.crossOrigin = "Anonymous";
imageObj.src = 'rope41.png'; // Make sure the path is correct
function initializeOverlay() {
const container = document.querySelector('.image-container');
const ratio = Math.min(container.clientWidth / imageObj.naturalWidth, container.clientHeight / imageObj.naturalHeight);
const imageWidth = imageObj.naturalWidth * ratio;
const imageHeight = imageObj.naturalHeight * ratio;
var tempImageWidth = imageWidth - 4; //Adjusting width the initial overlay to fit properly in pixels
var tempImageHeight = imageHeight - 3; //Adjusting height the initial overlay to fit properly pixels
overlay.style.width = `${tempImageWidth}px`;
overlay.style.height = `${tempImageHeight}px`;
// Center the overlay
overlay.style.top = `${(container.clientHeight - imageHeight) / 2}px`;
overlay.style.left = `${(container.clientWidth - imageWidth) / 2}px`;
$(overlay).resizable({
containment: "parent",
handles: 'n, e, s, w, ne, se, sw, nw',
minWidth: 100, // Setting minimum width for resizing
minHeight: 100, // Setting minimum height for resizing
resize: function(event, ui) {
updateOverlayBackground(ui.position, ui.size);
}
}).draggable({
containment: "parent",
drag: function(event, ui) {
// Get the current dimensions using jQuery
const currentWidth = $(overlay).width();
const currentHeight = $(overlay).height();
// Create a size object to pass to the update function
const size = {
width: currentWidth,
height: currentHeight
};
updateOverlayBackground(ui.position, size);
}
});
updateOverlayBackground({
top: overlay.style.top,
left: overlay.style.left
}, {
width: tempImageWidth,
height: tempImageHeight
});
}
function updateOverlayBackground(position, size) {
// Corrected to ensure position and size are correctly parsed as numbers
const left = parseFloat(position.left) || 0; // Added default value to prevent undefined
const top = parseFloat(position.top) || 0; // Added default value to prevent undefined
const width = parseFloat(size.width) || 0; // Added default value to prevent undefined
const height = parseFloat(size.height) || 0; // Added default value to prevent undefined
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', cropImage);
function cropImage() {
const selectedShape = document.getElementById("shapeSelect").value;
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;
croppedCanvas.width = cropWidth;
croppedCanvas.height = cropHeight;
if (selectedShape === "rectangle") {
croppedCtx.drawImage(canvas, cropX, cropY, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);
} else if (selectedShape === "circle") {
let rx = cropWidth / 2; // Radius along x-axis
let ry = cropHeight / 2; // Radius along y-axis
let cx = rx; // Center along x-axis
let cy = ry; // Center along y-axis
croppedCtx.save(); // Save the current context state
croppedCtx.beginPath();
croppedCtx.translate(cx, cy); // Translate to the center of the ellipse
croppedCtx.scale(1, ry / rx); // Scale to make the circle an ellipse
croppedCtx.arc(0, 0, rx, 0, Math.PI * 2);
croppedCtx.closePath();
croppedCtx.restore(); // Restore the previous context state
croppedCtx.clip();
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(img.src);
imgPreview.appendChild(img);
}
});
</script>
</body>
</html>