Oto, co wymyśliłem do tej pory po przestudiowaniu pozostałych odpowiedzi. Powinien być w stanie obsługiwać tylko użytkowników dotykowych, tylko myszy lub hybrydowych.
Utwórz osobną klasę najechania dla efektu najechania. Domyślnie dodaj tę klasę hover do naszego przycisku.
Nie chcemy wykrywać obecności obsługi dotyku i wyłączać od samego początku wszystkie efekty najechania kursorem. Jak wspominali inni, urządzenia hybrydowe zyskują na popularności; ludzie mogą mieć obsługę dotykową, ale chcą używać myszy i odwrotnie. Dlatego należy usuwać klasę aktywowania tylko wtedy, gdy użytkownik faktycznie dotknie przycisku.
Następnym problemem jest to, co jeśli użytkownik chce wrócić do korzystania z myszy po dotknięciu przycisku? Aby rozwiązać ten problem, musimy znaleźć odpowiedni moment, aby z powrotem dodać klasę dymienia, którą usunęliśmy.
Nie możemy jednak dodać go z powrotem natychmiast po jego usunięciu, ponieważ stan najechania jest nadal aktywny. Możemy też nie chcieć zniszczyć i odtworzyć całego przycisku.
Pomyślałem więc o użyciu algorytmu zajętości (za pomocą setInterval) do sprawdzenia stanu aktywowania. Po dezaktywacji stanu najechania możemy ponownie dodać klasę najechania i zatrzymać oczekiwanie zajętości, przywracając nas z powrotem do pierwotnego stanu, w którym użytkownik może używać myszy lub dotyku.
Wiem, że zajęty czekanie nie jest takie wspaniałe, ale nie jestem pewien, czy jest odpowiednie wydarzenie. Rozważałem dodanie go z powrotem podczas imprezy mouseleave, ale nie był on zbyt mocny. Na przykład, gdy alert pojawia się po naciśnięciu przycisku, pozycja myszy zmienia się, ale zdarzenie mouseleave nie jest wyzwalane.
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>
Edycja: Innym podejściem, które próbowałem, jest wywołanie e.preventDefault()
w ramach ontouchstart lub ontouchend. Wydaje się, że zatrzymuje efekt najechania po dotknięciu przycisku, ale także zatrzymuje animację kliknięcia przycisku i zapobiega wywoływaniu funkcji onclick po dotknięciu przycisku, więc musisz wywoływać je ręcznie w obsłudze ontouchstart lub ontouchend. Niezbyt czyste rozwiązanie.