Моделирование тремора (например, болезни Паркинсона) с помощью мыши на веб-странице?

Я работаю над созданием, которое повышает осведомленность о доступности в Интернете. Для презентации мы хотим предложить небольшой семинар, который имитирует различные инвалидности/нарушения для людей. Это делается с помощью веб-сайта, созданного специально для этой презентации.

У одного из проявленных нарушений есть тремор, а это означает, что у него возникают неустойчивые, трудно контролируемые движения рук. При этом ухудшении очень трудно точно перемещать курсор мыши и нажимать кнопку мыши, когда мышь находится над ссылкой. Как некоторые пожилые люди, так и люди с заболеваниями, например. Паркинсона, может страдать от тремора.

Теперь я хотел бы как-то переместить курсор мыши непредсказуемым образом, так что людям очень сложно щелкнуть маленькую кнопку. Поскольку JavaScript не позволяет перемещать курсор мыши напрямую, я ищу другие способы достижения этого. Я придумал следующие идеи:

  • Использование драйвера/утилиты мыши, которая имитирует дрожание мыши.
  • Скрыть курсор мыши с помощью CSS, поместить анимацию GIF дрожащего курсора мыши на место исходного курсора (с помощью JavaScript), а затем сделать целевую ссылку кликабельной только каждые несколько секунд в течение секунды или около того. Это, по крайней мере, дало бы ощущение, будто человек всегда нажимает на не тот момент.

В то время как первая идея была бы довольно крутой, я не мог найти такой инструмент, как для Mac, так и для Windows. И у меня нет никаких навыков программирования таким образом.

Вторая идея кажется немного неуклюжей, но я думаю, что она достигнет желаемого эффекта.

Есть ли у кого-нибудь другая идея?

Ответ 1

Я сделал быструю демонстрацию того, что, надеюсь, должно быть в состоянии основывать ваш код, используя API-интерфейс указателя поворота.

Я разблокировал этот указатель-lock-demo repo и изменил его, чтобы добавить элемент случайного перемещения.

Вот ссылка на мою страницу GitHub: https://aristocrates.github.io/pointer-lock-demo
И вот ссылка на мое репо: https://github.com/aristocrates/pointer-lock-demo

Важный код javascript содержится в app.js в методе canvasLoop(e).

Единственное, что я изменил с оригинальной демонстрацией, было после строк

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

Я добавил две строки для представления случайного движения:

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

Есть еще много вещей, которые вы могли бы улучшить, но, надеюсь, это поможет вам начать работу.

Ответ 2

Способ без javascript

На самом деле, мне нравятся решения, которые могут основываться на javascript, поскольку они скорее связаны с веб-сайтами, а хорошие шансы - независимы от ОС. Однако я думал о том, как решить проблему для всех браузеров, поскольку в этом случае решения для 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 - частота "тремора"

Еще одна вещь - адаптировать программу для вашей системы. Программа "dummy" и не может обнаружить мышь сама по себе, поэтому "/dev/input/event4" жестко закодирован. Чтобы понять, что может быть идентификатором вашей системы, вы можете попробовать:

[email protected]:/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 для этой программы (низкая частота кадров, к сожалению, так что держите изображение не слишком большим) здесь.

Небольшая заметка (если вы не знаете, что делать с кодом C) - чтобы скомпилировать программу выше, просто используйте:

[email protected]:/path$ gcc -std=gnu99 file.c -o m

где file.c - это имя вашего исходного файла исходного кода, тогда вы получите исполняемый файл, называемый m в вашем каталоге. Скорее всего, вам понадобятся разрешения на запись в устройство мыши напрямую, поэтому вы можете использовать sudo:

[email protected]:/path$ sudo ./m

Другая ОС

Логика останется прежней:

  • Найдите способ доступа к устройству мыши.
  • Запись события движущейся мыши
  • Применить рандомизацию к вашему мероприятию

