Normalisation de la vitesse de la molette de la souris sur les navigateurs


147

Pour une question différente, j'ai composé cette réponse , y compris cet exemple de code .

Dans ce code, j'utilise la molette de la souris pour effectuer un zoom avant / arrière sur un canevas HTML5. J'ai trouvé du code qui normalise les différences de vitesse entre Chrome et Firefox. Cependant, la gestion du zoom dans Safari est beaucoup, beaucoup plus rapide que dans l'un ou l'autre.

Voici le code que j'ai actuellement:

var handleScroll = function(e){
  var delta = e.wheelDelta ? e.wheelDelta/40 : e.detail ? -e.detail/3 : 0;
  if (delta) ...
  return e.preventDefault() && false;
};
canvas.addEventListener('DOMMouseScroll',handleScroll,false); // For Firefox
canvas.addEventListener('mousewheel',handleScroll,false);     // Everyone else

Quel code puis-je utiliser pour obtenir la même valeur «delta» pour la même quantité de molette de la souris sur Chrome v10 / 11, Firefox v4, Safari v5, Opera v11 et IE9?

Cette question est liée, mais n'a pas de bonne réponse.

Edit : Une enquête plus approfondie montre qu'un événement de défilement 'up' est:

                  | evt.wheelDelta | evt.detail
------------------ + ---------------- + ------------
  Safari v5 / Win7 | 120 | 0
  Safari v5 / OS X | 120 | 0
  Safari v7 / OS X | 12 | 0
 Chrome v11 / Win7 | 120 | 0
 Chrome v37 / Win7 | 120 | 0
 Chrome v11 / OS X | 3 (!) | 0 (peut-être faux)
 Chrome v37 / OS X | 120 | 0
        IE9 / Win7 | 120 | indéfini
  Opera v11 / OS X | 40 | -1
  Opera v24 / OS X | 120 | 0
  Opera v11 / Win7 | 120 | -3
 Firefox v4 / Win7 | undefined | -3
 Firefox v4 / OS X | undefined | -1
Firefox v30 / OS X | undefined | -1

De plus, l'utilisation du trackpad MacBook sous OS X donne des résultats différents même en se déplaçant lentement:

  • Sur Safari et Chrome, la wheelDeltavaleur est de 3 au lieu de 120 pour la molette de la souris.
  • Sur Firefox, detailc'est généralement 2, parfois 1, mais lorsque vous faites défiler très lentement AUCUN ÉVÉNEMENT HANDLER INCENDIE .

La question est donc:

