首页 文章

用鼠标在网页上模拟震颤(例如帕金森病)?

提问于
浏览
204

我正在为一个提高互联网可访问性意识的基金会工作 . 对于演示文稿,我们希望提供一个小型研讨会,模拟人们的不同残疾/损伤 . 这是通过专门为此演示文稿创建的网站完成的 .

其中一个显示的损伤是震颤,这意味着经历摇晃,难以控制的手部动作 . 由于这种损害,在鼠标悬停在链接上时,很难准确地移动鼠标光标并按下鼠标按钮 . 一些老人和有疾病的人,例如帕金森病,可以患震颤 .

现在我想以某种方式以不可预测的方式移动鼠标光标,这样人们很难点击一个小按钮 . 因为JavaScript不允许直接移动鼠标光标,所以我正在寻找其他方法来实现这一点 . 我提出了以下想法:

  • 使用模拟鼠标抖动的鼠标驱动程序/实用程序 .

  • 通过CSS隐藏鼠标光标,将摇动鼠标光标的GIF动画放置在原始光标的位置(使用JavaScript),然后使目标链接每隔几秒钟只能点击一次左右 . 这至少会给人一种总是在错误的时刻点击的感觉 .

虽然第一个想法很酷,但我无法找到像这样的工具,无论是Mac还是Windows . 我自己编程这样的东西没有任何技巧 .

第二个想法似乎有点笨拙,但我认为它会达到预期的效果 .

有人有另一个想法吗?

