Simuler un tremblement (par exemple la maladie de Parkinson) avec la souris sur une page web?

je travaille pour une fondation qui sensibilise à l'accessibilité sur internet. Pour une présentation, nous voulons offrir un petit atelier qui simule différents handicaps/déficiences pour les personnes. Cela se fait via un site web créé spécialement pour cette présentation.

l'une des déficiences démontrées est d'avoir un tremblement, ce qui signifie qu'il faut faire face à des mouvements de main tremblants et difficiles à contrôler. Avec cette déficience, il est très difficile de déplacer la souris curseur exactement et pour appuyer sur le bouton de la souris pendant que la souris est sur un lien. Certaines personnes âgées et certaines personnes atteintes d'une maladie, comme la maladie de Parkinson, peuvent souffrir de tremblements.

maintenant, j'aimerais d'une façon ou d'une autre déplacer le curseur de la souris d'une manière imprévisible, de sorte qu'il est très difficile pour les gens de cliquer sur un petit bouton. Parce que JavaScript ne permet pas de déplacer le curseur de la souris directement, je cherche d'autres moyens pour y arriver. J'ai eu les idées suivantes:

  • utilisant un pilote / utilitaire de souris simulant l'agitation de la souris.
  • masquer le curseur de la souris via CSS, placer une animation GIF d'un curseur de souris Tremblant à l'endroit du curseur original (avec JavaScript), puis faire le lien cible cliquable que toutes les quelques secondes pour une seconde ou plus. Cela donnerait au moins l'impression que l'on clique toujours au mauvais moment.

alors que la première idée serait plutôt cool, Je ne pouvais pas trouvez un outil comme celui-ci, que ce soit pour Mac ou pour Windows. Et je n'ai aucune compétence pour programmer une telle chose moi-même.

la seconde idée semble un peu maladroite, mais elle aurait l'effet désiré, je pense.

quelqu'un a une autre idée?

203
demandé sur Matthew Haugen 2014-08-12 11:52:20

13 réponses

j'ai fait une démonstration rapide de quelque chose sur lequel vous devriez pouvoir baser votre code, en utilisant L'API Pointer Lock API .

je bifurquais ce pointeur-lock-démo repo et l'a modifié pour ajouter un mouvement aléatoire de l'élément.

voici le lien vers ma page GitHub: https://aristocrates.github.io/pointer-lock-demo

Et voici le lien de mon repo: https://github.com/aristocrates/pointer-lock-demo

le code javascript d'importance est contenu dans app.js , dans la méthode canvasLoop(e) .

La seule chose que j'ai changé à partir de la démo originale a été après les lignes

x += movementX * 2;
y += movementY * 2;

j'ai ajouté deux lignes pour représenter le mouvement aléatoire:

x += Math.floor(Math.random()*3 - 1);
y += Math.floor(Math.random()*3 - 1);

il y a encore beaucoup de choses que vous pourriez améliorer, vous aider à obtenir commencé.

148
répondu Aristocrates 2014-08-12 08:30:16

Non-façon javascript

en fait, j'aime les solutions, qui peuvent être basées sur javascript, car elles sont plus probablement liées au web, et les bonnes chances sont-OS - indépendantes. Cependant, je pensais à-comment résoudre votre problème pour tous les navigateurs, car les solutions javascript, dans ce cas, sera difficile à ajuster pour tous les navigateurs possibles (Je ne suis pas sûr si c'est possible du tout).