Что это. Например, Mac OS имеет собственный способ работы с мышью (не так, как Linux, Mac не имеет procfs), она хорошо описана здесь.

В качестве заключения

Что лучше - решения, основанные на javascript или устройства, - зависит от вас, потому что в этом случае все решения (например, кросс-браузер или кросс-OS) могут решить все. Поэтому я представил рекомендации вместе с определенным рабочим примером того, как реализовать это на уровне ОС. Преимущество здесь в том, что решение является кросс-браузерным, но, как стоимость, у нас есть OS-привязанная программа.

Ответ 3

Я сделал это как шутка один раз на форуме Puppy Linux Forum и получил комментарий, что:

Люди с Паркинсоном не посчитают это забавным!!!

Cure здесь просто cntrl-C, к счастью.

Вот оболочка script, которая требует 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

Я совершил ошибку, щелкнув по ней сам, вместо того, чтобы запускать ее из командной строки и быстро обнаружил, насколько это расстраивает. Мне потребовалось несколько попыток открыть окно терминала, чтобы его убить.

Ответ 4

Ваша вторая идея (скрыть курсор) находится на полпути к той, которая, как я думаю, может сработать для вас:

  • Скрыть курсор мыши с помощью CSS, как вы предлагаете. (cursor:none IIRC)
  • Вместо gif-кода с шатким курсором используйте некоторое абстрагируемое изображение + CSS + JS для эмуляции указателя мыши; т.е. следуйте мыши по странице и поместите изображение курсора, где курсор мыши будет изначально.

Затем вы добавляете некоторую треморную математику в код курсора, чтобы "встряхнуть" курсор. До вас, чтобы определить, какие правильные кривые должны правильно имитировать вход тремора.

Наконец: для любых элементов управления, которые вы программируете (ссылки и т.д.):

  • захватить события щелчка, подтолкнуть их к текущему местоположению "тремора", основанному на состоянии ваших кривых дрожания, и ограничить - проверьте свои элементы, чтобы увидеть, не потерял ли пользователь из указанного элемента или, возможно, элемент, который не предназначалось.

Один главный бонус с этой реализацией: ваш "шаткий курсор" будет отображаться на сенсорных устройствах, на которых не было бы курсора.


Edit:

Основанный на Майкле Theriot (очень чистый и полезный!) база JSFiddle из комментариев, здесь, которая постоянно трепещет с нормально распределенной разверткой вокруг текущего местоположения курсора: http://jsfiddle.net/benmosher/0x4mc64v/4/

(массив normal является результатом вызова rnorm(100) в моей консоли R. Самый простой способ, который я мог бы подумать в JS, пробовать нормальное распределенное случайное целое.)

Ответ 5

Просто идея получить дрожь "правильно", вы можете записать движение мыши реального пациента, это делает ее более аутентичной, когда вы сообщаете людям, откуда поступают данные.

Там сценарии, позволяющие коту следовать за вашим курсором мыши, вы можете настроить его, чтобы второй курсор следовал (прыгал) курсором. Страница вычисляет позицию второго курсора, поэтому он также может определить, успешно ли событие клика или нет.

Если вы можете, пожалуйста, сделайте это на основе Интернета, вы достигнете гораздо большего количества людей таким образом, не попросив их установить программу или активировать флеш-память или что-то еще.

Ответ 6

Вместо того, чтобы пытаться переместить указатель, вы можете переместить приложение (веб-страницу). Я написал простую форму html, в которой есть некоторые поля ввода. Когда вы перемещаете мышь на форму, форма перемещается.

Вы можете увидеть демонстрацию движущейся формы в 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" выше), чтобы настроить движение формы.

Ответ 7

