<img data-draggable src="http://example.com/australia.gif"/>
const gifCanvas = document.querySelector('#gifcanvas');
const draggableElements = document.querySelectorAll('[data-draggable]');
const gifCanvasRect = gifCanvas.getBoundingClientRect();
function calculateCellDimensions() {
const gridOverlay = document.querySelector('.grid-overlay'); // Re-query to get the latest grid overlay
const cells = gridOverlay.querySelectorAll('.grid-cell');
if (cells.length === 0) return { width: 0, height: 0 };
const lastCell = cells[cells.length - 1];
const coordinates = lastCell.dataset.coordinates.split(',').map(Number);
const rows = coordinates[1] + 1;
const cols = coordinates[0] + 1;
const gridRect = gridOverlay.getBoundingClientRect();
return {
width: gridRect.width / cols,
height: gridRect.height / rows,
gridRect: gridRect // Return the gridRect for use in calculations
};
}
draggableElements.forEach(draggable => {
let offsetX, offsetY;
draggable.addEventListener('mousedown', function(e) {
const rect = draggable.getBoundingClientRect();
offsetX = e.clientX - rect.left; // Calculate the initial offset inside the draggable element
offsetY = e.clientY - rect.top;
document.body.style.userSelect = 'none'; // Prevent text selection
});
document.addEventListener('mousemove', function(e) {
if (!offsetX && !offsetY) return; // Check if dragging has started
const { width: cellWidth, height: cellHeight, gridRect } = calculateCellDimensions(); // Recalculate each time
// Calculate new position based on mouse location and initial offset
let newX = e.clientX - offsetX;
let newY = e.clientY - offsetY;
// Adjust for live snapping while dragging
let relativeX = newX - gridRect.left + (draggable.offsetWidth / 2); // Center of the draggable
let relativeY = newY - gridRect.top + (draggable.offsetHeight / 2); // Center of the draggable
let snappedX = Math.round(relativeX / cellWidth) * cellWidth - (draggable.offsetWidth / 2);
let snappedY = Math.round(relativeY / cellHeight) * cellHeight - (draggable.offsetHeight / 2);
// Confine within gifCanvas
snappedX = Math.max(gifCanvasRect.left, Math.min(snappedX + gridRect.left, gifCanvasRect.right - draggable.offsetWidth));
snappedY = Math.max(gifCanvasRect.top, Math.min(snappedY + gridRect.top, gifCanvasRect.bottom - draggable.offsetHeight));
draggable.style.left = `${snappedX - gifCanvasRect.left}px`; // Adjust position relative to gifCanvas
draggable.style.top = `${snappedY - gifCanvasRect.top}px`;
});
document.addEventListener('mouseup', function() {
offsetX = null;
offsetY = null;
document.body.style.userSelect = ''; // Re-enable text selection
});
});
After we update the HTML, JS of the element that we intend to drag around, we click the framing tool to the divide the canvas.
The framing tool lets us customize the density of the canvas and will act as a guide for the grid snapping as we move the draggable element around.
Let's run our script and record a gif.
Check out the final effect with the grid portions visible.
Top comments (0)