donc, comme vous l'avez mentionné, il y a une autre façon - i.e. pour émuler le comportement au niveau de L'OS. Ceci a un autre avantage aussi - vous pouvez être sûr que pour le navigateur il regarde à 100% comme il était humain (parce que, bien, c'est le pilote qui envoie le signal). Vous pouvez donc utiliser des solutions basées sur le pilote / périphérique avec n'importe quel navigateur (ou même en situation, lorsque javascript est désactivé).

Linux

malheureusement, en impliquant le pilote / périphérique provoque immédiatement une dépendance du système D'exploitation. Donc pour chaque OS vous aurez besoin de solution propre. Dans ce post je suis concentré sur la solution basée sur Linux (donc, va travailler avec Linux) - et Mac OS un peu. Avec Linux, il est possible d'écrire explicitement des événements sur le périphérique, voici donc un exemple de fonction avec boucle principale:

int main()
{
    struct input_event event, event_end;

    int  fd = open("/dev/input/event4", O_RDWR);
    long ma = getInteger("Enter max amplitude [points, 0..50]: ", 0, 50);
    long ta = getInteger("Enter max wait time [usecs , 0..200000]: ", 0, 200000);
    if (fd < 0)
    {
        printf("Mouse access attempt failed:%s\n", strerror(errno));
        return -1;
    }
    memset(&event, 0, sizeof(event));
    memset(&event, 0, sizeof(event_end));
    gettimeofday(&event.time, NULL);
    event.type = EV_REL;
    gettimeofday(&event_end.time, NULL);
    event_end.type = EV_SYN;
    event_end.code = SYN_REPORT;
    event_end.value = 0;
    while(1)
    {
        event.code  = rand() % 2 ? REL_X : REL_Y;
        event.value = (rand() % 2 ? -1 : 1) * randomTill(ma);
        write(fd, &event, sizeof(event));
        write(fd, &event_end, sizeof(event_end));
        usleep(randomTill(ta));
    }
    close(fd);
    return 0;
}

Mon code complet pour la question ici . Le programme demandera l'amplitude du " tremblement "et sa fréquence (ainsi, combien de temps en micro-secondes sont entre les"tremblements"). Pour imiter la situation, il va forcer la souris à se déplacer au hasard pour 0..X points dans la direction aléatoire (haut-bas-gauche-bas) et attendre au hasard 0..Y micro-secondes jusqu'à la prochaine "tremblement", il X est l'amplitude de "tremblement" et Y est la fréquence de" tremblement "

une autre chose pourrait être d'adapter le programme à votre système. Le programme est "dummy" et ne peut pas détecter la souris par lui-même, donc "/dev/input/event4" est codé en dur. Pour réaliser ce peut être un identifiant pour votre système, vous pouvez essayer:

user@host:/path$ cat /proc/bus/input/devices | grep mouse
H: Handlers=mouse0 event3 
H: Handlers=mouse1 event4

Et donc les possibilités sont "event3" et "event4" - mais pour votre système peut avoir d'autres valeurs. Ainsi, si cela est différent de ce qui est actuellement utilisé dans le code C, il suffit de changer la ligne correspondante (donc, la ligne avec int fd = open("/dev/input/event4", O_RDWR); et placez votre appareil à la place de event4 )

Un gif démo pour ce programme (faible taux de trame, malheureusement, de garder une image pas trop grande) ici .

une petite note de côté ( si vous ne savez pas quoi faire avec le code C) - pour compiler le programme ci-dessus, il suffit d'utiliser:

user@host:/path$ gcc -std=gnu99 file.c -o m

file.c est le nom de votre fichier de code source C, alors vous obtiendrez exécutable, appelé m dans votre répertoire. Très probablement, vous aurez besoin de permissions pour écrire dans le dispositif de la souris directement, de sorte que vous pouvez utiliser sudo :

user@host:/path$ sudo ./m

autres OS

La logique restera même chose:

  • trouver un moyen d'accéder à votre souris
  • Écriture de l'événement de mouvement de la souris
  • appliquer la randomisation à votre événement

C'est tout. Par exemple, Mac OS a sa propre façon de travailler avec la souris (pas comme Linux, Mac n'a pas procfs ainsi), il est bien décrit ici .

comme conclusion

ce qui est mieux - javascript ou des solutions orientées périphérique-est à vous, parce que certaines conditions (comme cross - browser ou cross-OS) peut décider de tout dans ce cas. Par conséquent, j'ai fourni des lignes directrices ainsi que certains exemples de travail sur la façon de mettre en œuvre cela au niveau de L'OS. L'avantage ici est que la solution est cross-browser, mais comme un coût, nous avons OS-lié programme.

36
répondu Alma Do 2017-05-23 10:31:25

j'ai fait cela comme une blague une fois, sur le Puppy Linux Forum et j'ai eu le commentaire que:

les gens avec Parkinson ne penseront pas que c'est drôle !!!

Cure ici est tout simplement cntrl-C, heureusement.

voici le script shell qui nécessite xdotool

#!/bin/sh
while :; do
   xdotool mousemove_relative -- -$(($RANDOM % 10)) $(($RANDOM % 10))
   xdotool mousemove_relative -- $(($RANDOM % 10)) -$(($RANDOM % 10))
   sleep ${1:-.1} #adjust this as necessary for effect
done

nom comme parkinson_sim et exécuter avec l'argument optionnel pour le temps entre les tremblements qui peuvent être 0,001 à 999.0.

parkinson_sim [time_between_tremors_in_secondes] #default is 0.1

j'ai fait l'erreur de cliquer dessus moi-même au lieu de l'exécuter depuis la ligne de commande et j'ai vite découvert combien cela devait être frustrant. Il m'a fallu plusieurs essais pour ouvrir un terminal et le tuer.

23
répondu technosaurus 2014-08-13 21:19:52

votre deuxième idée (cacher le curseur) est à mi-chemin d'une qui je pense pourrait bien fonctionner pour vous:

  • masquez le curseur de la souris via CSS, comme vous le suggérez. ( cursor:none IIRC)
  • au lieu d'un gif Tremblant-curseur, utilisez une image + position absolue CSS + JS pour émuler le pointeur de la souris; i.e., suivez la souris autour de la page et plantez l'image du curseur où le curseur de la souris serait nativement.

