3

Currently working on image editing with some drag&drop. Having something functional on chrome, but on Safari, dragend event returns stupid coordinates (e.clientX and e.clientY). Just tried on Firefox, and the values are now empty.

So this is supposed to return the mouse position on canvas when the user drops an image, which works great on Chrome, but on Safari clientX is way too big and clientY is negative...

sticker.addEventListener("dragend", (e) => {
    let coords = new Array(
        document.getElementById("canvas").getBoundingClientRect()
    ).map((rect) => {
        console.log(e.clientX(e.clientY));
        return [(e.clientX - rect.left)(e.clientY - rect.top)].join();
    });
});
male-gal
  • 33
  • 4
  • Does this answer your question? [Drag and drop directive , no e.clientX or e.clientY on drag event in FireFox](https://stackoverflow.com/questions/23992091/drag-and-drop-directive-no-e-clientx-or-e-clienty-on-drag-event-in-firefox) – Oleg Valter is with Ukraine Jul 29 '21 at 11:51
  • also this one with more explanation: [Why is event.clientX incorrectly showing as 0 in firefox for dragend event?](https://stackoverflow.com/q/11656061/11407695) – Oleg Valter is with Ukraine Jul 29 '21 at 11:59

2 Answers2

3

My solution was to keep track of the position given by the drag callback function (which doens't have the problem 'dragEnd' have) and then when 'dragEnd' is triggered I just use the last values from those temp variables.

Example:

drag (ev) {
  this.last_x = ev.clientX;
  this.last_y = ev.clientY;
  ...
},
dragEnd (ev) {
  this.x = this.last_x;
  this.y = this.last_y;
  ...
}

I hope this help.

Matias
  • 575
  • 5
  • 17
1

Some browsers will indeed return fake values for this event, because it may well occur on a different document and even an other application than the one your page is running on.

This is somehow information leakage, and browsers don't like it.

An easy workaround is to instead listen to the drop event that should fire on your canvas element. In this event, it is admitted that the user gave you all permissions about the dragged content, so browsers will give you the correct coordinates.

const ctx = canvas.getContext('2d');
ctx.fillText('drop here', 20, 20);
canvas.addEventListener('drop', e => draw(e, 'red'));
canvas.addEventListener('dragover',e=>e.preventDefault());
sticker.addEventListener('dragstart', e=>{e.dataTransfer.setData('text', null)});

function draw(e, color) {
   e.preventDefault();
   const rect = canvas.getBoundingClientRect();
   ctx.beginPath();
   ctx.arc((e.clientX - rect.left), (e.clientY - rect.top), 5, 0, Math.PI*2);
   ctx.fillStyle = color;
   ctx.fill();
}
canvas {
  border:1px solid;
}
<div id="sticker" draggable="true">drag me</div>
<canvas id="canvas"></canvas>
Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • I did found another trick because I had to use dragend and not drop event, so on dragend I was getting the position of the MousePos event, but I admit your way of doing is cleaner. Thanks ! – male-gal Aug 09 '18 at 14:56