Mis à jour le 08/01/2013
  • Facile

Ce cours est visible gratuitement en ligne.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Les coordonnées de la souris

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Si vous avez déjà eu l'occasion de travailler dans un repère en maths (nan! ne partez pas !), vous savez sûrement déjà ce que sont les coordonnées.
Les coordonnées sont composées de deux nombres ici :

  • l'abscisse, que l'on va souvent nommer x qui contient la distance par rapport au bord gauche de la page ;

  • l'ordonnée, qui sera contenue dans la variable y qui contient la distance par rapport au bord supérieur de la page.

Image utilisateurVoir un exemple animé

Pour connaître la position de la souris sur l'écran, on va chercher à récupérer ces deux distances. :)

La variable event

La position de la souris se récupère via une variable particulière qui s'appelle event. Mais n'essayez pas d'utiliser cette variable directement : elle n'existe pas d'habitude. Pour l'utiliser, il faut déclencher un évènement.
Tous les évènements qui ont un rapport avec la souris marchent :
onclick, ondbclick, onmousemove, onmousedown, onmouseup, etc.

La variable event indiquera donc la position de la souris au moment du onclick au moment où cet évènement est déclenché (donc à chaque clic, cela va créer une nouvelle variable event).

Trois cas se présentent suivant la façon dont vous associez des évènements aux objets HTML de votre page.

Cas n°1 : assigner un évènement en HTML

Si pour ajouter un évènement à votre page, vous l'écriviez dans le code HTML :

<script type="text/javascript">
function onclick_page()
{
  
}
</script><input type="button" id="bouton_click" onclick="onclick_page();" value="Click!" />

vous avez juste à rajouter cette nouvelle variable :

<script type="text/javascript">
function onclick_page(event)
{
  //ici, on va se servir de la variable event ^^
  alert(event);
}
</script>
<input type="button" id="bouton_click" onclick="onclick_page(event);" value="Click!" />
Cas n°2 : assigner un évènement dynamiquement avec la méthode DOM-0

Le DOM-0 permet d'ajouter des évènements en modifiant une variable :

document.getElementById('bouton_click').onclick = onclick_page;

Il va falloir modifier légèrement le début de la fonction. La plupart des navigateurs transmettent bien une variable event à la fonction, sauf Internet Explorer où la variable event est globale. Pour concilier tous les navigateurs, il va falloir préciser tous les cas possibles :

function onclick_page(event)
{
  if( window.event)
    event = window.event;
  //On peut aussi écrire: event = event || window.event;
  //ici, on va se servir de la variable event ^^
  alert(event);
}
Cas n°3 : assigner un évènement dynamiquement avec addEventListener (DOM-2)

Si vous utilisez la fonction addEventListener (et attachEvent pour Internet Explorer), il n'y a pas grand-chose à modifier :

function onclick_page(event)
{
  //ici, on va se servir de la variable event ^^
  alert(event);
}
var objet = document.getElementById('bouton_click');
if( objet.addEventListener)
  objet.addEventListener('click',onclick_page,true);
else  //pour ie
  objet.attachEvent('onclick',onclick_page);

Personnellement, j'ai écrit une petite fonction pour ne pas avoir à toujours taper cette condition :

function addEvent(obj,event,fct)
{
        if( obj.attachEvent)
                obj.attachEvent('on' + event,fct);
        else
                obj.addEventListener(event,fct,true);
}

Comme ça, on pourra utiliser cette fonction à chaque fois que l'on veut rajouter un évènement, proprement. :)

addEvent(document.getElementById('bouton_click'),'click',onclick_page);

Les coordonnées

Notre but principal est de récupérer les coordonnées de la souris ; pour cela, on a récupéré la variable event et celle-ci possède les propriétés qui nous intéressent : clientX et clientY.

Aller, un premier exemple avec onclick :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>test coordonnées</title>
<script type="text/javascript">function onclick_page(event)
{
  var x = event.clientX;
  var y = event.clientY;
  alert('Vous avez cliqué au point de coordonnés: ' + x + ', ' + y );
}</script>

</head>
<body onclick="onclick_page(event);">

</body>
</html>

Tester ce code

Exercice

Au lieu d'ouvrir une boîte de dialogue (alert), faites en sorte que le message apparaisse dans une zone de texte dans la page web. Ensuite, remplacez l'évènement onclick par un évènement onmousemove. Les coordonnées vont être mises à jour à chaque déplacement de la souris !

Correction

Si vous avez besoin d'un moyen pour connaître l'état d'une variable (pour déboguer), il faudra utiliser des fonctions comme console.debug (pour firebug).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>test coordonnées</title>
<script type="text/javascript">
function souris(event)
{
  var x = event.clientX;
  var y = event.clientY;
  document.getElementById('coordonnes').value = x + ', ' + y;
}
</script>

</head>
<body onmousemove="souris(event);">
  <div id="info">
    Coordonnées de la souris : <input type="text" id="coordonnes" value="inconnues" readonly="readonly" />
  </div>
</body>
</html>

Tester ce code

Position absolue

On peut placer une balise HTML exactement là où on le souhaite grâce au style CSS et à l'utilisation des positions absolues. Il suffit alors d'indiquer à l'aide des propriétés left et top l'abscisse et l'ordonnée de l'élément.
Par exemple, pour placer le div qui porte l'id info (dans l'exemple précédent), à 30 pixels du bord gauche et à 100 pixels en dessous de la page, on ferait :

#info
{
  position: absolute;
  left: 30px;
  top: 100px;
}

Oui, oui, mais on va faire ce placement en Javascript grâce au DOM !