puis, vous ajoutez quelques mathématiques de tremblement à votre code de curseur, pour "secouer" le curseur. À vous de déterminer ce que les bonnes courbes sont de simuler correctement l'entrée de tremblement.

enfin: pour tous les contrôles que vous programmez (liens, etc.):

  • capturez les évènements de clics, pointez-les vers l'emplacement actuel de "tremor" basé sur l'état de vos courbes de tremor, et les limites-vérifiez vos éléments pour voir si l'Utilisateur a secoué hors de l'élément prévu, ou peut-être dans un élément qui n'était pas prévu.

One major bonus avec cette implémentation: votre 'curseur Tremblant' sera affiché sur les appareils tactiles, qui n'auraient pas de curseur pour commencer.


Edit:

D'après Michael Theriot (très propre et serviable!) base JSFiddle des commentaires, en voici un qui tremble constamment avec un balayage normalement distribué autour du curseur emplacement actuel: http://jsfiddle.net/benmosher/0x4mc64v/4 /

(le tableau normal est le résultat de l'appel de rnorm(100) dans ma console R. La façon la plus simple que je pourrais penser à dans JS pour échantillonner un entier aléatoire normalement distribué.)

16
répondu Ben Mosher 2014-08-19 11:42:37

juste une idée pour obtenir le tremblement "droit", vous pouvez enregistrer le mouvement de la souris d'un vrai patient, ce qui le rend plus authentique quand vous dites aux gens d'où les données proviennent.

il y a des scripts pour laisser un chat suivre votre curseur de souris, vous pouvez en ajuster un pour laisser un deuxième curseur suivre (sauter) votre curseur. La page calcule la position du deuxième curseur, de sorte qu'elle peut également déterminer si un événement de clic est réussi ou non.

si vous le pouvez, s'il vous plaît faites-le basé sur le web, vous atteindrez beaucoup plus de gens de cette façon que de leur demander d'installer un programme ou d'activer flash ou quoi que ce soit.

14
répondu user3934260 2014-08-12 16:25:12

au lieu d'essayer de déplacer le pointeur, vous pouvez déplacer l'application (page web) à la place. J'ai écrit une forme html simple qui a quelques champs d'entrée en elle. Lorsque vous déplacez la souris sur le formulaire, le formulaire se déplace.

, Vous pouvez voir une démonstration de la forme mobile à jsfiddle . Essayez de cliquer sur l'un des champs de saisie pour voir l'effet.

j'ai utilisé l'effet jQuery shake pour atteindre cet objectif. JavaScript pour l'effet de secousse ressemble à cela, et provoque juste la forme de se déplacer de haut en bas chaque fois que la souris est déplacée au-dessus de lui:

<script type="text/javascript">
    $(document).ready(function() {
        $("#toggle").hover(function () {
            $(this).effect("shake", { direction: "up", times: 1, distance: 40}, 1000);
        });
    });
</script>

bien que la forme ne se déplace que de haut en bas, je pense qu'elle a l'effet désiré. Vous pouvez jouer avec les paramètres (direction, temps, distance, ainsi que le non-nommé "1000" ci-dessus) pour modifier le mouvement de la forme.

10
répondu chue x 2014-08-12 23:08:59

Pourquoi ne pas utiliser une solution matérielle? Il y a certaines souris là-bas que vous pouvez mettre des poids, comme le Logitech G500. Au lieu de mettre dans un poids, mettez dans un petit moteur oscillant qui fait trembler légèrement la souris. Cela a aussi simulé le trouble réel plus: ce n'est pas seulement le curseur qui secoue, mais la main entière et la souris. Et cela signifie aussi que vous pouvez montrer d'autres logiciels que les sites web.

au lieu d'une souris avec une fente de poids, vous pouvez aussi juste scotchez quelque chose à la souris, mais c'est plus visible.

10
répondu Nzall 2014-08-14 09:17:36

comme vous pensiez le faire avec un pilote de souris personnalisé, je suppose qu'un petit programme tournant sur le PC ferait l'un ou l'autre? Si c'est le cas, voici un petit extrait pour C#, qui déplace à l'infini le curseur au hasard avec une plage de plus moins 5PX autour de la position actuelle du curseur. Après chaque déplacement le programme attend 50 ms à 100 ms (pas précis!). Les tremblements peuvent être configurés en adaptant les valeurs pour le déplacement et les pauses. J'ai couru ce dans une console application et selon les valeurs qu'il m'a donné un moment difficile d'arrêter le programme.

Random rand = new Random();

while(true)
{
    Cursor.Position = new Point() { X = Cursor.Position.X + rand.Next(11)-5, Y = Cursor.Position.Y + rand.Next(11)-5 };
    Thread.Sleep(rand.Next(50) + 50);
}
6
répondu Paul Kertscher 2014-08-14 09:58:22

Voici une version windows de mon script xdotool qui utilise AutoIt . C'était mon premier script AutoIt, et il n'a fallu que quelques minutes pour écrire, donc je suis sûr qu'il peut être amélioré. Il suffit de sauvegarder avec l'extension .au3 et exécutez-le avec AutoIt (exécutez le Script x86).

HotKeySet("{HOME}", "GStart")
HotKeySet("{PAUSE}", "Gpause")
HotKeySet("{ESC}", "Gexit")

While 1
    Sleep(100)
WEnd

Func Gstart()
While 1
    sleep(100)
    $pos = MouseGetPos()
    $x = $pos[0] + 10 - Random(0, 20, 1)
    $y = $pos[1] + 10 - Random(0, 20, 1)
    MouseMove($x,$y)
Wend
Endfunc


Func Gpause()
While 1
   sleep(100)
Wend
Endfunc

Func Gexit()
    MsgBox(0, "exit box", "Script exited")
    Exit 0
EndFunc

Contrôles

  • à la Maison : Démarrer la simulation.
  • pause : mettre en pause la simulation.
  • Esc : Sortir de la simulation.

Ou d'utiliser ma version compilée à partir de ici .

6
répondu technosaurus 2014-08-15 10:11:18

vous ne pouvez pas vous attendre à ce que quelqu'un puisse tenir ses mains parfaitement stables, donc une chose que vous pouvez considérer est,

  1. expliquez aux utilisateurs ce que vous faites et,
  2. rend les éléments cliquables sur la page de démonstration beaucoup plus petit que la normale.
  3. augmente la sensibilité de la souris sur le système exemple au maximum.

mon raisonnement est (mise en garde, Je ne suis pas un expert en ux ou médecine) en rendant les éléments cliquables plus petits, vous créez un problème similaire pour la plupart des gens qu'une personne atteinte de la maladie de Parkinson ferait face à un site web quotidien.

5
répondu jdphenix 2015-04-07 23:26:05
  • dans votre DIV , CSS-masquer le curseur en utilisant cursor:none;
  • créer un .png curseur image et le déplacer ( left , top ) avec jQ sur mousemove
  • Randomiser l' .png margin-left et margin-top utilisant un setTimeout (pour rendre le re-positionnement lisse utiliser CSS3 transition ou le faire avec jQ .animate() ).

Note: le script ne peut pas savoir si la main est toujours sur la souris ;)

