Je travaille pour une fondation qui sensibilise Internet à l'accessibilité. Pour une présentation, nous souhaitons offrir un petit atelier simulant différentes incapacités/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 le tremblement, ce qui signifie que les mouvements de la main sont tremblants et difficiles à contrôler. Avec cette déficience, il est très difficile de déplacer le curseur de la souris avec précision et d’appuyer sur le bouton de la souris lorsque la souris survole un lien. À la fois des personnes âgées et des personnes atteintes d’une maladie, par exemple: Parkinson, peut souffrir de tremblement.
J'aimerais maintenant déplacer le curseur de la souris d'une manière imprévisible, de sorte qu'il est très difficile pour les personnes de cliquer sur un petit bouton. Comme JavaScript ne permet pas de déplacer directement le curseur de la souris, je cherche d’autres moyens d’y parvenir. Je suis venu avec les idées suivantes:
Alors que la première idée serait plutôt cool, je ne pouvais pas trouver 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 deuxième idée semble un peu maladroite, mais elle produirait l’effet souhaité, je pense.
Quelqu'un a-t-il une autre idée?
J'ai fait une démonstration rapide de quelque chose sur lequel vous devriez pouvoir fonder votre code, en utilisant le API Pointer Lock .
J'ai forké ce repo pointer-lock-demo et l'ai modifié pour ajouter un élément de mouvement aléatoire.
Voici le lien vers ma page GitHub: https://aristocrates.github.io/pointer-lock-demo
Et voici le lien vers mon dépôt: 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 modifiée par rapport à la démo originale est après les lignes
x += movementX * 2;
y += movementY * 2;
J'ai ajouté deux lignes pour représenter un 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, mais j'espère que cela peut vous aider à démarrer.
En fait, j'aime bien les solutions, qui peuvent être basées sur le javascript, car elles sont plus susceptibles d'être liées au Web et de bonnes chances - indépendantes du système d'exploitation. Cependant, je réfléchissais à la façon de résoudre votre problème pour tous les navigateurs, car les solutions javascript, dans ce cas, seront difficiles à ajuster pour tous les navigateurs possibles (je ne suis pas sûr que ce soit possible du tout).
Ainsi, comme vous l’avez mentionné, il existe un autre moyen - c’est-à-dire d’imiter le comportement au niveau du système d’exploitation. Cela a aussi un autre avantage - vous pouvez être sûr que pour le navigateur, il a l’air 100% comme c’était un humain (parce que, c’est le pilote qui envoie le signal). Vous pouvez donc utiliser des solutions basées sur les pilotes/périphériques avec n’importe quel navigateur (ou même dans certaines situations, lorsque javascript est désactivé).
Malheureusement, l'implication du pilote/périphérique entraîne immédiatement une dépendance du système d'exploitation. Donc, pour chaque OS, vous aurez besoin de votre propre solution. Dans cet article, je me suis concentré sur une solution basée sur Linux (donc fonctionnera sous Linux) - et un peu sur Mac OS. Avec Linux, il est possible d'écrire des événements sur un périphérique de manière explicite. 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 le problème soit trouvé ici . Le programme demandera l'amplitude du "tremblement" et sa fréquence (ainsi, combien de fois en micro-secondes séparent les "tremblements"). Pour émuler la situation, il forcera la souris à se déplacer de manière aléatoire pour que 0..X
Pointe dans une direction aléatoire (haut-bas-gauche-en bas à gauche) et attende au hasard 0..Y
Quelques micro-secondes jusqu'au prochain "tremblement", puis X
est l'amplitude de "tremblement" et Y
est la fréquence de "tremblement"
Une autre chose peut être d’adapter le programme à votre système. Le programme est "factice" et ne peut pas détecter la souris lui-même, donc "/dev/input/event4"
Est codé en dur. Pour réaliser ce qui 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 les possibilités sont donc "event3"
Et "event4"
- mais pour votre système, elles peuvent avoir d'autres valeurs. Donc, si cela diffère du code C actuellement utilisé, changez simplement la ligne correspondante (donc, ligne avec int fd = open("/dev/input/event4", O_RDWR);
et placez votre périphérique à la place de event4
)
Une démo gif pour ce programme (fréquence d'image faible, malheureusement, alors gardez une image pas trop grande) ici .
Petite remarque (si vous ne savez pas quoi faire avec le code C) - pour compiler le programme ci-dessus, utilisez simplement:
user@Host:/path$ gcc -std=gnu99 file.c -o m
où file.c
est le nom de votre fichier de code source C, vous obtiendrez un exécutable, appelé m
dans votre répertoire. Très probablement, vous aurez besoin d'autorisations pour écrire directement dans le périphérique de la souris. Vous pouvez donc utiliser Sudo
:
user@Host:/path$ Sudo ./m
La logique restera la même:
C'est ça. Par exemple, Mac OS a sa propre façon de travailler avec la souris (contrairement à Linux, Mac n’a pas procfs
), c’est bien décrit ici .
Ce qui est mieux - des solutions javascript ou orientées vers les appareils - revient à vous, car certaines conditions (telles que l'utilisation simultanée de plusieurs navigateurs ou d'un système d'exploitation) peuvent tout décider dans ce cas. Par conséquent, j’ai fourni des directives avec certains exemples concrets sur la manière de les mettre en œuvre au niveau du système d’exploitation. L'avantage ici est que cette solution est multi-navigateur, mais en tant que coût, nous avons un programme lié au système d'exploitation.
Je l'ai fait comme une blague une fois, sur le Puppy Linux Forum et j'ai obtenu le commentaire suivant:
Les personnes atteintes de la maladie de Parkinson ne penseront pas que c'est drôle !!!
Cure ici est 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
Nommez parkinson_sim et lancez un argument optionnel indiquant le délai entre les secousses pouvant aller de 0,001 à 999,0.
parkinson_sim [time_between_tremors_in_seconds] #default est 0.1
J'ai fait l'erreur de cliquer dessus moi-même au lieu de l'exécuter à partir de la ligne de commande et j'ai rapidement découvert à quel point cela devait être frustrant. Il m'a fallu plusieurs essais pour ouvrir une fenêtre de terminal afin de la tuer.
Votre deuxième idée (masquer le curseur) est à mi-chemin de celle qui, à mon avis, peut vous convenir:
cursor:none
IIRC)Ensuite, vous ajoutez des maths de tremblement au code de votre curseur pour "secouer" le curseur. À vous de déterminer quelles sont les bonnes courbes pour simuler correctement l’entrée des tremblements.
Enfin: pour tous les contrôles que vous programmez (liens, etc.):
Un bonus majeur avec cette implémentation: votre 'curseur tremblant' sera affiché sur les appareils tactiles, qui n'auront pas de curseur pour commencer.
D'après la base JSFiddle de Michael Theriot (très propre et utile!) Tirée des commentaires, en voici une qui bouge constamment avec un balayage distribué normalement autour de l'emplacement actuel du curseur: http://jsfiddle.net/benmosher/0x4mc64v/ 4 /
(Le tableau normal
est le résultat de l'appel de rnorm(100)
dans ma console R. La manière la plus simple que je puisse imaginer dans JS d'échantillonner un entier aléatoire distribué normalement.)
Juste une idée pour que le tremblement soit "correct", vous pouvez enregistrer le mouvement de la souris d'un vrai patient, cela le rend plus authentique lorsque vous dites aux gens d'où proviennent les données.
Là, un script permettant à un chat de suivre le curseur de votre souris, vous pouvez en ajuster un pour laisser un second curseur suivre votre curseur. La page calcule la position du second curseur afin de déterminer si un événement de clic a réussi ou non.
Si vous le pouvez, rendez-vous sur Internet, vous atteindrez ainsi beaucoup plus de personnes que de leur demander d'installer un programme, d'activer le flash ou quoi que ce soit d'autre.
Au lieu d'essayer de déplacer le pointeur, vous pouvez déplacer l'application (page Web) à la place. J'ai écrit un formulaire HTML simple qui contient des champs de saisie. Lorsque vous déplacez la souris sur le formulaire, le formulaire se déplace.
Vous pouvez voir ne démo de la forme en mouvement sur jsfiddle . Essayez de cliquer sur l'un des champs de saisie pour voir l'effet.
J'ai utilisé l'effet jquery shake pour y parvenir. Le javascript de l'effet shake ressemble à ceci et ne fait que déplacer le formulaire de haut en bas chaque fois que la souris est déplacée dessus:
<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 fasse que monter et descendre, je pense que cela a l'effet désiré. Vous pouvez jouer avec les paramètres (direction, temps, distance, ainsi que le "1000" non nommé ci-dessus) pour ajuster le mouvement de la forme.
Pourquoi ne pas utiliser une solution matérielle? Il y a certaines souris sur lesquelles vous pouvez peser, comme la Logitech G500. Au lieu de mettre un poids, installez un petit moteur oscillant qui fait trembler légèrement la souris. Cela simulait également davantage le désordre réel: ce n’est pas seulement le curseur qui tremble, mais la main entière et la souris. Et cela signifie également que vous pouvez afficher d'autres logiciels que les sites Web.
Au lieu d'une souris avec une fente de poids, vous pouvez également coller quelque chose à la souris, mais c'est plus visible.
Alors que vous pensiez le faire avec un pilote de souris personnalisé, je suppose qu’un petit programme exécuté sur le PC ferait l’un ou l’autre? Si tel est le cas, voici un petit extrait de code pour C #, qui déplace le curseur de manière infinie de manière aléatoire, avec une plage de plus moins 5 pixels autour de la position actuelle du curseur. Après chaque déplacement, le programme attend entre 50 ms et 100 ms (inexact!). Le tremblement peut être configuré en adaptant les valeurs pour le déplacement et les pauses. J'ai exécuté cela dans une application console et - en fonction des valeurs - cela m'a causé beaucoup de difficulté à 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);
}
Voici une version Windows de mon script xdotool qui utilise AutoIt . C'était mon tout premier script AutoIt, et il n'a fallu que quelques minutes pour écrire, alors je suis sûr que cela peut être amélioré. Il suffit de sauvegarder avec l'extension .au3 et de l'exécuter avec AutoIt (Run 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
Ou utilisez ma version compilée de ici .
Vous ne pouvez pas vous attendre à ce que quelqu'un soit capable de tenir ses mains parfaitement stables, alors une chose à considérer est:
Mon raisonnement est (attention, je ne suis pas un expert en ux ou en médecine) en réduisant les éléments cliquables, vous créez un problème similaire pour la plupart des personnes qu'une personne atteinte de la maladie de Parkinson rencontrerait avec un site Web quotidien.
DIV
, CSS-cache le curseur en utilisant cursor:none;
left
, top
) avec jQ sur mousemove
margin-left
Et margin-top
En utilisant un setTimeout
(pour que le repositionnement se fasse en douceur, utilisez CSS3 transition
ou faites-le avec jQ .animate()
).Remarque: 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>
Vous pouvez utiliser un costume de simulation pour le vieil âge, tel que celui décrit dans l'article this ... rendre les mains généralement maladroites.
Les parties de bas niveau de la simulation du tremblement sont bien répondues maintenant. Je vais ajouter quelque chose en se concentrant sur le type de tremblement à simuler:
La plupart des réponses implémentent un curseur de souris qui se déplace sur un chemin aléatoire avec une largeur de pas maximale fixe dans les directions X et Y.
Cela devrait fonctionner assez bien pour que vous puissiez difficilement frapper une zone spécifique comme un bouton.
Pour le problème plus général de la simulation des problèmes d’assurance-chômage causés par un tremblement provoqué par la maladie de Parkinson, il serait au moins intéressant de simuler réellement les mouvements de la main de ce type de tremblement.
Je suppose que la marche aléatoire peut ne pas être une très bonne approximation .
Il peut être difficile d’obtenir des données réelles sur les traces de la main du mouvement de tremblement bien sûr, mais il existe certainement des documents sur l’analyse de ce type de tremblement:
Le document Représentation paramétrique du mouvement des mains dans la maladie de Parkinson explique comment tracer au mieux les traces 3D des mouvements des mains.
Le papier est payant, mais l'aperçu en haut à droite, intitulé "Regarde à l'intérieur>" sur l'image du livre, montre quelques tracés intéressants de différentes représentations de données de trace de main .