Поделиться через


Взаимодействие с пером и тактильная обратная связь

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

С Windows 11 введена новая возможность, которая делает использование цифрового пера еще более естественным и убедительным: при использовании пера, поддерживающего "тактильную обратную связь", пользователи могут ощутимо чувствовать взаимодействие пера с пользовательским интерфейсом приложения.

Замечание

При упоминании этой новой функции в API-интерфейсах разработчиков и связанной документации используется термин "тактильный", а "тактильный" — дружественное название, представленное пользователям для настройки предпочтений обратной связи в параметрах Windows.

Опыт тактильной обратной связи, поддерживаемый в Windows 11, включает обратную связь при рисовании и обратную связь при взаимодействии.

  • Отзыв на рукописный ввод имитирует ощущение различных типов письменных или рисовательных инструментов (таких как ручка, маркер, карандаш, текстовыделитель и т. д.) через постоянные вибрации при контакте пера с экраном. По умолчанию Windows Ink Platform поддерживает тактильную обратную связь для всех средств рисования (в этом разделе рассматривается, как создать собственное решение для рукописного ввода, отличающееся от стандартного, предоставляемого Windows Ink).
  • С другой стороны, интерактивная обратная связь — это прямая обратная связь, основанная на ключевых пользовательских действиях, таких как наведение курсора или нажатие кнопки, а также на реакцию на завершение действия или привлечение внимания пользователя.

Как правило, для полной поддержки тактильной обратной связи требуются пять шагов:

  • Обнаружение ввода пера.
  • Определите, поддерживает ли текущее перо и устройство тактильную обратную связь, а если да, то какие тактильные функции обратной связи они поддерживают.
  • Выберите сигнал тактильной обратной связи для отправки.
  • Отправьте тактильную обратную связь.
  • Остановите тактильную обратную связь

Распознавание ввода пером

Чтобы обнаружить и изолировать входные данные пера, необходимо сначала зарегистрировать событие Pointer Input , а затем проверить, является ли pointerDeviceTypeпером.

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


private void InputObserver_PointerEntered(object sender, PointerRoutedEventArgs e)
{
    ...
    
    // If the current Pointer device is not a pen, exit.
    if (e.Pointer.PointerDeviceType != PointerDeviceType.Pen) 
    {
       return;
    }
    
    ...    
}

Определение поддержки хаптиковой обратной связи

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

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

Сначала мы пытаемся получить объект PenDevice из текущего PointerId. Если не удается получить PenDevice, мы просто вернемся из обработчика событий.

Если был получен PenDevice , мы проверяем, поддерживает ли оно свойство SimpleHapticsController . Если нет, мы снова просто вернемся из обработчика событий.

// Attempt to retrieve the PenDevice from the current PointerId.
penDevice = PenDevice.GetFromPointerId(e.Pointer.PointerId);

// If a PenDevice cannot be retrieved based on the PointerId, it does not support 
// advanced pen features, such as haptic feedback. 
if (penDevice == null)
{
    return;
}

// Check to see if the current PenDevice supports haptic feedback by seeing if it 
// has a SimpleHapticsController.
hapticsController = penDevice.SimpleHapticsController;
if (hapticsController == null)
{
    return;
}

Объект SimpleHapticsController, полученный в предыдущем примере, используется в последующих примерах для получения информации о хаптических возможностях, передачи и остановки хаптической обратной связи.

Замечание

Если вы создаете приложения с помощью Windows App SDK, вы можете использовать PenDevice interop (PenDeviceInterop.FromPoint(PointerPoint)) для доступа к системе PenDevice.

private void InputObserver_PointerEntered(PointerInputObserver sender, PointerEventArgs args)
{
    var penDevice = PenDeviceInterop.PenDeviceFromPointerPoint(args.CurrentPoint);
}

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

Волновые формы рисования

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

Функция Описание Обязательный или необязательный
Непрерывная волновая форма чернил Имитирует ощущение письма шариковой ручкой. Это резервный вариант по умолчанию, когда волны рукописного ввода не поддерживаются храптовым пером. Обязательный
Непрерывная волновая форма кисти Непрерывный тактильный сигнал, когда пользователь выбирает кисть в качестве инструмента. Необязательно
ChiselMarkerContinuous форма волны Непрерывный тактильный сигнал, когда пользователь выбирает маркер/выделитель в качестве инструмента для рисования. Необязательно
Ластик Непрерывная волна Непрерывный тактильный сигнал, когда пользователь выбирает ластик в качестве инструмента рисования. Необязательно
Непрерывная волновая форма Galaxy
(Документация и руководство по реализации HID называют эту волну SparkleContinuous)
Непрерывный тактильный сигнал для специальных инструментов, таких как многоцветная кисть. Необязательно
Метка непрерывной волны Непрерывный хаптитический сигнал при выборе маркера в качестве средства рукописного ввода. Необязательно
непрерывная волновая форма карандаша Непрерывный тактильный сигнал, когда пользователь выбирает карандаш как инструмент. Необязательно