function rand(min, max) {return Math.random() * (max - min) + min;}

var $cursor = $('div img');

$('div').mousemove(function(e) {  // Make .png follow the mouse coordinates
  $cursor.css({
    left: e.pageX,
    top:e.pageY
  });
}).hover(function(e){
  $cursor.toggle(); // Show .png cursor as we enter the DIV
});

(function tremor(){ // Add tremor to .png image
  $cursor.css({
      marginLeft: rand(-15,15), // arm tremor
      marginTop:  rand(-30,30)  // hand contractions
  });
  setTimeout(tremor, rand(50,100));
}());
div{
  position:absolute;
  background:#eee;
  height:100%;
  width:100%;
  cursor:none;
}

div img{
  display:none;
  position:absolute;
  transition: margin 0.2s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div><img src="http://i.stack.imgur.com/KwMGA.png"></div>
4
répondu Roko C. Buljan 2014-12-11 23:05:34

les parties basses de la simulation du tremblement sont bien répondues maintenant. Je vais ajouter quelque chose se concentrant sur le genre de tremblement pour simuler:

la plupart des réponses implémentent un curseur de souris qui se déplace sur un chemin aléatoire avec une certaine largeur de pas maximale fixe dans la direction X et Y.

cela devrait fonctionner assez bien pour le cas d'utilisation de rendre difficile de frapper une zone spécifique comme un bouton.

pour le question plus générale de la simulation de problèmes D'assurance-chômage causés par un tremblement causé par la maladie de Parkinson, il serait au moins intéressant de simuler réellement les mouvements de la main de ce genre de tremblement.

Je soupçonne que la marche au hasard peut ne pas être une très bonne approximation .

peut-être difficiles à se procurer de la main réelle des données de trace de tremblements mouvement, bien sûr, mais il y a certainement des documents sur l'analyse de ce genre de tremblement:

Le papier Représentation Paramétrique du Mouvement de la Main dans la Maladie de Parkinson est sur la façon de meilleur terrain 3D mouvement de la main des traces.

Le papier est paywalled, mais l'aperçu en haut à droite, intitulé "regarder à l'intérieur >" sur l'image du livre, montre quelques intrigues intéressantes de différents représentations de la main trace données .

2
répondu Volker Siegel 2014-08-16 20:54:16