human (Nov 27, 2024, 12:37 PM)
Build me an artifact - no React - that lets me drop an image onto a page (or open it with a file picker) and then shows me that image with a cropperjs UI that is configured to a 2x1 area - a social media card
I can drag that 2x1 area around and below the image is a preview of the selected image, the preview is a 0.7 quality JPEG
It gives me a download link that download that JPEG
assistant (Nov 27, 2024, 12:37 PM)
I'll help you create an HTML artifact with cropper.js integration for creating social media cards with a 2:1 aspect ratio.
<!DOCTYPE html>
<html>
<head>
<title>Social Media Card Cropper</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.css">
<style>
body {
font-family: system-ui, -apple-system, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f5f5f5;
}
.container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.drop-zone {
border: 2px dashed #ccc;
border-radius: 4px;
padding: 20px;
text-align: center;
margin-bottom: 20px;
background: #fafafa;
cursor: pointer;
}
.drop-zone.dragover {
border-color: #666;
background: #eee;
}
.img-container {
max-width: 100%;
margin-bottom: 20px;
}
#image {
display: block;
max-width: 100%;
}
.preview-container {
margin-top: 20px;
padding: 10px;
background: #fafafa;
border-radius: 4px;
}
#preview {
width: 100%;
max-width: 600px;
margin: 0 auto;
display: block;
}
.download-btn {
display: inline-block;
padding: 10px 20px;
background: #0066cc;
color: white;
text-decoration: none;
border-radius: 4px;
margin-top: 10px;
}
.download-btn:hover {
background: #0052a3;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div class="container">
<h1>Social Media Card Cropper</h1>
<p>Drop an image or click to select. The crop area is fixed to 2:1 ratio.</p>
<div class="drop-zone" id="dropZone">
Drop image here or click to select
<input type="file" id="fileInput" accept="image/*" class="hidden">
</div>
<div class="img-container">
<img id="image" class="hidden">
</div>
<div class="preview-container hidden" id="previewContainer">
<h3>Preview (0.7 quality JPEG)</h3>
<img id="preview">
<div style="text-align: center; margin-top: 10px;">
<a href="#" id="downloadBtn" class="download-btn">Download Social Media Card</a>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.js"></script>
<script>
let cropper = null;
const dropZone = document.getElementById('dropZone');
const fileInput = document.getElementById('fileInput');
const image = document.getElementById('image');
const preview = document.getElementById('preview');
const previewContainer = document.getElementById('previewContainer');
const downloadBtn = document.getElementById('downloadBtn');
// Handle drag and drop
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.classList.add('dragover');
});
dropZone.addEventListener('dragleave', () => {
dropZone.classList.remove('dragover');
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.classList.remove('dragover');
handleFile(e.dataTransfer.files[0]);
});
// Handle click to select
dropZone.addEventListener('click', () => {
fileInput.click();
});
fileInput.addEventListener('change', (e) => {
if (e.target.files.length) {
handleFile(e.target.files[0]);
}
});
function handleFile(file) {
if (!file.type.startsWith('image/')) {
alert('Please select an image file.');
return;
}
const reader = new FileReader();
reader.onload = (e) => {
image.src = e.target.result;
image.classList.remove('hidden');
initCropper();
};
reader.readAsDataURL(file);
}
function initCropper() {
if (cropper) {
cropper.destroy();
}
cropper = new Cropper(image, {
aspectRatio: 2,
viewMode: 1,
dragMode: 'move',
autoCropArea: 1,
restore: false,
guides: true,
center: true,
highlight: false,
cropBoxMovable: true,
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
crop: updatePreview
});
}
function updatePreview() {
if (!cropper) return;
const canvas = cropper.getCroppedCanvas();
if (!canvas) return;
// Convert to JPEG with 0.7 quality
const previewUrl = canvas.toDataURL('image/jpeg', 0.7);
preview.src = previewUrl;
previewContainer.classList.remove('hidden');
// Update download link
downloadBtn.href = previewUrl;
downloadBtn.download = 'social-media-card.jpg';
}
</script>
</body>
</html>
I've created an HTML artifact that includes:
- A drag-and-drop zone (you can also click to select a file)
- A cropper.js interface configured with:
- Fixed 2:1 aspect ratio
- Move-only mode (no resizing of the crop box)
- Guides and grid for better positioning
- A live preview showing the cropped image as a 0.7 quality JPEG
- A download button that saves the cropped image
The interface is styled with a clean, modern look and includes:
- Responsive design that works on different screen sizes
- Visual feedback for drag and drop
- Clear instructions
- Preview area with the final JPEG output
You can simply drag any image onto the drop zone or click to select one, and then:
- Move the crop area around to select the desired portion
- See a live preview below
- Download the final JPEG when you're satisfied
The cropper is configured to maintain the 2:1 aspect ratio at all times, making it perfect for social media cards. Let me know if you'd like any adjustments to the interface or functionality!
human (Dec 10, 2024, 08:32 PM)
Make it so pasting an image works too
assistant (Dec 10, 2024, 08:32 PM)
I'll add clipboard paste support to the image cropper.
Find this:
const dropZone = document.getElementById('dropZone');
const fileInput = document.getElementById('fileInput');
Replace with this:
const dropZone = document.getElementById('dropZone');
const fileInput = document.getElementById('fileInput');
// Handle paste events
document.addEventListener('paste', (e) => {
e.preventDefault();
const items = (e.clipboardData || e.originalEvent.clipboardData).items;
for (const item of items) {
if (item.type.indexOf('image') === 0) {
const file = item.getAsFile();
handleFile(file);
break;
}
}
});
Find this:
Drop image here or click to select
Replace with this:
Drop image here, click to select, or paste from clipboard
I've added clipboard paste support to the image cropper. Now you can:
- Drag and drop an image
- Click to select a file
- Paste an image directly from your clipboard (Ctrl+V / Cmd+V)
The paste functionality works anywhere on the page - you don't need to focus on any specific element. I also updated the instructions in the drop zone to indicate that pasting is supported.
Let me know if you'd like any other improvements!