Quelle est la meilleure façon de différencier ce comportement (idéalement sans aucun agent utilisateur ni reniflage du système d'exploitation)?


Désolé, j'ai supprimé ma question. J'écris une réponse maintenant. Avant d'aller beaucoup plus loin, parlez-vous du défilement sur Safari sous Mac OS X? Quand vous faites défiler un peu, ça défile un peu, mais si vous gardez un rythme constant, ça va progressivement plus vite?
Blender

@Blender Je teste actuellement sur OS X, et oui, Safari est la valeur aberrante qui zoome environ 20 fois plus vite que Chrome. Malheureusement, je n'ai pas de souris physique attachée, donc mes tests sont limités à des balayages à deux doigts de distances et de vitesses équivalentes.
Phrogz

J'ai mis à jour la question avec des détails sur le comportement des 5 meilleurs navigateurs sous OS X et Win7. C'est un champ de mines, Chrome sur OS X semblant être la valeur aberrante problématique.
Phrogz

@Phrogz Ne devrait-il pas l'être e.wheelDelta/120?
Šime Vidas le

@ ŠimeVidas Oui, le code que j'ai copié et que j'utilisais était clairement faux. Vous pouvez voir un meilleur code dans ma réponse ci-dessous .
Phrogz le

Réponses:


57

Edit septembre 2014

Étant donné que:

  • Différentes versions du même navigateur sur OS X ont donné des valeurs différentes dans le passé, et peuvent le faire à l'avenir, et que
  • L'utilisation du trackpad sur OS X produit des effets très similaires à l'utilisation d'une molette de souris, mais donne des valeurs d' événements très différentes , et pourtant la différence de périphérique ne peut pas être détectée par JS

… Je ne peux que recommander d'utiliser ce code de comptage simple basé sur les signes:

var handleScroll = function(evt){
  if (!evt) evt = event;
  var direction = (evt.detail<0 || evt.wheelDelta>0) ? 1 : -1;
  // Use the value as you will
};
someEl.addEventListener('DOMMouseScroll',handleScroll,false); // for Firefox
someEl.addEventListener('mousewheel',    handleScroll,false); // for everyone else

La tentative originale d'être correcte suit.

Voici ma première tentative de script pour normaliser les valeurs. Il a deux défauts sur OS X: Firefox sur OS X produira des valeurs 1/3 ce qu'elles devraient être, et Chrome sur OS X produira des valeurs 1/40 ce qu'elles devraient être.

// Returns +1 for a single wheel roll 'up', -1 for a single roll 'down'
var wheelDistance = function(evt){
  if (!evt) evt = event;
  var w=evt.wheelDelta, d=evt.detail;
  if (d){
    if (w) return w/d/40*d>0?1:-1; // Opera
    else return -d/3;              // Firefox;         TODO: do not /3 for OS X
  } else return w/120;             // IE/Safari/Chrome TODO: /3 for Chrome OS X
};

Vous pouvez tester ce code sur votre propre navigateur ici: http://phrogz.net/JS/wheeldelta.html

Les suggestions pour détecter et améliorer le comportement sur Firefox et Chrome sous OS X sont les bienvenues.

Edit : Une suggestion de @Tom est de simplement compter chaque appel d'événement comme un seul mouvement, en utilisant le signe de la distance pour l'ajuster. Cela ne donnera pas d'excellents résultats sous un défilement fluide / accéléré sous OS X, ni ne gérera parfaitement les cas où la molette de la souris est déplacée très rapidement (par exemple, wheelDelta240), mais cela se produit rarement. Ce code est maintenant la technique recommandée indiquée en haut de cette réponse, pour les raisons qui y sont décrites.


@ ŠimeVidas Merci, c'est essentiellement ce que j'ai, sauf que je tiens également compte de la différence de 1/3 sur Opera OS X.
Phrogz

@Phrogz, avez-vous une version mise à jour en septembre 2014 avec tout OS X / 3 ajouté? Ce serait un excellent ajout pour la communauté!
Basj

@Phrogz, ce serait génial. Je n'ai pas de Mac ici pour tester ... (je serais heureux de donner une prime pour ça, même si je n'ai pas beaucoup de réputation moi-même;))
Basj

1
Sur Windows Firefox 35.0.1, wheelDelta n'est pas défini et le détail est toujours 0, ce qui fait échouer le code fourni.
Max Strater

1
@MaxStrater Face au même problème, j'ai ajouté "deltaY" pour surmonter cela dans une direction comme celle-là, je (((evt.deltaY <0 || evt.wheelDelta>0) || evt.deltaY < 0) ? 1 : -1)ne sais pas ce que QA découvre avec cela, cependant.
Brock

28

Voici ma folle tentative de produire un delta cohérent et normalisé entre navigateurs (-1 <= delta <= 1):

var o = e.originalEvent,
    d = o.detail, w = o.wheelDelta,
    n = 225, n1 = n-1;

// Normalize delta
d = d ? w && (f = w/d) ? d/f : -d/1.35 : w/120;
// Quadratic scale if |d| > 1
d = d < 1 ? d < -1 ? (-Math.pow(d, 2) - n1) / n : d : (Math.pow(d, 2) + n1) / n;
// Delta *should* not be greater than 2...
e.delta = Math.min(Math.max(d / 2, -1), 1);

Ceci est totalement empirique mais fonctionne assez bien sur Safari 6, FF 16, Opera 12 (OS X) et IE 7 sur XP


3
Si je pouvais voter encore 10 fois, je le pourrais. Merci beaucoup!
justnorris

Pouvez-vous s'il vous plaît avoir le code fonctionnel complet dans une démo (par exemple jsFiddle)?
adardesign

Y at - il une raison de mettre en cache la event-object en o?
yckart

Non, il n'y en a pas. La ovariable est là pour montrer que nous voulons l'événement d'origine et non un événement encapsulé comme jQuery ou d'autres bibliothèques peut passer aux gestionnaires d'événements.
smrtl

