male-gal
male-gal

Reputation: 33

Dragend client coordinates incoherent on Safari and Firefox

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();
    });
});

Upvotes: 3

Views: 1320

Answers (2)

Matias
Matias

Reputation: 597

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.

Upvotes: 3

Kaiido
Kaiido

Reputation: 136638

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>

Upvotes: 1

Related Questions