center spawned images under cursor; playing card layout for multiple images
Hunter
Sunday, October 19th, 2025 at 9:39 PM
238 e.stopPropagation();
239 });
240
- page.addEventListener('drop', (e) => {
241 + page.addEventListener('drop', async (e) => {
242 e.preventDefault();
243 e.stopPropagation();
244
249 const dropX = e.clientX - gridRect.left;
250 const dropY = e.clientY - gridRect.top;
251
252 + // Load first image to get base dimensions
253 + let firstImageDimensions = null;
254 + if (files.length > 0) {
255 + const firstFile = files[0];
256 + const reader = new FileReader();
257 + const dataUrl = await new Promise(resolve => {
258 + reader.onload = (e) => resolve(e.target.result);
259 + reader.readAsDataURL(firstFile);
260 + });
261 +
262 + const img = new Image();
263 + await new Promise(resolve => {
264 + img.onload = () => {
265 + const aspectRatio = img.width / img.height;
266 + let widthCells, heightCells;
267 + if (aspectRatio >= 1) {
268 + heightCells = 5;
269 + widthCells = Math.round(heightCells * aspectRatio);
270 + } else {
271 + widthCells = 5;
272 + heightCells = Math.round(widthCells / aspectRatio);
273 + }
274 + widthCells = Math.min(widthCells, GRID_COLS);
275 + heightCells = Math.min(heightCells, GRID_ROWS);
276 + firstImageDimensions = { widthCells, heightCells };
277 + resolve();
278 + };
279 + img.src = dataUrl;
280 + });
281 + }
282 +
283 + // Now process all files
284 files.forEach((file, idx) => {
285 const reader = new FileReader();
286 reader.onload = (event) => {
304 widthCells = Math.min(widthCells, GRID_COLS);
305 heightCells = Math.min(heightCells, GRID_ROWS);
306
- // Calculate position near drop point
- let xCell = Math.round(dropX / CELL_SIZE_PX) + (idx * 2);
- let yCell = Math.round(dropY / CELL_SIZE_PX);
307 + // Calculate position with first image's center under drop point
308 + let xCell = Math.round(dropX / CELL_SIZE_PX - firstImageDimensions.widthCells / 2) + (idx * 2);
309 + let yCell = Math.round(dropY / CELL_SIZE_PX - firstImageDimensions.heightCells / 2);
310
311 // Ensure image stays within grid bounds
312 xCell = Math.max(0, Math.min(GRID_COLS - widthCells, xCell));
313 yCell = Math.max(0, Math.min(GRID_ROWS - heightCells, yCell));
314
- addImage(event.target.result, xCell, yCell, widthCells, heightCells);
315 + addImage(event.target.result, xCell, yCell, widthCells, heightCells, idx + 1);
316 };
317 img.src = event.target.result;
318 };
320 });
321 });
322
- function addImage(src, xCell, yCell, widthCells, heightCells) {
323 + function addImage(src, xCell, yCell, widthCells, heightCells, zIndex = 0) {
324 const container = document.createElement('div');
325 container.className = 'image-container';
326 + if (zIndex > 0) {
327 + container.style.zIndex = zIndex;
328 + }
329
330 const img = document.createElement('img');
331 img.src = src;