@smrtl pouvez-vous expliquer n et n1? A quoi servent ces variables?
Om3ga

28

Nos amis de Facebook ont ​​mis au point une excellente solution à ce problème.

J'ai testé sur une table de données que je construis en utilisant React et ça défile comme du beurre!

Cette solution fonctionne sur une variété de navigateurs, sur Windows / Mac, et les deux utilisant le trackpad / souris.

// Reasonable defaults
var PIXEL_STEP  = 10;
var LINE_HEIGHT = 40;
var PAGE_HEIGHT = 800;

function normalizeWheel(/*object*/ event) /*object*/ {
  var sX = 0, sY = 0,       // spinX, spinY
      pX = 0, pY = 0;       // pixelX, pixelY

  // Legacy
  if ('detail'      in event) { sY = event.detail; }
  if ('wheelDelta'  in event) { sY = -event.wheelDelta / 120; }
  if ('wheelDeltaY' in event) { sY = -event.wheelDeltaY / 120; }
  if ('wheelDeltaX' in event) { sX = -event.wheelDeltaX / 120; }

  // side scrolling on FF with DOMMouseScroll
  if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) {
    sX = sY;
    sY = 0;
  }

  pX = sX * PIXEL_STEP;
  pY = sY * PIXEL_STEP;

  if ('deltaY' in event) { pY = event.deltaY; }
  if ('deltaX' in event) { pX = event.deltaX; }

  if ((pX || pY) && event.deltaMode) {
    if (event.deltaMode == 1) {          // delta in LINE units
      pX *= LINE_HEIGHT;
      pY *= LINE_HEIGHT;
    } else {                             // delta in PAGE units
      pX *= PAGE_HEIGHT;
      pY *= PAGE_HEIGHT;
    }
  }

  // Fall-back if spin cannot be determined
  if (pX && !sX) { sX = (pX < 1) ? -1 : 1; }
  if (pY && !sY) { sY = (pY < 1) ? -1 : 1; }

  return { spinX  : sX,
           spinY  : sY,
           pixelX : pX,
           pixelY : pY };
}

Le code source peut être trouvé ici: https://github.com/facebook/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js


3
Un lien plus direct qui n'a pas été regroupé vers le code original pour normalizeWHeel.js github.com/facebook/fixed-data-table/blob/master/src/…
Robin Luiten

Merci @RobinLuiten, mise à jour de l'article original.
George

Ce truc est génial. Je viens de l'utiliser et fonctionne comme un charme! Bon travail Facebook :)
perry

Pourriez-vous donner un exemple de son utilisation? Je l'ai essayé et cela fonctionne dans FF mais pas dans Chrome ou IE (11) ..? Merci
Andrew

2
Pour tous ceux qui utilisent npm, il existe un package prêt à l'emploi contenant uniquement ce code déjà extrait de la table de données fixes de Facebook. Voir ici pour plus de détails npmjs.com/package/normalize-wheel
Simon Watson

11

J'ai fait un tableau avec différentes valeurs renvoyées par différents événements / navigateurs, en tenant compte de l' wheel événement DOM3 que certains navigateurs prennent déjà en charge (tableau ci-dessous).

Sur cette base, j'ai créé cette fonction pour normaliser la vitesse:

http://jsfiddle.net/mfe8J/1/

function normalizeWheelSpeed(event) {
    var normalized;
    if (event.wheelDelta) {
        normalized = (event.wheelDelta % 120 - 0) == -0 ? event.wheelDelta / 120 : event.wheelDelta / 12;
    } else {
        var rawAmmount = event.deltaY ? event.deltaY : event.detail;
        normalized = -(rawAmmount % 3 ? rawAmmount * 10 : rawAmmount / 3);
    }
    return normalized;
}

Table pour mousewheel, wheelet les DOMMouseScrollévénements:

