Deaktivieren Sie das Scrollen, wenn Sie ein bestimmtes Element berühren

73

Ich habe eine Seite mit einem Abschnitt, in dem eine Zeichnung skizziert werden kann. Die Touchmove-Ereignisse, zumindest die vertikalen, scrollen jedoch auch durch die Seite (was das Skizzieren beeinträchtigt), wenn sie in einem mobilen Browser verwendet werden. Gibt es eine Möglichkeit, entweder a) das Scrollen der Seite zu deaktivieren und wieder zu aktivieren (damit ich sie deaktivieren kann, wenn jede Zeile gestartet wird, aber nach jeder Zeile wieder einschalten kann) oder b) die Standardbehandlung von zu deaktivieren Touchmove-Ereignisse (und vermutlich das Scrollen), die auf die Leinwand gehen, auf der die Skizze gezeichnet ist (ich kann sie nicht einfach vollständig deaktivieren, da sie beim Skizzieren verwendet werden)?

Ich habe für die Skizze jquery-mobile vmouse-Handler verwendet, wenn das einen Unterschied macht.

Update : Wenn ich auf einem iPhone die zu skizzierende Leinwand auswähle oder vor dem Zeichnen nur ein wenig mit dem Finger halte, wird die Seite nicht gescrollt und nicht aufgrund von irgendetwas, das ich auf der Seite codiert habe.

Scott Hunter
quelle
2
Ich bin mir ziemlich sicher, dass es Ihnen in der Form, in der es dort vorhanden ist, nicht viel helfen wird, aber schauen Sie sich diese Frage an . Es handelt sich um reguläres Scrollen, aber vielleicht können Sie es verwenden.
Kiruse

Antworten:

112

Setzen Sie die CSS-Eigenschaft touch-action auf none, die auch mit passiven Ereignis-Listenern funktioniert :

touch-action: none;

Das Anwenden dieser Eigenschaft auf ein Element löst nicht das Standardverhalten (Bildlauf) aus, wenn das Ereignis von diesem Element ausgeht .

John Weisz
quelle
2
Das scheint auch touchstartEreignisse zu töten , die nicht nützlich sind, wenn Sie Berührungsereignisse erkennen, aber kein Scrollen zulassen möchten.
Badrush
11
@ Badrush - Bist du sicher? Ich verwende dies für meine eigenen "ziehbaren" Komponenten und feuere einwandfrei touchstart.
John Weisz
2
Funktioniert hervorragend für ein Canvas-Element (setzen Sie einfach style = "touch-action: none" direkt in den HTML-Code). Was könnte einfacher sein! Andere Lösungen von dieser Seite sind für mich fehlgeschlagen. Vielen Dank!
Yury
1
omg ich liebe dich dafür :)
Nerdess
45

Hinweis: Wie in den Kommentaren von @nevf erwähnt, funktioniert diese Lösung aufgrund von Leistungsänderungen möglicherweise nicht mehr (zumindest in Chrome) . Es wird empfohlen, dies zu verwenden, touch-actionwas auch in der Antwort von @ JohnWeisz vorgeschlagen wird .

Ähnlich wie bei der Antwort von @Llepwryd habe ich eine Kombination aus ontouchstartund verwendet ontouchmove, um das Scrollen zu verhindern, wenn es sich auf einem bestimmten Element befindet.

Entnommen wie es ist aus einem meiner Projekte:

window.blockMenuHeaderScroll = false;
$(window).on('touchstart', function(e)
{
    if ($(e.target).closest('#mobileMenuHeader').length == 1)
    {
        blockMenuHeaderScroll = true;
    }
});
$(window).on('touchend', function()
{
    blockMenuHeaderScroll = false;
});
$(window).on('touchmove', function(e)
{
    if (blockMenuHeaderScroll)
    {
        e.preventDefault();
    }
});

Im Wesentlichen höre ich beim Start der Berührung zu, um zu sehen, ob sie mit jQuery an einem Element beginnt, das einem anderen Kind untergeordnet ist, .closestund erlaube, dass die Berührungsbewegung beim Scrollen ein- und ausgeschaltet wird. Das e.targetbezieht sich auf das Element, mit dem der Touch-Start beginnt.

Sie möchten die Standardeinstellung für das Touch-Move-Ereignis verhindern, müssen jedoch auch Ihre Markierung am Ende des Touch-Ereignisses löschen, da sonst keine Touch-Scroll-Ereignisse funktionieren.

Dies kann ohne jQuery erreicht werden. Für meine Verwendung hatte ich jedoch bereits jQuery und musste nichts codieren, um festzustellen, ob das Element ein bestimmtes übergeordnetes Element hat.

Getestet in Chrome auf Android und einem iPod Touch ab dem 18.06.2013

Turnerj
quelle
Dieser ist brillant!
Gjermund Dahl
Ich fand, dass dies für meine Bedürfnisse funktioniert, $(".carousel").on('touchstart', function (e) { e.preventDefault(); });was ein Auf- und Ab-Scrollen auf meinem Karussell verhindert :)
Chris C
2
Chrome ignoriert jetzt event.preventDefault () für Touch-Ereignisse, sodass dies nicht funktioniert. Siehe: developer.google.com/web/updates/2017/01/…
nevf
1
Vielen Dank an @nevf, ich habe meiner Antwort eine Notiz hinzugefügt, die darauf hinweist und auf JohnWeisz 'Antwort für den anscheinend empfohlenen Ansatz verweist. Ich bin froh zu wissen, dass mein Ansatz mindestens ein paar Jahre gedauert hat. 🙂
Turnerj
24

