Pay attention to mouseup
. You try to get correct top
and left
values for fixed
element, but its top
and left
properties of style calculated by the viewport
of browser (not by the top and left of document
). This is correct code.
class CanvasCrop {
constructor(media) {
let x1 = 0;
let y1 = 0;
let x2 = 0;
let y2 = 0;
let dragThreshold = 50;
let mousedown = false;
let dragging = false;
const selectionRect = document.getElementById('selectionRect');
function reCalc() {
var x3 = Math.min(x1, x2);
var x4 = Math.max(x1, x2);
var y3 = Math.min(y1, y2);
var y4 = Math.max(y1, y2);
selectionRect.style.left = x3 + 'px';
selectionRect.style.top = y3 + 'px';
selectionRect.style.width = x4 - x3 + 'px';
selectionRect.style.height = y4 - y3 + 'px';
}
function cropMedia(media, {
stretch = 1,
left = 0,
top = 0,
width,
height
} = {}) {
const croppedCanvas = document.createElement('canvas');
croppedCanvas.width = width;
croppedCanvas.height = height;
const ctx = croppedCanvas.getContext('2d');
ctx.drawImage(media, left, top, width, height, 0, 0, width * stretch, height * stretch);
return croppedCanvas;
}
media.onmousedown = function(e) {
mousedown = true;
selectionRect.hidden = 0;
x1 = e.clientX;
y1 = e.clientY;
};
onmousemove = function(e) {
//todo implement isDragging
if (mousedown) {
x2 = e.clientX;
y2 = e.clientY;
var deltaX = Math.abs(x2 - x1);
var deltaY = Math.abs(x2 - x1);
reCalc();
if (deltaX > dragThreshold || deltaY > dragThreshold) dragging = true;
}
};
onmouseup = (e) => {
var pic = document.getElementById('pic');
var offsetTop = pic.offsetTop;
var offsetLeft = pic.offsetLeft;
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
var scrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
scrollTop -= offsetTop;
scrollLeft -= offsetLeft;
selectionRect.hidden = 1;
mousedown = false;
if (dragging) {
dragging = false;
let croppedCanvas = cropMedia(media, {
left: parseInt(selectionRect.style.left, 10) + scrollLeft,
top: parseInt(selectionRect.style.top, 10) + scrollTop,
width: parseInt(selectionRect.style.width, 10),
height: parseInt(selectionRect.style.height, 10)
});
const preview = document.getElementById('preview');
preview.innerHTML = '';
preview.appendChild(croppedCanvas);
}
};
}
}
const cc = new CanvasCrop(document.getElementById('pic'));