Почему бы не использовать аппаратное решение? Есть определенные мыши, в которые вы можете положить вес, как Logitech G500. Вместо того, чтобы вставлять вес, поставьте небольшой колебательный двигатель, который заставляет мышцу слегка встряхнуть. Это также смоделировало фактическое расстройство больше: это не только курсор, который трясет, но и всю руку и мышь. И это также означает, что вы можете показывать другое программное обеспечение, чем веб-сайты.

Вместо мыши с слотом веса вы также можете просто скопировать что-то на мышь, но это более заметно.

Ответ 8

Как вы думали делать это с помощью специального драйвера мыши, я полагаю, что небольшая программа, работающая на ПК, тоже будет делать? Если это так, вот небольшой фрагмент для С#, который бесконечно перемещает курсор в случайном порядке с диапазоном плюс минус 5 пикселей вокруг текущей позиции курсора. После каждого перемещения программа ждет 50 мс до 100 мс (неточно!). Шаги можно настроить, адаптировав значения для перемещения и пауз. Я запустил это в консольном приложении и - в зависимости от значений - мне было довольно сложно остановить программу.

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

Ответ 9

Вы не можете ожидать, что кто-то сможет держать руки в совершенном состоянии, поэтому вы можете подумать,

  • Объясните пользователям, что вы делаете, и
  • Сделать интерактивные элементы на демо-странице намного меньше, чем обычно.
  • Повышение чувствительности мыши на примерной системе до максимума.

Мое рассуждение (предостережение, я не эксперт по ux или медицине), уменьшив количество элементов, доступных для кликов, для большинства людей создается аналогичная проблема, с которой сталкивается человек, страдающий болезнью Паркинсона, с повседневным веб-сайтом,

Ответ 10

Вот версия Windows моего xdotool script, которая использует AutoIt. Это был мой первый AutoIt script, и писать было всего пару минут, поэтому я уверен, что его можно улучшить. Просто сохраните с расширением .au3 и запустите его с помощью AutoIt (запустите 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

Управление

  • Главная: запуск моделирования.
  • пауза: пауза моделирования.
  • Esc: симуляция выхода.

Или используйте мою скомпилированную версию из здесь.

Ответ 11

Вы можете использовать костюм моделирования для старости, например, описанный в этой статье... Я подозреваю, что часть дрожания руки это всего лишь вибрирующий мотор, обвязанный вокруг запястья, плюс несколько толстых перчаток, чтобы руки были обычно неуклюжими.

Ответ 12

  • В вашем DIV, CSS-скрыть курсор, используя cursor:none;
  • Создайте .png изображение курсора и переместите его (left, top) с помощью jQ на mousemove
  • Рандомизировать .png margin-left и margin-top с помощью setTimeout (чтобы сделать повторное позиционирование плавным использованием CSS3 transition или сделать это с помощью jQ .animate()).

Примечание. script не может знать, находится ли рука на мыши;)

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>

Ответ 13

Нынешние уровни симуляции дрожания хорошо отвечают. Я добавлю что-то, фокусирующееся на типе дрожания, чтобы имитировать:

В большинстве ответов используется курсор мыши, который перемещается по случайному пути с некоторой фиксированной максимальной шириной шага в направлениях X и Y.

Это должно работать достаточно хорошо для использования, чтобы затруднить попадание в определенную область, например, на кнопку.

Для более общей проблемы моделирования проблем пользовательского интерфейса, вызванных тремором от болезни Паркинсона, было бы, по крайней мере, интересно на самом деле имитировать ручные движения такого рода дрожания. Я подозреваю, что случайное блуждание может быть не очень хорошим приближением.

Это может быть тяжело получить реальные данные трассировки руки движения тремора, конечно, но, конечно, есть статьи об анализе такого рода дрожания:

Статья Параметрическое представление движения руки в болезни Паркинсона - о том, как наилучшим образом отображать 3D-движения движения руки.
Бумага платная, но предварительный просмотр в верхнем правом углу, обозначенный "Look Inside > " на изображении книги, показывает некоторые интересные графики различных представлений данных ручной трассировки.