我为一个基金会工作,该基金会旨在提高人们对互联网无障碍的认识。为了演示,我们想提供一个小型研讨会,模拟不同的残疾/缺陷。这是通过一个专门为这次演示创建的网站来完成的。

其中一个被证实的缺陷是有震颤,这意味着经历颤抖,难以控制的手部运动。由于这种缺陷,当鼠标在链接上时,很难准确地移动鼠标光标并按下鼠标按钮。一些老年人和有疾病的人,如帕金森氏症患者,都可能患有震颤。

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

使用模拟鼠标晃动的鼠标驱动程序/实用程序。 通过CSS隐藏鼠标光标,在原始光标的位置放置一个晃动的鼠标光标的GIF动画(使用JavaScript),然后让目标链接每隔几秒就可以点击一次,持续一秒钟左右。这至少会给人一种感觉,好像总是在错误的时刻点击。

虽然第一个想法很酷,但我找不到这样的工具,无论是Mac还是Windows。我自己也没有任何编程技能。

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

有人有别的想法吗?


当前回答

As you were thinking about doing it with a custom mouse driver I suppose a small program running on the PC would do either? If this is the case, here is a small snippet for C#, which infinitely moves the cursor randomly withing a range of plus minus 5px around the current cursor position. After each displacement the program waits 50 ms to 100 ms (not accurate!). The shakiness can be configured by adapting the values for the displacement and the pauses. I ran this in a console application and - depending on the values - it gave me quite a hard time stopping the program.

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);
}

其他回答

我曾经在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] #默认值为0.1

我犯了一个错误,我自己点击了它,而不是从命令行运行它,很快就发现这是多么令人沮丧。我试了几次才打开一个终端窗口来杀死它。

As you were thinking about doing it with a custom mouse driver I suppose a small program running on the PC would do either? If this is the case, here is a small snippet for C#, which infinitely moves the cursor randomly withing a range of plus minus 5px around the current cursor position. After each displacement the program waits 50 ms to 100 ms (not accurate!). The shakiness can be configured by adapting the values for the displacement and the pauses. I ran this in a console application and - depending on the values - it gave me quite a hard time stopping the program.

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);
}

你可以使用一套模拟老年人的服装,比如本文中描述的那种……我怀疑手颤抖的部分只是一个振动电机绑在手腕上,加上一些厚手套,使手通常笨拙。

非javascript方法

实际上,我喜欢基于javascript的解决方案,因为它们更有可能与web相关,而且很有可能与操作系统无关。然而,我在想-如何解决所有浏览器的问题,因为javascript解决方案,在这种情况下,将很难调整为所有可能的浏览器(我不确定是否有可能)。

所以,正如你所提到的,还有另一种方法——即在操作系统级别上模拟行为。这也有另一个好处——你可以确定对于浏览器来说,它看起来是100%的人类(因为,好吧,它是驱动程序发送信号)。所以你可以在任何浏览器中使用基于驱动程序/设备的解决方案(甚至在javascript被禁用的情况下)。

Linux

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

我的完整代码的问题可以在这里找到。 该程序将要求“震颤”的振幅和频率(因此,“震颤”之间有多少微秒的时间)。为了模拟情况,它将强制鼠标随机移动0..X指向随机方向(上-下-左-下),随机等待0..距离下一次“震颤”的时间为Y微秒,其中X为“震颤”的振幅,Y为“震颤”的频率

另一件事可能是为您的系统调整程序。这个程序是“假的”,不能自己检测鼠标,所以“/dev/input/event4”是硬编码的。要了解什么可能是你的系统的标识符,你可以尝试:

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

所以可能性是"event3"和"event4" -但对于您的系统可能有其他值。因此,如果这与当前在C代码中使用的不同,只需更改相应的行(因此,line with int fd = open("/dev/input/event4", O_RDWR);用你的设备代替事件

这里是这个程序的gif演示(不幸的是,帧率低,所以图像不要太大)。

一个小提示(如果你不知道如何处理C代码)-要编译上面的程序,只需使用:

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

其中file. C是你的C源代码文件的名称,然后你将得到可执行文件,在你的目录中称为m。大多数情况下,你需要权限直接写入鼠标设备,所以你可以使用sudo:

user@host:/path$ sudo ./m

其他操作系统

逻辑将保持不变:

找到一种访问鼠标设备的方法 写入移动鼠标事件 将随机化应用于你的事件

就是这样。例如,Mac OS有自己的鼠标操作方式(不像Linux, Mac也没有procfs),这里有详细的描述。

作为结论

哪个更好——javascript还是面向设备的解决方案——取决于你,因为在这种情况下,某些条件(比如跨浏览器或跨操作系统)可能决定一切。因此,我提供了一些指导原则,以及一些如何在操作系统级别上实现它的工作示例。这里的好处是解决方案是跨浏览器的,但代价是我们有操作系统绑定的程序。

你不能指望任何人都能把他们的手握得非常稳定,所以你可以考虑的一件事是,

向用户解释你在做什么, 让演示页面上的可点击元素比正常情况下要小得多。 将示例系统上的鼠标灵敏度提高到最大。

我的理由是(注意,我不是用户体验或医学专家)通过缩小可点击元素,你为大多数人创造了一个类似的问题,患有帕金森病的人每天都会面对一个网站。