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

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

Представьте себе открытое вертикальное popup-меню, у которого выбран верхний пукнт, который ведет к подменю, которое тут же открывается справа (для простоты положим, что места справа и внизу полно).

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

Но такого не происходит. Во всех нормальных оконных средах есть специальная логика, которая отслеживает это движение, и если оно "похоже" на движение к подменю — придерживает его закрытие. Сделано так потому, что человеку сложнее и медленнее двигать мышь строго в горизонтальном и вертикальном направлении, и практически все люди, когда выбирают пункт в подменю, ведут мышь хоть и не точно напрямик, но сильно срезая углы.

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

Кстати, в выпадающих меню на веб-страницах такой логики нет. Браузеры не могут ее реализовать, потому что нет какого-то одного стандартного способа делать меню, и для браузера это просто кусок скрипта и HTML'а разной степени витиеватости. А веб-разработчики не реализуют ее в скриптах, потому что это, говоря прямо, одуреешь программироватькрайне непросто.

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

P.S. Это, кстати, еще одна иллюстрация к тому, что программировать контролы пользовательских интерфейсов — трудно.

Комментарии: 14

  1. Артём Сапегин

    Что-то я в Windows XP такого поведения не наблюдаю. Подменю закрывается сразу.

  2. Лёхха

    А разве есть смысл меню для веба? только если в 2.0, и то с натяжкой...

    ЗЫ: Иван, поставьте же наконец логотип для своего фида! а то читаю и не всегда вижу кого :)

  3. FLOODkOFF

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

    Проверил - В windows xp задержка такая же как и если бы я навел на открывающееся меню чтобы оно открылось, но потом отвел мышь вниз (т.е. на дочернее меню мышку не наводил бы) и ждал бы пока закроется это дочернее меню.

  4. Headcrab

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

  5. Евгений Иванов

    тут всё просто. если мышь двигается, ничего не делать.
    как только мышь остановилась - открывать новое меню.
    :)

    заходи в Icq=214889076, поговорим.

  6. Иван Сагалаев

    Да, значит про Windows я погорячился про обратный ход. Ложная память, видимо :-).

    А у меня да, Gnome.

  7. Давид Мзареулян

    Читаю эту запись в FF (Win), тут же в нём проверяю: имеет место банальнейший таймаут на закрытие подменю. Меню 2-го уровня закрывается примерно через секунду после ухода мыши с родительского пункта меню 1-го уровня. При движении по пунктам меню 1-го уровня, они подсвечиваются, но соответствующие подменю 2-го уровня не открывается, пока не закроется прежде открытое подменю и пока курсор не остановится на каком-либо пункте (т.е. на открытие тоже таймаут, но поменьше, около полусекунды).

    Т.е., да, система не совсем тривиальная (и с двумя Вашими последними абзацами я вполне согласен), но и не rocket science.

  8. Tema

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

  9. Иван Сагалаев

    Ну с Windows мы уже разобрались — действительно все так, как все написали.

    Но вот что касается Firefox'а, им бы я не стал проверять поведение системы, потому что XUL, хоть и старается по максимуму этому поведению соответсвовать, не везде это получается. Сейчас проверил у себя в Ubuntu: Firefox тоже не закрывает мгновенно дочерние меню при движении к родителю. А Gnome'овское меню - закрывает.

  10. WiRED

    Есть подозрение, что у вас - типа антракт :-)

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

    Прямо по Пруткову - бросая камни в воду, наблюдай за кругами, иначе сие будет пустой тратой времени :-)

  11. dp_wiz

    wow. в xfce обнаружил такое, да. Если вести по-диагонали, то (о чудо!) меню не переключается. А если вести мышу вниз, а потом вправо - то скрывается сразу же.

    ps: long live ubuntu!

  12. AL-one

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

  13. Dima

    Когда в компании где я работаю возникла необходимость пропатчить подобное глобальное popup меню для интранета я решил проблему иначе, без привлечения js одними только css. Вокруг каждого блока меню я сделал прозрачную охранную зону в пару десятков пикселей при попадании на которую меню бы не схлопывалось (т.е фактически указатель мыши оставался в пределах данного блока). Это устранило проблему срезаемых углов и непроизвольного выхода указателя мыши за границы popup блока (особенно актуальная проблема для пользователей с touchpad'ами). Вот уже 3 месяца эта схема работает и пока нареканий не было... Конечно подход дотаточно примитивный зато простой в реализации и действенный в рамках решаемой задачи :)

  14. Петро

    У Оперы кстати с этими меню постоянные проблемы. Навигация по сайтам intel.comn и activestate.com была сущим кошмаром, сейчас в 8-9-ой версии получше, но глюки всё ещё случаются.

Добавить комментарий