web-dev-qa-db-fra.com

event.offsetX dans Firefox

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script language="javascript">
function main(){
    var canvas = document.getElementById("canvas");
    canvas.addEventListener("mousemove", function(e){
        if (!e) e = window.event;
        var ctx = canvas.getContext("2d");

        var x = e.offsetX;
        var y = e.offsetY;

        ctx.fillRect(x, y, 1, 1);
    });
}
</script>
</head>
<body onload="main();">
<div style="width: 800px; height: 600px; -webkit-transform: scale(0.75,0.75); -moz-transform: scale(0.75,0.75)">
    <canvas id="canvas" width="400px" height="400px" style="background-color: #cccccc;"></canvas>
</div>
</body>
</html>

Veuillez prendre en compte l'exemple rapide et sale ci-dessus . Veuillez noter que ma toile est contenue par un div ayant une transformation d'échelle appliquée . Le code ci-dessus fonctionne parfaitement sur tout navigateur basé sur un kit Web. En déplaçant la souris, il dessine des points sur le canevas . Malheureusement, dans Firefox, son modèle d’événement ne prend pas en charge les propriétés offsetX/Y . Comment puis-je transformer les coordonnées de la souris à partir de (éventuellement) event.clientX (ce qui est également supporté dans firefox) en coordonnées relatives de la toile, en tenant compte de la position de la toile, de la transformation, etc.? Merci Luca.

44
lviggiani

Essayez layerX, layerY

var x = (e.offsetX === undefined) ? e.layerX : e.offsetX;
var y = (e.offsetY === undefined) ? e.layerY : e.offsetY;

VIOLON

34
Musa

À partir de page de suivi des bogues JQuery - voici un joli polyfill:

var offX  = (e.offsetX || e.pageX - $(e.target).offset().left);

.. où e est l'événement renvoyé par un événement jQuery. Evidemment, seulement si Jquery est déjà sur votre projet, sinon vous devrez faire les choses offset() manuellement.

77
dmp

Malheureusement, aucune solution n'a fonctionné pour moi.

J'ai trouvé une bonne implémentation ici :

var target  = e.target || e.srcElement,
              rect    = target.getBoundingClientRect(),
              offsetX = e.clientX - rect.left,
              offsetY  = e.clientY - rect.top;

e.offsetX   = offsetX;
e.offsetY   = offsetY;
19
Vyacheslav Cotruta

Malheureusement, offsetX et layerX ne sont pas exactement identiques puisque offsetX correspond au décalage dans l'élément actuel, mais layerX correspond au décalage par rapport à la page. Voici un correctif que j'utilise actuellement pour cela:

function fixEvent(e) {
    if (! e.hasOwnProperty('offsetX')) {
        var curleft = curtop = 0;
        if (e.offsetParent) {
           var obj=e;
           do {
              curleft += obj.offsetLeft;
              curtop += obj.offsetTop;
           } while (obj = obj.offsetParent);
        }
        e.offsetX=e.layerX-curleft;
        e.offsetY=e.layerY-curtop;
    }
    return e;
}
15
Tom Fredian

Il y a un bug dans la solution de Musa: imaginez ce qui se passe si e.offsetX === 0 et e.layerX === undefined...

var x = e.offsetX || e.layerX; // x is now undefined!

Une version plus robuste est la suivante:

var x = e.hasOwnProperty('offsetX') ? e.offsetX : e.layerX;
var y = e.hasOwnProperty('offsetY') ? e.offsetY : e.layerY;

Ou bien, parce que nous pouvons supposer que si offsetX est défini, offsetY sera aussi:

var hasOffset = e.hasOwnProperty('offsetX'),
    x         = hasOffset ? e.offsetX : e.layerX,
    y         = hasOffset ? e.offsetY : e.layerY;
11
Mark Whitaker

offset ne traduit pas directement dans layer; la propriété offset ne représente pas la marge de l'élément. Le code ci-dessous devrait en tenir compte.

function(e) {
    var x = e.offsetX, y = e.offsetY;
    if(e.hasOwnProperty('layerX')) {
      x = e.layerX - e.currentTarget.offsetLeft;
      y = e.layerY - e.currentTarget.offsetTop;
    }
}
4
EnotionZ

Aucune des versions non-jquery ne fonctionne complètement pour différentes raisons. Avec votre aide, cependant, cela a fonctionné:

if(!event.hasOwnProperty('offsetX')) {
    event.offsetX = event.layerX - event.currentTarget.offsetLeft;
    event.offsetY = event.layerY - event.currentTarget.offsetTop;
}
3
brannigan

J'ai trouvé que toutes les réponses postées ici sauf les deux dernières réponses d'EnotionZ et de laz brannigan (auparavant avec zéro vote chacune) étaient fausses dans les cas où plusieurs éléments étaient contenus dans une div. Dans mon cas, j'ai plusieurs éléments de toile à l'intérieur d'une seule div et j'écoute chaque toile séparément.

Après de nombreux essais et erreurs, la réponse correcte finale à laquelle je suis arrivé, qui fonctionne parfaitement et de manière identique pour moi dans FireFox et Chrome est la suivante:

//inside my mouse events handler:
var anOffsetX = (inEvent.offsetX !== undefined) ? inEvent.offsetX : (inEvent.layerX - inEvent.target.offsetLeft);
var anOffsetY = (inEvent.offsetY !== undefined) ? inEvent.offsetY : (inEvent.layerY - inEvent.target.offsetTop);

Cela fonctionnera probablement aussi pour les marges et comme EnotionZ l’indique dans son message, mais je n’ai pas essayé.

3
jeremykentbgross

Mais que ferez-vous s'il n'y a pas de layerX, layerY?

 var xe=e.offsetX,ye=e.offsetY;
  if(!xe){
     xe=e.clientX - $(e.target).offset().left;
  }
  if(!ye){
    ye= e.clientY - $(e.target).offset().top;
  }
2
Abdennour TOUMI

Si certains ont encore besoin de solutions, celle-ci fonctionne parfaitement dans Firefox: 

var x = e.offsetX || e.originalEvent.layerX;
var y = e.offsetY || e.originalEvent.layerY;
0
Crisoforo Gaspar