Es gibt einen kleinen "Hack" in CSS, mit dem Sie auch das Scrollen deaktivieren können:

.lock-screen {
    height: 100%;
    overflow: hidden;
    width: 100%;
    position: fixed;
}

Durch Hinzufügen dieser Klasse zum Textkörper wird das Scrollen verhindert.

Mehdi
quelle
2
Dies funktionierte perfekt für mich auf dem iPhone / iPad. Vielen Dank!
TK123
Diese Lösung ist die beste. Ich habe sowohl den akzeptierten als auch den am meisten gewählten ausprobiert. Beides hat nicht funktioniert. Dieser ist sauber und leicht.
Murtaza Munshi
Stimmen Sie zu, diese Lösung ist auch für mich am besten.
Eurobertics
19
document.addEventListener('touchstart', function(e) {e.preventDefault()}, false);
document.addEventListener('touchmove', function(e) {e.preventDefault()}, false);

Dies sollte das Scrollen verhindern, aber es werden auch andere Berührungsereignisse unterbrochen, sofern Sie keine benutzerdefinierte Methode zum Behandeln dieser Ereignisse definieren.

Raphael Rafatpanah
quelle
5
Ich hatte dies mit ontouchmove versucht, wodurch das Scrollen deaktiviert wurde, aber ich konnte es nicht zurückbekommen.
Scott Hunter
4
Es fehlt eine wichtige Sache: Sie müssen setzen{passive: false} document.addEventListener('touchstart', handleEndEventFn, { passive: false });
dreampulse
Ich habe festgestellt, dass nur das Deaktivieren, touchmoveaber anstatt den Ereignislistener an das Dokument zu binden, das direkte Binden an das Canvas-Element dazu beigetragen hat, das Scrollen bei Verwendung des Canvas zu verhindern, aber touchstartfunktionieren durfte , da ich es nicht verhindert habe.
Badrush
Wie bekomme ich den Touchmove zurück? Ich habe versucht anzurufen document.removeEventListener('touchmove', handleFn), aber es funktioniert nicht.
Newman
@newman Um es erfolgreich zu entfernen, müssen Sie alle Parameter genau so haben, wie Sie es hinzugefügt haben, einschließlich {passiv: false}
Johncl
2

Die ultimative Lösung wäre Einstellung overflow: hidden;auf document.documentElementetwa so:

/* element is an HTML element You want catch the touch */
element.addEventListener('touchstart', function(e) {
    document.documentElement.style.overflow = 'hidden';
});

document.addEventListener('touchend', function(e) {
    document.documentElement.style.overflow = 'auto';
});

Durch die Einstellung overflow: hiddenbeim Start der Berührung wird alles, was über das Fenster hinausgeht, ausgeblendet, wodurch die Verfügbarkeit zum Scrollen aufgehoben wird (kein zu scrollender Inhalt).

Nach touchenddem Sperren kann durch Setzen overflowauf auto(der Standardwert) freigegeben werden .

Es ist besser, dies anzuhängen, <html>da dies <body>möglicherweise zum Stylen verwendet wird und Kinder sich unerwartet verhalten können.

BEARBEITEN: Info touch-action: none;- Safari unterstützt es laut MDN nicht .

soanvig
quelle
Dies funktionierte für mich auf dem iPad (iOS 13), auf dem jeweils nur ein Element beweglich sein soll. e.preventDefault (); scheint die srceen nicht daran zu hindern, sich zu bewegen.
JScarry
0

Versuchen Sie, den Überlauf auf dem Objekt zu verbergen, das Sie nicht scrollen möchten, während ein Berührungsereignis stattfindet. Setzen Sie z. B. den Überlauf beim Start ausgeblendet und am Ende wieder auf Auto.

Hast Du es versucht ? Es würde mich interessieren, ob dies funktionieren würde.

document.addEventListener('ontouchstart', function(e) {
    document.body.style.overflow = "hidden";
}, false);

document.addEventListener('ontouchmove', function(e) {
    document.body.style.overflow = "auto";
}, false);
Woody
quelle
Mir ist nicht klar, wie ich das verwenden soll. Wo / wann werden diese Anrufe getätigt? Wie wird das normale Scrollen wiederhergestellt, sobald die "Berührung" abgeschlossen ist (touchmove bezeichnet nicht das ENDE der Berührung, sondern nur eine Bewegung INNERHALB einer Berührung, wie ich es verstehe).
Scott Hunter
Das normale Scrollen wird wiederhergestellt, indem der Überlauf auf Auto zurückgesetzt wird. Tatsächlich entfernen Sie in diesem Fall die Bildlaufleisten und damit die Bildlauffähigkeit des Körpers. Sie müssten es also wieder aktivieren, wenn Sie mit der Geste fertig sind, die das unerwünschte Scrollen beeinflusst. Wäre das ontouchend?
Woody
Dies war mein erster Gedanke, aber es funktioniert nicht auf dem Handy
Oldboy
0

Ich fand, dass das ev.stopPropagation();für mich funktioniert hat.

Micahblu
quelle
0

Zu meiner Überraschung funktioniert die Methode "prepareDefault ()" für mich unter dem neuesten Google Chrome (Version 85) unter iOS 13.7. Es funktioniert auch auf Safari auf demselben Gerät und auch auf meinem Android 8.0-Tablet. Ich habe es derzeit für die 2D-Ansicht auf meiner Website hier implementiert: https://papercraft-maker.com

Phuocdh90
quelle