13 回答

  • 4

    你的第二个想法(隐藏光标)是我觉得可能适合你的那个想法的一半:

    • 如您所知,通过CSS隐藏鼠标光标 . ( cursor:none IIRC)

    • 使用一些图像CSS绝对定位JS来模拟鼠标指针,而不是抖动光标GIF . 即,在页面上跟随鼠标并将光标图像植入鼠标光标本身所在的位置 .

    然后,在光标代码中添加一些震颤数学,以“摇动”光标 . 由您决定正确模拟震颤输入的正确曲线 .

    最后:对于您编程的任何控件(链接等):

    • 捕获单击事件,根据震颤曲线的状态将它们移动到当前"tremor"位置,然后检查元素以查看用户是否已从想要的元素中抖动,或者可能移动到非预期的元素中 .

    One major bonus 使用此实现:您的'shaky cursor'将显示在触摸设备上,而这些设备上没有光标 .


    编辑:

    基于迈克尔·塞里奥特(Michael Theriot)'s (very clean and helpful!) base JSFiddle from the comments, here',它在当前光标位置周围进行正常分布式扫描时不断颤抖:http://jsfiddle.net/benmosher/0x4mc64v/4/

    normal 数组是在我的R控制台中调用 rnorm(100) 的结果 . 我在JS中可以想到最简单的方法来采样正态分布的随机整数 . )

  • 36

    这是我的xdotool脚本的Windows版本,使用AutoIt . 这是我的第一个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
    

    Controls

    • 主页:开始模拟 .

    • 暂停:暂停模拟 .

    • Esc:退出模拟 .

    或者使用here中的编译版本 .

  • 23

    我在Puppy Linux Forum上做了一次这样的笑话,并得到了评论:

    帕金森病患者不会觉得这很有趣!这里的治疗简直就是cntrl-C,幸运的是 .

    这是shell脚本,需要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
    

    命名为parkinson_sim并使用可选参数运行震颤之间的时间,可以是0.001到999.0 .

    parkinson_sim [time_between_tremors_in_seconds] #default为0.1

    我自己错误地点击它而不是从命令行运行它,并很快发现它一定是多么令人沮丧 . 我花了好几次尝试打开一个终端窗口来杀死它 .

  • 6

    您可以移动应用程序(网页),而不是尝试移动指针 . 我写了一个简单的html表单,里面有一些输入字段 . 将鼠标移动到表单上时,表单会移动 .

    你可以看到a demo of the moving form at jsfiddle . 尝试单击其中一个输入字段以查看效果 .

    我使用jquery shake效果来实现这一点 . 摇动效果的javascript看起来像这样,只要鼠标移到它上面就会使表单上下移动:

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

    虽然表单只是上下移动,但我认为它具有预期的效果 . 您可以使用参数(方向,时间,距离以及上面未命名的“1000”)来调整表单移动 .

  • 10

    模拟震颤的低级部分现在已得到很好的回答 . 我将添加一些关注模拟震颤的东西:

    大多数答案都实现了在随机路径上移动的鼠标光标在X和Y方向上具有一些固定的最大步长 .

    这应该足够好用于使得难以像按钮那样击中特定区域的用例 .

    对于模拟由帕金森病引起的震颤引起的UI问题的更一般性问题,实际模拟这种震颤的手部运动至少是有趣的 .
    我怀疑随机游走可能不是很好 approximation .

    当然可能是震颤运动 hard to get hold of real hand trace data ,但肯定有关于分析这种震颤的论文:

    论文Parametric Representation of Hand Movement in Parkinson’s Disease是关于如何最好地绘制3D手部运动轨迹 .
    这张纸是支付水印的,但是图书右侧的预览标记为"Look Inside >",显示了一些有趣的不同 representations of hand trace data 图 .

  • 10

    当您考虑使用自定义鼠标驱动程序时,我想在PC上运行的一个小程序会做什么?如果是这种情况,这里有一个C#的小片段,它可以随机地无限移动光标,其范围为当前光标位置的正负5px . 每次移位后,程序等待50 ms到100 ms(不准确!) . 可以通过调整位移和暂停的值来配置抖动 . 我在一个控制台应用程序中运行它 - 根据值 - 它让我很难停止程序 .

    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

    我快速演示了一些你希望能够使用Pointer Lock API开启代码的东西 .

    我分叉this pointer-lock-demo repo并修改它以添加随机运动元素 .

    这是我的GitHub页面的链接:https://aristocrates.github.io/pointer-lock-demo
    以下是我的回购链接:https://github.com/aristocrates/pointer-lock-demo

    重要的javascript代码包含在 canvasLoop(e)canvasLoop(e) 方法中 .

    我从原始演示中改变的唯一一件事是在线后

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

    我添加了两行来表示随机移动:

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

    还有很多东西你可以改进,但希望这可以帮助你开始 .

  • 148

    你不能指望任何人能够完全稳定地握住他们的手,所以你可以考虑的一件事是,

    • 向用户解释您正在做的事情,

    • 使演示页面上的可点击元素比平常小得多 .

    • 将示例系统上的鼠标灵敏度提高到最大值 .

    我的理由是(警告,我不是ux或医学方面的专家)通过使可点击元素变小,你为大多数人创造了类似的问题,患有帕金森病的人将面对日常网站 .

  • 5

    为什么不使用硬件解决方案?有一些老鼠,你可以放入重量,如罗技G500 . 而不是放重,放入一个小型摆动马达,使鼠标轻微摇晃 . 这也模拟了实际的障碍:它不仅仅是光标抖动,而是整个手和鼠标 . 它还意味着您可以显示除网站之外的其他软件 .

    而不是带有重量槽的鼠标,你也可以只是将东西粘贴到鼠标上,但这更加引人注目 .

  • 4

    非JavaScript方式

    实际上,我喜欢可能基于javascript的解决方案,因为它们更可能与网络相关,并且很有可能 - 独立于操作系统 . 但是,我正在考虑 - 如何解决所有浏览器的问题,因为在这种情况下,javascript解决方案很难针对所有可能的浏览器进行调整(我不确定它是否可行) .

    因此,正如您所提到的,还有另一种方法 - 即模拟OS级别的行为 . 这也有另一个优点 - 你可以肯定,对于浏览器来说,它看起来是100%,因为它是人类(因为,它是发送信号的驱动程序) . 因此,您可以在任何浏览器中使用基于驱动程序/设备的解决方案(甚至在禁用javascript的情况下) .

    Linux

    不幸的是,涉及驱动程序/设备会立即导致OS依赖因此对于每个操作系统,您都需要自己的解决方案在这篇文章中,我专注于基于Linux的解决方案(因此,将与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;
    }
    

    我发现 full code 的问题是here . 该程序将询问"tremor"的振幅及其频率(因此,微秒之间的时间在"tremors"之间) . 为了模拟情况,它将强制鼠标随机方向随机移动 0..X 点(上下左下)并随机等待 0..Y 微秒直到下一个"tremor", X 是"tremor"的振幅, Y 是"tremor"的频率

    另一件事可能是为您的系统调整程序 . 该程序是"dummy"并且无法自行检测鼠标,因此 "/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); 对齐并放置您的设备而不是 event4

    这个程序的gif演示(遗憾的是低帧率,所以保持图像不要太大)here .

    一点注意事项(如果你不知道如何处理C代码) - 要编译上面的程序,只需使用:

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

    其中 file.c 是您的C源代码文件的名称,然后您将获得可执行文件,在您的目录中名为 m . 您很可能需要直接写入鼠标设备的权限,因此您可以使用 sudo

    user@host:/path$ sudo ./m
    

    其他操作系统

    逻辑将保持不变:

    • 找到一种访问鼠标设备的方法

    • 写移动鼠标的事件

    • 将随机化应用于您的活动

    那个's it. For instance, Mac OS has its own way to work with mouse (not like Linux, Mac hasn' t procfs 也是如此,它被很好地描述了here .

    作为结论

    什么是更好的 - javascript或面向设备的解决方案 - 取决于你,因为某些条件(如跨浏览器或跨操作系统)可能决定在这种情况下的一切 . 因此,我提供了指南以及如何在操作系统级别实现该指南的某些工作示例 . 这里的好处是解决方案是跨浏览器的,但作为成本,我们有操作系统绑定程序 .

  • 2
    • DIV 中,CSS-使用 cursor:none; 隐藏光标

    • 创建.png光标图像并在 mousemove 上使用jQ移动它( lefttop

    • 使用 setTimeout 随机化.png margin-leftmargin-top (使重新定位顺利使用CSS3 transition 或使用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>
    
  • 16

    只是让震颤“正确”的想法,您可以记录真实患者的鼠标移动,这使您在告诉人们数据来源时更加真实 .

    有一个让猫跟随你的鼠标光标的脚本,你可以调整一个让第二个光标跟随(跳转)你的光标 . 页面正在计算第二个光标的位置,因此它还可以确定点击事件是否成功 .

    如果可以的话,请以网络为基础,这样就可以达到更多人的目的,而不是要求他们安装程序或激活闪存或其他任何东西 .

  • 14

    您可以使用老式模拟套装,例如this文章中描述的套装......我怀疑手部震动部分只是一个绑在手腕上的振动马达,加上一些厚手套使手部一般笨拙 .

相关问题