Формы волн взаимодействия

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

Функция Описание Обязательный или необязательный
Щелкните форму волны Короткий отклик "щелчок". Это резервный вариант по умолчанию, когда волны взаимодействия, выбранные приложением, не поддерживаются хаптильной ручкой. Обязательный
Форма волны ошибок Сильный сигнал для оповещения пользователя о том, что действие завершилось сбоем или произошла ошибка. Необязательно
Волна наведения Указывает, что пользователь навел указатель мыши на интерактивный элемент пользовательского интерфейса. Необязательно
Пресс-форма волны Указывает, когда пользователь нажимает интерактивный элемент пользовательского интерфейса в добавочном действии (см. раздел "Выпуск"). Необязательно
Форма волны выпуска Указывает, когда пользователь отпускает интерактивный элемент пользовательского интерфейса в пошаговом действии (см. нажатие). Необязательно
Форма волны успешности Сильный сигнал, чтобы предупредить пользователя об успешном выполнении действия. Необязательно
Непрерывный сигнал Buzz Чувство непрерывного жужжания. Необязательно
RumbleContinuous форма сигнала Непрерывное ощущение гула. Необязательно

Настройки тактильной обратной связи

Некоторые хаптильные ручки могут поддерживать следующие настройки.

Функция Описание Обязательный или необязательный
Интенсивность Задает интенсивность хаптикового сигнала. Необязательно
Количество воспроизведения Повторяет тактильный сигнал заданное количество раз. Необязательно
Интервал приостановки воспроизведения Задает время между каждым повторяющимся воспроизведением хаптикового сигнала. Необязательно
Длительность воспроизведения Задает интервал времени, в течение которого воспроизводится тактильный сигнал. Необязательно

Проверка поддержки пользовательских параметров

Чтобы проверить интенсивность, количество воспроизведения, интервал приостановки воспроизведения и поддержку длительности воспроизведения, используйте следующие свойства SimpleHapticsController:

Отправка и остановка рукописного ввода отзывов

Используйте метод SendHapticFeedback объекта SimpleHapticsController, чтобы передать формы колебаний рисования на стилус пользователя. Этот метод поддерживает передачу либо только волны, либо волны с настраиваемым значением интенсивности (см. раздел "Настройка хаптической обратной связи").

Вызовите SendHapticFeedback и передайте волну индикации перу, чтобы настроить его на воспроизведение этой волны, как только кончик пера касается экрана. Форма волны будет воспроизводиться до тех пор, пока перо не будет снято или не будет вызвана функция StopFeedback, в зависимости от того, что произойдет первым. Мы рекомендуем выполнить это в обработчике событий PointerEntered для элемента, в котором вы хотите воспроизвести тактильные сигналы. Например, приложение с пользовательской реализацией рукописного ввода сделает это в методе PointerEntered на холсте для ввода рукописного текста.

Чтобы получить нужную форму волны рукописного ввода, необходимо выполнить итерацию через коллекцию SupportedFeedbackSimpleHapticsController, гарантируя, что она поддерживается активным пером.

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

В следующем примере мы пытаемся отправить сигнал BrushContinuous (но возвращаемся к InkContinuous, если BrushContinuous не поддерживается).

SimpleHapticsControllerFeedback currentWaveform;

// Attempt to set the currentWaveform to BrushContinuous.
foreach (var waveform in hapticsController.SupportedFeedback)
{
    if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.BrushContinuous)
    {
        currentWaveform = waveform;
    }
} 

// If currentWaveform is null, it was not in the SupportedFeedback collection, so instead set 
// the waveform to InkContinuous.
if (currentWaveform == null)
{
    foreach (var waveform in hapticsController.SupportedFeedback)
    {
        if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.InkContinuous)
        {
            currentWaveform = waveform;
        }
    }
}

// Send the currentWaveform 
hapticsController.SendHapticFeedback(currentWaveform);

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

Замечание

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

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

hapticsController.StopFeedback();

Отправка и остановка обратной связи о взаимодействии

Отправка отзывов об взаимодействии довольно похожа на отправку отзывов рукописного ввода.

Используйте метод SendHapticFeedback объекта SimpleHapticsController для передачи волновых форм взаимодействия перу пользователя. Этот метод поддерживает передачу либо только волны, либо волны с настраиваемым значением интенсивности (см. раздел "Настройка хаптической обратной связи").

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