Petits rappels
  • Pour récupérer l'élément HTML qui porte l'id blabla :

    var element = document.getElementById('blabla');
  • Pour modifier le style CSS d'un élément, par exemple background-color :

    element.style.backgroundColor = '#FFF'; //Pour chaque tiret, on remplace la lettre suivante par une majuscule

Modifiez le dernier exemple pour qu'en plus d'afficher les coordonnées de la souris, il déplace le <div id="info"> au même endroit que la souris.

Correction

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>test coordonnées</title>
<style type="text/css">
#info
{
        background-color: #DDD;
        border: 1px solid #000;
}
</style>
<script type="text/javascript">
function souris(event)
{
  var x = event.clientX;
  var y = event.clientY;
  document.getElementById('coordonnes').value = x + ', ' + y;
  //Nouveau code :
  var element = document.getElementById('info');
  element.style.position = 'absolute';
  element.style.left = x + 'px';
  element.style.top = y + 'px';
}
</script>

</head>
<body onmousemove="souris(event);">
        <div id="info">
                Coordonnées de la souris : <input type="text" id="coordonnes" value="inconnues" readonly="readonly" />
        </div>
</body>
</html>

Tester : le bloc suit la souris

Fil rouge : gestion des fenêtres

On va commencer notre script qui imite des fenêtres. Il nous faut déjà un bloc (div) jouant le rôle de fenêtre déplaçable ainsi qu'un autre bloc pour la barre de titre. Enfin, un petit bouton pour minimiser pourrait également servir.

On obtient donc un code HTML de ce genre :

<div id="fenetre">
  <div class="barre" onmousedown="start_drag(document.getElementById('fenetre'), event);">
    <button class="close" onclick="document.getElementById('fenetre').parentNode.removeChild(document.getElementById('fenetre'));">X</button>
    Titre
  </div>
  Contenu de la page !!
</div>

J'ai déjà rajouté un évènement onmousedown sur la barre de titre, qui va appeler notre fonction et déclencher le début du déplacement.

On stockera l'élément en cours de déplacement dans une variable : dragged (c'est moi qui ai décidé de l'appeler comme ça :p ) et on va avoir besoin de deux autres évènements :

  • onmousemove pour déplacer l'élément à chaque mouvement de souris ;

  • onmouseup qui se chargera d'arrêter le déplacement lorsqu'on lâchera la souris.

Je vous laisse essayer un peu avant de vous montrer comment j'ai fait (il y a sûrement plusieurs méthodes).

Correction

Ci-dessous le style CSS ajouté ; sûrement une question de goût et le mien est assez mauvais.
Voilà mon résultat (avec les artistes que vous êtes, je suis sûr que vous avez fait mieux :p ) :

Image utilisateur
#fenetre
{
        position: absolute;
        width: 400px;
        height: 200px;
        background-color: #DDD;
        border: 1px solid #000;
}

.close
{
        float: right;
        background-color: #EEE;
}

.barre
{
        width: 100%;
        height: 30px;
        background-color: #00D;
        color: #FFF;
        cursor: hand;
}

Pour le code Javascript, j'ai décidé de commencer à rajouter les évènements (onmousemove et onmousedown) dynamiquement sans avoir à toucher au code HTML.
Pour "capter" le maximum de déplacement, on va fixer ces évènements sur l'élément HTML le plus haut possible : document.

var dragged = null; //L'élément en cours de drag
//Lorsque dragged = null, il n'y a rien en cours de déplacement


function start_drag(objet,event)
{
  dragged = objet; //On le place comme objet en cours
}

function drag_onmousemove(event)  //Lorsque la souris se déplace
{
  if( dragged ) //s'il n'y a pas d'élément en cours de déplacement, inutile de le déplacer :) 
  {
    var x = event.clientX;
    var y = event.clientY;
    dragged.style.position = 'absolute';
    dragged.style.left = x + 'px';
    dragged.style.top = y + 'px';
  }
}

function drag_onmouseup(event)  //Lorsque le bouton de la souris est relâché
{
  dragged = null; //On arrête le drag & drop
}

//Ma petite fonction "magique" pour ajouter des évènements
function addEvent(obj,event,fct)
{
  if( obj.attachEvent)
     obj.attachEvent('on' + event,fct);
  else
     obj.addEventListener(event,fct,true);
}

//On ajoute les deux évènements avec la méthode
addEvent(document,'mousemove',drag_onmousemove);
addEvent(document,'mouseup',drag_onmouseup);

Tester la première version du script de fenêtres

Comportement par défaut

Un bug assez gênant apparaît pendant le déplacement : le texte est sélectionné, et c'est assez moche comme effet. :-°
De la part du navigateur, c'est assez logique : quand on enfonce un bouton de la souris et qu'on la déplace, c'est pour sélectionner du texte, c'est ce qu'il doit se passer par défaut.
Ici, ce n'est pas ce qu'on souhaite faire et il faut donc annuler ce comportement par défaut :

//des lignes à rajouter dans start_drag:
event.returnValue = false; //Pour Internet Explorer
if( event.preventDefault ) event.preventDefault();

(Cela ressemble beaucoup à return false; que l'on voit souvent.)

Prendre en compte le scroll

Si vous avez eu l'occasion de tester ce code et que vous avez scrollé (bougé l'ascenseur, vertical ou horizontal), vous avez sûrement remarqué un décalage . Il faut donc rajouter à x et y la position actuelle des ascenseurs (horizontaux et verticaux):

var x = event.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft);
var y = event.clientY + (document.body.scrollTop || document.documentElement.scrollTop);

Et voilà, on sait déplacer un bloc en fonction des mouvements de la souris mais ...

Oui mais... la souris reste toujours accrochée au même endroit, c'est nul !! :(

Il faut garder le même décalage entre la souris et le bloc tout au long du déplacement !

Exemple de certificat de réussite
Exemple de certificat de réussite