Skip to content

Commit a57b5c3

Browse files
committed
zoom in and out and background color
https://gist.github.com/simonw/a3e7f3ce34e26ab7c207fe641853e4a0 Pure vibe based coding, I hacked at it until it seemed to work, didn't even look at the code
1 parent a109547 commit a57b5c3

File tree

1 file changed

+91
-7
lines changed

1 file changed

+91
-7
lines changed

social-media-cropper.html

+91-7
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,17 @@ <h1>Social Media Card Cropper</h1>
7676
<label style="margin-right: 10px;">
7777
<input type="radio" name="aspectRatio" value="2" checked> 2:1 ratio
7878
</label>
79-
<label>
79+
<label style="margin-right: 10px;">
8080
<input type="radio" name="aspectRatio" value="1.4"> 14:10 ratio
8181
</label>
82+
<div style="margin-top: 10px;">
83+
<label for="backgroundColor">Background color:</label>
84+
<input type="color" id="backgroundColor" value="#ffffff">
85+
</div>
86+
<div style="margin-top: 10px;">
87+
<button id="zoomInBtn" type="button" style="margin-right: 5px;">Zoom +</button>
88+
<button id="zoomOutBtn" type="button">Zoom -</button>
89+
</div>
8290
</div>
8391

8492
<div class="drop-zone" id="dropZone">
@@ -105,6 +113,9 @@ <h3>Preview (0.7 quality JPEG)</h3>
105113
let cropper = null;
106114
const dropZone = document.getElementById('dropZone');
107115
const fileInput = document.getElementById('fileInput');
116+
const backgroundColor = document.getElementById('backgroundColor');
117+
const zoomInBtn = document.getElementById('zoomInBtn');
118+
const zoomOutBtn = document.getElementById('zoomOutBtn');
108119

109120
// Handle paste events
110121
document.addEventListener('paste', (e) => {
@@ -158,6 +169,37 @@ <h3>Preview (0.7 quality JPEG)</h3>
158169
}
159170
});
160171
});
172+
173+
// Listen for background color changes and update the cropper
174+
backgroundColor.addEventListener('change', () => {
175+
if (cropper) {
176+
initCropper();
177+
}
178+
});
179+
180+
// Handle zoom buttons
181+
zoomInBtn.addEventListener('click', () => {
182+
if (cropper) {
183+
cropper.zoom(0.1);
184+
}
185+
});
186+
187+
zoomOutBtn.addEventListener('click', () => {
188+
if (cropper) {
189+
cropper.zoom(-0.1);
190+
// Force update canvas size to allow zooming out beyond image boundaries
191+
const canvasData = cropper.getCanvasData();
192+
const newWidth = canvasData.width * 0.9;
193+
const newHeight = canvasData.height * 0.9;
194+
195+
cropper.setCanvasData({
196+
width: newWidth,
197+
height: newHeight,
198+
left: canvasData.left + (canvasData.width - newWidth) / 2,
199+
top: canvasData.top + (canvasData.height - newHeight) / 2
200+
});
201+
}
202+
});
161203

162204
function handleFile(file) {
163205
if (!file.type.startsWith('image/')) {
@@ -185,26 +227,68 @@ <h3>Preview (0.7 quality JPEG)</h3>
185227

186228
cropper = new Cropper(image, {
187229
aspectRatio: ratio,
188-
viewMode: 1,
230+
viewMode: 0, // Changed to 0 for no restrictions
189231
dragMode: 'move',
190-
autoCropArea: 1,
232+
autoCropArea: 0.8,
191233
restore: false,
192234
guides: true,
193235
center: true,
194236
highlight: false,
195237
cropBoxMovable: true,
196-
cropBoxResizable: false,
238+
cropBoxResizable: true,
197239
toggleDragModeOnDblclick: false,
240+
minCropBoxWidth: 100,
241+
minCropBoxHeight: 100,
242+
minCanvasWidth: 0,
243+
minCanvasHeight: 0,
244+
background: true,
198245
crop: updatePreview
199246
});
200247
}
201248

202249
function updatePreview() {
203250
if (!cropper) return;
204251

205-
const canvas = cropper.getCroppedCanvas();
206-
if (!canvas) return;
207-
252+
// Create a larger canvas with the background color
253+
const crop = cropper.getData();
254+
const canvas = document.createElement('canvas');
255+
const ctx = canvas.getContext('2d');
256+
257+
// Get the selected aspect ratio
258+
const aspectRatioValue = document.querySelector('input[name="aspectRatio"]:checked').value;
259+
const ratio = parseFloat(aspectRatioValue);
260+
261+
// Set canvas dimensions to the desired aspect ratio
262+
if (ratio === 2) {
263+
canvas.width = 1200;
264+
canvas.height = 600;
265+
} else {
266+
canvas.width = 1400;
267+
canvas.height = 1000;
268+
}
269+
270+
// Fill with background color
271+
ctx.fillStyle = backgroundColor.value;
272+
ctx.fillRect(0, 0, canvas.width, canvas.height);
273+
274+
// Get the cropped canvas
275+
const croppedCanvas = cropper.getCroppedCanvas();
276+
if (!croppedCanvas) return;
277+
278+
// Calculate dimensions to center the image
279+
const scale = Math.min(
280+
canvas.width / croppedCanvas.width,
281+
canvas.height / croppedCanvas.height
282+
) * 0.9; // Scale slightly down to add padding
283+
284+
const scaledWidth = croppedCanvas.width * scale;
285+
const scaledHeight = croppedCanvas.height * scale;
286+
const x = (canvas.width - scaledWidth) / 2;
287+
const y = (canvas.height - scaledHeight) / 2;
288+
289+
// Draw the cropped image centered on the background
290+
ctx.drawImage(croppedCanvas, x, y, scaledWidth, scaledHeight);
291+
208292
// Convert to JPEG with 0.7 quality
209293
const previewUrl = canvas.toDataURL('image/jpeg', 0.7);
210294
preview.src = previewUrl;

0 commit comments

Comments
 (0)