| mousewheel        | Chrome (win) | Chrome (mac) | Firefox (win) | Firefox (mac) | Safari 7 (mac) | Opera 22 (mac) | Opera 22 (win) | IE11      | IE 9 & 10   | IE 7 & 8  |
|-------------------|--------------|--------------|---------------|---------------|----------------|----------------|----------------|-----------|-------------|-----------|
| event.detail      | 0            | 0            | -             | -             | 0              | 0              | 0              | 0         | 0           | undefined |
| event.wheelDelta  | 120          | 120          | -             | -             | 12             | 120            | 120            | 120       | 120         | 120       |
| event.wheelDeltaY | 120          | 120          | -             | -             | 12             | 120            | 120            | undefined | undefined   | undefined |
| event.wheelDeltaX | 0            | 0            | -             | -             | 0              | 0              | 0              | undefined | undefined   | undefined |
| event.delta       | undefined    | undefined    | -             | -             | undefined      | undefined      | undefined      | undefined | undefined   | undefined |
| event.deltaY      | -100         | -4           | -             | -             | undefined      | -4             | -100           | undefined | undefined   | undefined |
| event.deltaX      | 0            | 0            | -             | -             | undefined      | 0              | 0              | undefined | undefined   | undefined |
|                   |              |              |               |               |                |                |                |           |             |           |
| wheel             | Chrome (win) | Chrome (mac) | Firefox (win) | Firefox (mac) | Safari 7 (mac) | Opera 22 (mac) | Opera 22 (win) | IE11      | IE 10 & 9   | IE 7 & 8  |
| event.detail      | 0            | 0            | 0             | 0             | -              | 0              | 0              | 0         | 0           | -         |
| event.wheelDelta  | 120          | 120          | undefined     | undefined     | -              | 120            | 120            | undefined | undefined   | -         |
| event.wheelDeltaY | 120          | 120          | undefined     | undefined     | -              | 120            | 120            | undefined | undefined   | -         |
| event.wheelDeltaX | 0            | 0            | undefined     | undefined     | -              | 0              | 0              | undefined | undefined   | -         |
| event.delta       | undefined    | undefined    | undefined     | undefined     | -              | undefined      | undefined      | undefined | undefined   | -         |
| event.deltaY      | -100         | -4           | -3            | -0,1          | -              | -4             | -100           | -99,56    | -68,4 | -53 | -         |
| event.deltaX      | 0            | 0            | 0             | 0             | -              | 0              | 0              | 0         | 0           | -         |
|                   |              |              |               |               |                |                |                |           |             |           |
|                   |              |              |               |               |                |                |                |           |             |           |
| DOMMouseScroll    |              |              | Firefox (win) | Firefox (mac) |                |                |                |           |             |           |
| event.detail      |              |              | -3            | -1            |                |                |                |           |             |           |
| event.wheelDelta  |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.wheelDeltaY |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.wheelDeltaX |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.delta       |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.deltaY      |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.deltaX      |              |              | undefined     | undefined     |                |                |                |           |             |           |

2
Résultats dans différentes vitesses de défilement dans Safari et Firefox actuels sous macOS.
Lenar Hoyt

6

Une autre solution plus ou moins autonome ...

Cela ne prend cependant pas de temps entre les événements. Certains navigateurs semblent toujours déclencher les événements avec le même delta, et les déclencher plus rapidement lors du défilement rapide. D'autres font varier les deltas. On peut imaginer un normaliseur adaptatif qui prend en compte le temps, mais qui serait quelque peu compliqué et difficile à utiliser.

Travail disponible ici: jsbin / iqafek / 2

var normalizeWheelDelta = function() {
  // Keep a distribution of observed values, and scale by the
  // 33rd percentile.
  var distribution = [], done = null, scale = 30;
  return function(n) {
    // Zeroes don't count.
    if (n == 0) return n;
    // After 500 samples, we stop sampling and keep current factor.
    if (done != null) return n * done;
    var abs = Math.abs(n);
    // Insert value (sorted in ascending order).
    outer: do { // Just used for break goto
      for (var i = 0; i < distribution.length; ++i) {
        if (abs <= distribution[i]) {
          distribution.splice(i, 0, abs);
          break outer;
        }
      }
      distribution.push(abs);
    } while (false);
    // Factor is scale divided by 33rd percentile.
    var factor = scale / distribution[Math.floor(distribution.length / 3)];
    if (distribution.length == 500) done = factor;
    return n * factor;
  };
}();

// Usual boilerplate scroll-wheel incompatibility plaster.