При использовании любой из форм волн, не относящихся к непрерывному взаимодействию, не требуется выполнять соответствующий вызов StopFeedback . Вам по-прежнему нужно вызвать StopFeedback для непрерывных волновых форм взаимодействия.

Замечание

Отправка сигнала взаимодействия при воспроизведении волны рукописного ввода временно прерывает волну рукописного ввода. Форма волны рукописного ввода возобновляется при остановке волны взаимодействия.

Чтобы получить нужную форму взаимодействия, необходимо пройти через коллекцию SupportedFeedback в SimpleHapticsController, убедившись, что она поддерживается активным пером.

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

В следующем примере мы пытаемся отправить сигнал Ошибки (но переключаемся на щелчок, если Ошибка не поддерживается).

SimpleHapticsControllerFeedback currentWaveform;  

// Attempt to set the currentWaveform to BrushContinuous.
foreach (var waveform in hapticsController.SupportedFeedback)
{
    if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.Error)
    {
        currentWaveform = waveform;
    }
} 

// If currentWaveform is null, it was not in the SupportedFeedback collection, so instead set 
// the waveform to Click.
if (currentWaveform == null)
{
    foreach (var waveform in hapticsController.SupportedFeedback)
    {
        if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.Click)
        {
            currentWaveform = waveform;
        }
    }
} 

// Send the currentWaveform.
hapticsController.SendHapticFeedback(currentWaveform); 

Настройка хаптильной обратной связи

Существует три способа настройки осязательной обратной связи. Первый поддерживается как отзывами о рукописном вводе, так и взаимодействием, а второй и третий поддерживаются только отзывами о взаимодействии.

  1. Настройте интенсивность обратной связи относительно максимального параметра интенсивности системы. Для этого необходимо сначала проверить, поддерживает ли SimpleHapticsController настройку интенсивности, а затем вызвать SendHapticFeedback с требуемым Intensity значением.

    if (hapticsController.IsIntensitySupported) 
    {
        foreach (var waveform in hapticsController.SupportedFeedback)
        {
            if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.Click)
            {
                double intensity = 0.75;
                hapticsController.SendHapticFeedback(waveform, intensity);
            }
        }
    }
    
  2. Повторите тактильный сигнал заданное количество раз. Для этого необходимо сначала проверить, поддерживает ли SimpleHapticsController настройку интенсивности, а затем вызвать SendHapticFeedbackForPlayCount с нужным значением счетчика. Можно также задать как интенсивность, так и интервал приостановки воспроизведения.

    Замечание

    Если SimpleHapticsController не поддерживает настройку интенсивности или интервала приостановки воспроизведения, указанные значения будут игнорироваться.

    if (hapticsController.IsPlayCountSupported && hapticsController.IsIntensitySupported && hapticsController.IsReplayPauseIntervalSupported)
    {
        foreach (var waveform in hapticsController.SupportedFeedback)
        {
            if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.Click)
            {
                double intensity = 0.75;
                int playCount = 3;
                System.TimeSpan pauseDuration = new System.TimeSpan(1000000);
                hapticsController.SendHapticFeedbackForPlayCount(currentWaveform, intensity, playCount, pauseDuration);
            }
        }
    }
    
  3. Задайте длительность гаптического сигнала. Для этого необходимо сначала проверить, что SimpleHapticsController поддерживает настройку длительности воспроизведения, а затем вызовите SendHapticFeedbackForDuration с требуемым значением интервала времени. Вы также можете задать интенсивность.

    Замечание

    Если SimpleHapticsController не поддерживает настройку интенсивности, указанное значение будет игнорироваться.

    if (hapticsController.IsPlayDurationSupported && hapticsController.IsIntensitySupported)
    {
        foreach (var waveform in hapticsController.SupportedFeedback)
        {
            if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.RumbleContinuous)
            {
                double intensity = 0.75;
                System.TimeSpan playDuration = new System.TimeSpan(5000000);
                hapticsController.SendHapticFeedbackForDuration(currentWaveform, intensity, playDuration);
            }
        }
    }
    

Примеры

Ознакомьтесь с примером тактильных ощущений пера для примеров работы следующей функциональности:

  • Получите SimpleHapticsController из ввода пера: переход от PointerId к PenDevice и далее к SimpleHapticsController (требуется перо с поддержкой тактильной отдачи и устройство, поддерживающее перо).
  • Проверьте возможности тактильной обратной связи пера: SimpleHapticsController предоставляет свойства, связанные с возможностями оборудования пера, включая IsIntensitySupported, IsPlayCountSupported, SupportedFeedback и так далее.
  • Запустите и остановите тактическую обратную связь: используйте методы SendHapticFeedback и StopFeedback соответствующим образом.
  • Триггер тактильной отдачи: обратная связь как для рукописного ввода, так и для интерактивного взаимодействия.