Это то, что я придумал до сих пор после изучения остальных ответов. Он должен поддерживать только сенсорные, мышиные или гибридные пользователи.
Создайте отдельный класс наведения для эффекта наведения. По умолчанию добавьте этот класс наведения к нашей кнопке.
Мы не хотим обнаруживать наличие сенсорной поддержки и отключать все эффекты наведения с самого начала. Как уже упоминалось, гибридные устройства набирают популярность; люди могут иметь сенсорную поддержку, но хотят использовать мышь и наоборот. Поэтому удаляйте класс наведения только тогда, когда пользователь фактически касается кнопки.
Следующая проблема заключается в том, что если пользователь захочет вернуться к использованию мыши после нажатия кнопки? Чтобы решить эту проблему, нам нужно найти подходящий момент, чтобы добавить обратно класс hover, который мы удалили.
Однако мы не можем добавить его обратно сразу после его удаления, потому что состояние наведения все еще активно. Мы можем не захотеть уничтожить и воссоздать всю кнопку также.
Итак, я подумал об использовании алгоритма ожидания занятости (используя setInterval) для проверки состояния наведения. После того как состояние наведения деактивировано, мы можем добавить обратно класс наведения и остановить ожидание занятости, возвращая нас в исходное состояние, в котором пользователь может использовать мышь или касание.
Я знаю, что ожидание не так уж и здорово, но я не уверен, что есть подходящее событие. Я решил добавить его обратно в событие mouseleave, но это было не очень надежно. Например, когда после нажатия кнопки появляется предупреждение, положение мыши смещается, но событие отпускания мыши не вызывается.
var button = document.getElementById('myButton');
button.ontouchstart = function(e) {
console.log('ontouchstart');
$('.button').removeClass('button-hover');
startIntervalToResetHover();
};
button.onclick = function(e) {
console.log('onclick');
}
var intervalId;
function startIntervalToResetHover() {
// Clear the previous one, if any.
if (intervalId) {
clearInterval(intervalId);
}
intervalId = setInterval(function() {
// Stop if the hover class already exists.
if ($('.button').hasClass('button-hover')) {
clearInterval(intervalId);
intervalId = null;
return;
}
// Checking of hover state from
// http://stackoverflow.com/a/8981521/2669960.
var isHovered = !!$('.button').filter(function() {
return $(this).is(":hover");
}).length;
if (isHovered) {
console.log('Hover state is active');
} else {
console.log('Hover state is inactive');
$('.button').addClass('button-hover');
console.log('Added back the button-hover class');
clearInterval(intervalId);
intervalId = null;
}
}, 1000);
}
.button {
color: green;
border: none;
}
.button-hover:hover {
background: yellow;
border: none;
}
.button:active {
border: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='myButton' class='button button-hover'>Hello</button>
Изменить: Другой подход, который я попробовал, это позвонить e.preventDefault()
в ontouchstart или ontouchend. Кажется, что он останавливает эффект наведения при нажатии кнопки, но он также останавливает анимацию нажатия кнопки и предотвращает вызов функции onclick при касании кнопки, поэтому вы должны вызывать их вручную в обработчике ontouchstart или ontouchend. Не очень чистое решение.