Ich hatte die folgenden Probleme mit den vorhandenen Lösungen und habe etwas gefunden, das alle Probleme zu lösen scheint. Dies setzt voraus, dass Sie für etwas Cross-Browser, Cross-Gerät abzielen, und wollen nicht Gerät sniffing.
Die Probleme, die damit gelöst werden
Mit nur touchstart
o touchend
:
- Bewirkt, dass das Ereignis ausgelöst wird, wenn die Personen beim Versuch, am Inhalt vorbeizuscrollen und den Finger zufällig über diesem Element hatten, als sie mit dem Streichen begannen, wodurch die Aktion unerwartet ausgelöst wurde.
- Kann das Ereignis auslösen auf der Langpresse ähnlich wie beim Rechtsklick auf dem Desktop. Wenn Ihr Klick-Ereignis z. B. zur URL X führt und der Benutzer lange drückt, um X in einer neuen Registerkarte zu öffnen, wird der Benutzer verwirrt sein, weil X in beiden Registerkarten geöffnet ist. Bei einigen Browsern (z. B. iPhone) kann dies sogar dazu führen, dass das Menü bei langem Drücken nicht angezeigt wird.
Auslöser mouseover
Veranstaltungen am touchstart
y mouseout
en touchmove
hat weniger schwerwiegende Folgen, beeinträchtigt aber das übliche Verhalten des Browsers, zum Beispiel:
- Ein langer Druck würde einen Mouseover auslösen, der nie endet.
- Viele Android-Browser behandeln die Position des Fingers auf
touchstart
wie ein mouseover
das ist mouseout
auf der nächsten touchstart
. Eine Möglichkeit, Mouseover-Inhalte in Android zu sehen, besteht daher darin, den gewünschten Bereich zu berühren und mit dem Finger zu wackeln, wobei die Seite leicht gescrollt wird. Behandlung von touchmove
als mouseout
bricht dies.
Die Lösung
Theoretisch könnte man einfach ein Flag hinzufügen mit touchmove
aber iPhones lösen touchmove auch dann aus, wenn es keine Bewegung gibt. Theoretisch könnten Sie einfach die touchstart
y touchend
Veranstaltung pageX
y pageY
aber auf iPhones gibt es keine touchend
pageX
o pageY
.
Um alle Bereiche abzudecken, wird es also leider ein wenig komplizierter.
$el.on('touchstart', function(e){
$el.data('tstartE', e);
if(event.originalEvent.targetTouches){
// store values, not reference, since touch obj will change
var touch = e.originalEvent.targetTouches[0];
$el.data('tstartT',{ clientX: touch.clientX, clientY: touch.clientY } );
}
});
$el.on('touchmove', function(e){
if(event.originalEvent.targetTouches){
$el.data('tstartM', event.originalEvent.targetTouches[0]);
}
});
$el.on('click touchend', function(e){
var oldE = $el.data('tstartE');
if( oldE && oldE.timeStamp + 1000 < e.timeStamp ) {
$el.data('tstartE',false);
return;
}
if( $el.data('iosTouchM') && $el.data('tstartT') ){
var start = $el.data('tstartT'), end = $el.data('tstartM');
if( start.clientX != end.clientX || start.clientY != end.clientY ){
$el.data('tstartT', false);
$el.data('tstartM', false);
$el.data('tstartE',false);
return;
}
}
$el.data('tstartE',false);
Theoretisch gibt es Es gibt Möglichkeiten, die exakte Zeit für einen Longpress zu ermitteln, anstatt 1000 als Näherungswert zu verwenden, aber in der Praxis ist das nicht so einfach, und es ist am besten, einen vernünftigen Proxy zu verwenden .