Обрабатывать как мыши, так и сенсорные события на сенсорных экранах

Я пишу веб-приложение, которое должно поддерживать взаимодействие с мышью и касанием. Для тестирования я использую сенсорное устройство с Windows 7. Я пытался обнюхать события касания в последних браузерах Firefox и Chrome и получил следующие результаты:

Прикосновение Firefox срабатывает при касании и соответствующем событии мыши. Chrome срабатывает touchstart/mousedown, touchend/mouseup пары, но mousemove запускается очень странно: один/два раза, а touchmove.

Все события мыши обрабатываются, как всегда.

Есть ли способ обрабатывать мышь и сенсорный экран одновременно на современных сенсорных экранах? Если Firefox запускает пару событий touch и mouse, что происходит на touchmove с mousemove в Chrome? Должен ли я переводить все события мыши на касание или наоборот? Я надеюсь найти правильный способ создания адаптивного интерфейса.

Ответ 1

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

Вы можете сделать что-то вроде этого:

(function () {
    if ('ontouchstart' in window) {
        window.Evt = {
            PUSH : 'touchstart',
            MOVE : 'touchmove',
            RELEASE : 'touchend'
        };
    } else {
        window.Evt = {
            PUSH : 'mousedown',
            MOVE : 'mousemove',
            RELEASE : 'mouseup'
        };
    }
}());

// and then...

document.getElementById('mydiv').addEventListener(Evt.PUSH, myStartDragHandler, false);

Забастовкa >


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

var mydiv = document.getElementsById('mydiv');
mydiv.addEventListener('mousemove', myMoveHandler, false);
mydiv.addEventListener('touchmove', function (e) {
    // stop touch event
    e.stopPropagation();
    e.preventDefault();

    // translate to mouse event
    var clkEvt = document.createEvent('MouseEvent');
    clkEvt.initMouseEvent('mousemove', true, true, window, e.detail, 
                 e.touches[0].screenX, e.touches[0].screenY, 
                 e.touches[0].clientX, e.touches[0].clientY, 
                 false, false, false, false, 
                 0, null);
    mydiv.dispatchEvent(clkEvt);

    // or just handle touch event
    myMoveHandler(e);
}, false);

Ответ 2

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

Вместо этого вы всегда должны прослушивать как события касания, так и события мыши, но нажимайте preventDefault() на события касания, которые вы обрабатываете, чтобы предотвратить (теперь избыточные) события мыши из-за их увольнения. Подробнее см. http://www.html5rocks.com/en/mobile/touchandmouse/.

Ответ 3

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

var lastEvent = 3  ;
var MOUSE_EVENT = 1;
var TOUCH_EVENT = 2 ; 
 

element.addEventListener('touchstart', function(event)
		{
			 
			if (lastEvent === MOUSE_EVENT  )
			{
				var time =  Date.now() - eventTime  ;  
				if ( time > 5000 ) 
				{
					eventTime = Date.now() ;
					lastEvent = TOUCH_EVENT ;
					interactionStart(event) ;
				} 
			}
			else 
			{
				lastEvent = TOUCH_EVENT ; ;
				eventTime = Date.now() ;
				interactionStart(event)  ; 
			}
			 
		}) ;	

		element.addEventListener('mousedown',	function(event)
		{
			
			if (lastEvent === TOUCH_EVENT  )
			{
				var time =  Date.now() - eventTime  ;	
				if ( time > 5000 ) 
				{
					eventTime = Date.now() ;
					lastEvent = MOUSE_EVENT ;
					interactionStart(event) ;
				} 
			}
			else 
			{
				lastEvent=  MOUSE_EVENT ; 
				eventTime = Date.now() ;
				interactionStart(event)  ; 
			}
		}) ;  

function interactionStart(event) // handle interaction (touch or click ) here.
{...}

Ответ 4

Я использую этот помощник jQuery для привязки событий касания и кликов.

(function ($) {
$.fn.tclick = function (onclick) {
    this.bind("touchstart", function (e) { onclick.call(this, e); e.stopPropagation(); e.preventDefault(); });
    this.bind("click", function (e) { onclick.call(this, e); });   //substitute mousedown event for exact same result as touchstart         
    return this;
  };
})(jQuery);