var div = document.getElementById("thing");
div.addEventListener("DOMMouseScroll", grabScroll, false);
div.addEventListener("mousewheel", grabScroll, false);

function grabScroll(e) {
  var dx = -(e.wheelDeltaX || 0), dy = -(e.wheelDeltaY || e.wheelDelta || 0);
  if (e.detail != null) {
    if (e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
    else if (e.axis == e.VERTICAL_AXIS) dy = e.detail;
  }
  if (dx) {
    var ndx = Math.round(normalizeWheelDelta(dx));
    if (!ndx) ndx = dx > 0 ? 1 : -1;
    div.scrollLeft += ndx;
  }
  if (dy) {
    var ndy = Math.round(normalizeWheelDelta(dy));
    if (!ndy) ndy = dy > 0 ? 1 : -1;
    div.scrollTop += ndy;
  }
  if (dx || dy) { e.preventDefault(); e.stopPropagation(); }
}

1
Cette solution ne fonctionne pas du tout avec Chrome sur Mac avec Trackpad.
justnorris

@Norris, je crois que c'est le cas maintenant. Je viens de trouver cette question et l'exemple ici fonctionne sur mon macbook avec chrome
Harry Moreno

4

Solution simple et fonctionnelle:

private normalizeDelta(wheelEvent: WheelEvent):number {
    var delta = 0;
    var wheelDelta = wheelEvent.wheelDelta;
    var deltaY = wheelEvent.deltaY;
    // CHROME WIN/MAC | SAFARI 7 MAC | OPERA WIN/MAC | EDGE
    if (wheelDelta) {
        delta = -wheelDelta / 120; 
    }
    // FIREFOX WIN / MAC | IE
    if(deltaY) {
        deltaY > 0 ? delta = 1 : delta = -1;
    }
    return delta;
}

3

Pour la prise en charge du zoom sur les appareils tactiles, inscrivez-vous aux événements gesturestart, gesturechange et gestureend et utilisez la propriété event.scale. Vous pouvez voir un exemple de code pour cela.

Pour Firefox 17, l' onwheelévénement devrait être pris en charge par les versions de bureau et mobiles (selon les documents MDN sur onwheel ). Aussi pour Firefox, peut-être que l' MozMousePixelScrollévénement spécifique à Gecko est utile (bien qu'il soit vraisemblablement obsolète puisque l'événement DOMMouseWheel est maintenant obsolète dans Firefox).

Pour Windows, le pilote lui-même semble générer les événements WM_MOUSEWHEEL, WM_MOUSEHWHEEL (et peut-être l'événement WM_GESTURE pour le panoramique du pavé tactile?). Cela expliquerait pourquoi Windows ou le navigateur ne semble pas normaliser les valeurs d'événement de la molette de la souris lui-même (et pourrait signifier que vous ne pouvez pas écrire de code fiable pour normaliser les valeurs).

Pour la prise en charge des événements onwheel(et non sur la molette) dans Internet Explorer pour IE9 et IE10, vous pouvez également utiliser l' événement standard W3C onwheel . Cependant, une encoche peut avoir une valeur différente de 120 (par exemple, une seule encoche devient 111 (au lieu de -120) sur ma souris en utilisant cette page de test ). J'ai écrit un autre article avec d'autres détails sur les événements de roue qui pourraient être pertinents.

Fondamentalement, dans mes propres tests pour les événements de roue (j'essaie de normaliser les valeurs de défilement), j'ai constaté que j'obtenais des valeurs variables pour le système d'exploitation, le fournisseur du navigateur, la version du navigateur, le type d'événement et le périphérique (souris à molette Microsoft, gestes du pavé tactile d'ordinateur portable , pavé tactile d'ordinateur portable avec zone de défilement, souris magique Apple, boule de défilement puissante Apple, pavé tactile Mac, etc.).

Et devez ignorer une variété d'effets secondaires de la configuration du navigateur (par exemple, Firefox mousewheel.enable_pixel_scrolling, chrome --scroll-pixels = 150), les paramètres du pilote (par exemple le pavé tactile Synaptics) et la configuration du système d'exploitation (paramètres de la souris Windows, préférences de la souris OSX, Paramètres du bouton X.org).


2

C'est un problème avec lequel je me bats depuis quelques heures aujourd'hui, et pas pour la première fois :(

J'ai essayé de résumer les valeurs sur un "balayage" et de voir comment les différents navigateurs rapportent les valeurs, et elles varient beaucoup, avec Safari rapportant des nombres plus importants sur presque toutes les plates-formes, Chrome rapportant beaucoup plus (comme 3 fois plus ) que Firefox, Firefox étant équilibré sur le long terme mais assez différent entre les plates-formes sur les petits mouvements (sur Ubuntu gnome, presque seulement +3 ou -3, il semble qu'il résume des événements plus petits et envoie ensuite un gros "+3")

Les solutions actuelles trouvées en ce moment sont trois:

  1. Le déjà mentionné "n'utilise que le signe" qui tue tout type d'accélération
  2. Reniflez le navigateur jusqu'à la version mineure et la plate-forme, et ajustez-le correctement
  3. Qooxdoo a récemment implémenté un algorithme auto-adaptatif, qui tente essentiellement de redimensionner le delta en fonction des valeurs minimale et maximale reçues jusqu'à présent.

L'idée de Qooxdoo est bonne et fonctionne, et c'est la seule solution que j'ai actuellement trouvée pour être complètement cohérente avec un navigateur croisé.

Malheureusement, il a également tendance à renormaliser l'accélération. Si vous l'essayez (dans leurs démos) et que vous faites défiler de haut en bas à vitesse maximale pendant un moment, vous remarquerez que le défilement extrêmement rapide ou extrêmement lent produit pratiquement la même quantité de mouvement. Au contraire, si vous rechargez la page et ne la glissez que très lentement, vous remarquerez qu'elle défilera assez rapidement ".

C'est frustrant pour un utilisateur Mac (comme moi) qui avait l'habitude de faire des glissements de défilement vigoureux sur le pavé tactile et de s'attendre à atteindre le haut ou le bas de l'objet défilé.

De plus, comme il réduit la vitesse de la souris en fonction de la valeur maximale obtenue, plus votre utilisateur essaie de l'accélérer, plus il ralentira, tandis qu'un utilisateur à «défilement lent» connaîtra des vitesses assez rapides.

Cela fait de cette solution (autrement brillante) une implémentation légèrement meilleure de la solution 1.

J'ai porté la solution sur le plugin jquery mousewheel: http://jsfiddle.net/SimoneGianni/pXzVv/

Si vous jouez avec pendant un certain temps, vous verrez que vous commencerez à obtenir des résultats assez homogènes, mais vous remarquerez également qu'il tend à + 1 / -1 valeurs assez rapidement.

Je travaille maintenant à l'améliorer pour mieux détecter les pics, afin qu'ils n'envoient pas tout "hors échelle". Il serait également intéressant d'obtenir également une valeur flottante entre 0 et 1 comme valeur delta, afin qu'il y ait une sortie cohérente.


1

Il n'y a certainement pas de moyen simple de normaliser tous les utilisateurs de tous les systèmes d'exploitation dans tous les navigateurs.

Cela devient pire que vos variantes listées - sur ma configuration WindowsXP + Firefox3.6, ma molette de souris fait 6 par défilement d'un cran - probablement parce que quelque part j'ai oublié que j'ai accéléré la molette de la souris, soit dans le système d'exploitation ou quelque part dans environ: config

Cependant, je travaille sur un problème similaire (avec une application similaire btw, mais non-canvas) et cela me vient à l'esprit en utilisant simplement le signe delta de +1 / -1 et en mesurant au fil du temps la dernière fois qu'elle a été déclenchée, vous avoir un taux d'accélération, ce est à dire. si quelqu'un fait défiler une fois contre plusieurs fois en quelques instants (ce que je parierais, c'est comment google maps le fait).

Le concept semble bien fonctionner dans mes tests, ajoutez simplement quelque chose de moins de 100 ms à l'accélération.


-2
var onMouseWheel = function(e) {
    e = e.originalEvent;
    var delta = e.wheelDelta>0||e.detail<0?1:-1;
    alert(delta);
}
$("body").bind("mousewheel DOMMouseScroll", onMouseWheel);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.