用鼠标在网页上模拟震颤(从帕金森氏病)?
我正在为提高互联网可访问性的基础而工作。 对于演示,我们想要提供一个小型的研讨会,模拟不同的残疾/人身伤害。 这是通过专门为此演示文稿创build的网站完成的。
其中一个显示的障碍是发生震颤,这意味着经历了颤动,难以控制的手部动作。 有了这种损伤,要精确地移动鼠标光标并在鼠标hover在链接上时按下鼠标button是非常困难的。 一些老年人和患有帕金森氏病的人都会患上震颤。
现在我想以某种不可预知的方式移动鼠标光标,所以人们很难点击一个小button。 由于JavaScript不允许直接移动鼠标光标,我正在寻找其他方法来实现这一点。 我想出了以下想法:
- 使用模拟鼠标抖动的鼠标驱动程序/实用程序。
- 通过CSS隐藏鼠标光标,将摇动的鼠标光标的GIFanimation放置在原始光标处(使用JavaScript),然后使目标链接每隔几秒钟就可以点击一秒左右。 这至less会给人一种总是在错误的时刻点击的感觉。
虽然第一个想法是相当酷的,我无法find这样的工具,无论是Mac或Windows。 而且我自己也没有任何编程这种东西的技能。
第二个想法似乎有点笨拙,但是我认为它会达到预期的效果。
有没有人有另一个想法?
我做了一个快速演示,希望能够使用指针lockingAPI来代码。
我分叉这个指针locking演示回购,并修改它添加一个随机移动元素。
这里是我的GitHub页面的链接: https : //aristocrates.github.io/pointer-lock-demo
这里是我的回购链接: https : //github.com/aristocrates/pointer-lock-demo
在canvasLoop(e)
方法中, app.js
中包含重要的javascript代码。
我从原来的演示改变的唯一的东西是在线之后
x += movementX * 2; y += movementY * 2;
我添加了两行代表随机移动:
x += Math.floor(Math.random()*3 - 1); y += Math.floor(Math.random()*3 - 1);
还有很多东西你可以改善,但希望这可以帮助你开始。
非JavaScript的方式
实际上,我喜欢可能基于javascript的解决scheme,因为它们更有可能与Web相关,而且很可能与OS无关。 不过,我正在考虑如何解决所有浏览器的问题,因为在这种情况下,JavaScript解决scheme将很难适应所有可能的浏览器(我不确定是否有可能)。
所以,正如你所提到的,还有另一种方法 – 即模仿操作系统级别的行为。 这也有另一个好处 – 你可能确定浏览器看起来像是人类的100%(因为它是发送信号的驱动程序)。 所以你可以使用基于驱动程序/设备的解决scheme与任何浏览器(甚至在情况下,当JavaScript被禁用)。
Linux的
不幸的是,涉及驱动程序/设备会立即引起操作系 所以对于每个操作系统,你都需要自己的解决 在这篇文章中,我专注于基于Linux的解决scheme(所以,将与Linux一起工作)以及Mac OS。 使用Linux,可以显式地将事件写入设备,下面是带有主循环的函数示例:
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; }
我在这里find完整的代码 。 该程序将要求“震颤”的幅度和频率(因此,在“震颤”之间的微秒内有多less次)。 为了模拟情况,迫使鼠标随机移动0..X
个点(上下左下),随机等待0..Y
微秒,直到下一个“震颤”, X
是振幅“震颤”, Y
是“震颤”
另一件事可能是适应你的系统的程序。 程序是“哑”, "/dev/input/event4"
检测鼠标,所以"/dev/input/event4"
是硬编码的。 要了解可能是您的系统的标识符,您可以尝试:
user@host:/path$ cat /proc/bus/input/devices | grep mouse H: Handlers=mouse0 event3 H: Handlers=mouse1 event4
所以可能性是"event3"
和"event4"
– 但是对于可能具有其他值的系统。 所以,如果这与目前在C代码中使用的不同,只需要改变相应的行(所以,用int fd = open("/dev/input/event4", O_RDWR);
并且把你的设备replace成event4
)
这个程序的gif演示(低帧率,不幸的是,所以保持图像不要太大)。
一个小方面说明(如果你不知道如何处理C代码) – 编译上面的程序,只需使用:
user@host:/path$ gcc -std=gnu99 file.c -om
其中file.c
是你的C源代码文件的名字,那么你会得到可执行文件,在你的目录中调用m
。 您很可能需要直接写入鼠标设备的权限,因此您可以使用sudo
:
user@host:/path$ sudo ./m
其他操作系统
逻辑将保持不变:
- find一种访问您的鼠标设备的方法
- 写移动鼠标的事件
- 随机应用到你的事件
而已。 例如,Mac OS有自己的方式来使用鼠标(不像Linux,Mac也没有procfs
), 这里有很好的描述。
作为结论
有什么更好的 – JavaScript或面向设备的解决scheme – 取决于你,因为某些条件(如跨浏览器或跨OS)可能决定在这种情况下的一切。 因此,我已经提供了一些指导方针以及如何在操作系统级别上实现的一些工作示例。 这样做的好处是该解决scheme是跨浏览器的,但作为一个成本,我们有OS绑定程序。
我曾经在Puppy Linux论坛上做过这个笑话,并得到了以下评论:
帕金森氏症患者不会觉得这很有趣!
这里治愈的只是cntrl-C,幸运的是。
这是需要xdotool的shell脚本
#!/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
命名为parkinson_sim,运行时间可以是0.001到999.0之间的可选参数。
parkinson_sim [time_between_tremors_in_seconds] #default是0.1
我自己点击它的错误,而不是从命令行运行它,很快发现它是多么的令人沮丧。 我花了几次尝试打开一个terminal窗口来杀死它。
你的第二个想法(隐藏光标)是我认为可以为你工作的一半。
- 按照你的build议,通过CSS隐藏鼠标光标。 (
cursor:none
IIRC) - 使用一些图像+ CSS绝对定位+ JS来模拟鼠标指针,而不是使用不稳定光标的GIF。 即按照鼠标在页面周围,植物鼠标光标本来将光标图像。
然后,给游标代码添加一些震颤math,以“摇动”游标。 由您决定什么正确的曲线正确模拟震颤input。
最后:无论你正在编程的控制(链接等):
- 捕获点击事件,根据您的震颤曲线的状态将它们推送到当前的“震颤”位置,并且边界检查您的元素,以查看用户是否已经摆脱了预期的元素,或者可能成为未预期的元素。
这个实现的一个主要的好处是:你的“不稳定的光标”将被显示在触摸设备上,这将不具有光标开始。
编辑:
根据评论中的Michael Theriot(非常干净和有用的)JSFiddle,下面是一个不断震动当前光标位置周围正常分布的扫描: http : //jsfiddle.net/benmosher/0x4mc64v/4/
( normal
数组是在我的R控制台中调用rnorm(100)
的结果。我可以想到在JS中用最简单的方法来抽样一个正态分布的随机整数。
只是一个想法,让震颤“正确”,你可以logging一个真正的病人的鼠标移动,这使得它更真实的时候,你告诉人们的数据来自何处。
有一个让猫跟随你的鼠标光标的脚本,你可以调整一个让第二个光标跟随(跳转)你的光标。 该页正在计算第二个游标的位置,因此它也可以确定点击事件是否成功。
如果可以的话,请把它build立在networking基础之上,而不是要求他们安装程序或者激活闪存或者其他任何东西。
而不是试图移动指针,而是移动应用程序(网页)。 我写了一个简单的html表单,里面有一些input字段。 当您将鼠标移动到窗体上时,表单将移动。
您可以在jsfiddle中看到移动窗体的演示 。 尝试点击其中一个input字段来查看效果。
我使用jQuery的抖动效果来实现这一点。 摇动效果的JavaScript看起来像这样,只要鼠标移到它上面,窗体就会上下移动:
<script type="text/javascript"> $(document).ready(function() { $("#toggle").hover(function () { $(this).effect("shake", { direction: "up", times: 1, distance: 40}, 1000); }); }); </script>
虽然forms只是上下移动,但我认为它有预期的效果。 您可以使用参数(方向,时间,距离以及未命名的“1000”)来调整窗体移动。
为什么不使用硬件解决scheme? 有一些老鼠在那里,你可以把重量,像罗技G500。 不要把重物放在一个小的摆动马达,使鼠标轻微抖动。 这也模拟了更多的实际障碍:它不仅仅是摇动的光标,而是整个手和鼠标。 这也意味着你可以显示除网站以外的其他软件。
而不是带有重量插槽的鼠标,您也可以将某些东西粘贴到鼠标上,但这更明显。
正如你正在考虑用自定义的鼠标驱动程序,我想在PC上运行一个小程序会做? 如果是这样的话,这是一个C#的小代码片断,在当前光标位置周围随机移动光标,范围为正负5px。 每次移位后程序等待50毫秒到100毫秒(不准确!)。 可以通过调整位移和暂停的值来configuration摇摆。 我在一个控制台应用程序中运行了这个程序,根据这些值的不同,这让我很难停止程序。
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); }
这是我使用AutoIt的 xdotool脚本的Windows版本。 这是我第一次使用AutoIt脚本,写了只需几分钟,所以我相信它可以改进。 只需使用扩展名.au3保存并使用AutoIt(运行脚本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
控制
- 主页:开始模拟。
- 暂停:暂停模拟。
- Esc:退出模拟。
或从这里使用我的编译版本。
你不能期望任何人能够稳定地握住他们的双手,所以你可以考虑的是,
- 向用户解释你在做什么,
- 使演示页面上的可点击元素比平常小得多。
- 将示例系统上的鼠标灵敏度提高到最大。
我的推理是(要注意,我不是专家,也不是医学专家)通过使可点击的元素变得更小,对于患有帕金森病的人而言,大多数人都会面对日常的网站,这就造成了类似的问题。
你可以使用一个老式的仿真套装,比如这篇文章中描述的仿真套装……我怀疑这个手震颤的部分只是一个绑在手腕上的振动电机,加上一些厚手套,使手一般笨拙。
- 在你的
DIV
,使用cursor:none;
来隐藏cursor:none;
- 创build一个.png光标图像,并用鼠标移动它(
left
,top
)jQ - 使用
setTimeout
随机化png的margin-left
和margin-top
(使重新定位平滑使用CSS3transition
或使用jQ.animate()
)。
注意:脚本不知道手是否仍然在鼠标上;)
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>
现在已经很好地回答了模拟震颤的低级部分。 我会添加一些重点的震颤来模拟:
大多数答案实现了鼠标光标在X和Y方向上的固定最大步长的随机path上移动。
这应该适用于使得难以像button那样击中特定区域的用例。
对于模拟帕金森病震颤导致的UI问题的更普遍的问题,实际上模拟这种震颤的手部运动至less是有趣的。
我怀疑随机游走可能不是一个很好的近似 。
当然可能很难掌握震颤运动的实际手迹数据 ,但肯定有分析这种震颤的论文:
帕金森病手部运动的参数化表示是关于如何最好地绘制3D手部运动轨迹。
这篇论文是有支付意义的,但在书籍图像上标注“Look Inside>”的右上angular预览显示了一些有趣的手迹数据的不同表示 。