Ich muss das Wischen nach links/rechts erkennen und darauf reagieren, aber ich möchte dem Benutzer die Möglichkeit geben, auf demselben Element zu scrollen, solange er seinen Finger nur nach links/rechts bewegt und dabei maximal X Pixel nach oben/unten bewegt sollte nicht scrollen, aber wenn er X überschreitet, sollte scrollen.
Also was ich getan habe ist:
var startX, startY, $this = $(this);
function touchmove(event) {
var touches = event.originalEvent.touches;
if (touches && touches.length) {
var deltaX = touches[0].pageX - startX;
var deltaY = touches[0].pageY - startY;
if (Math.abs(deltaY) > 50) {
$this.html('X: ' + deltaX + '<br> Y: ' + deltaY + '<br>TRUE');
$this.unbind('touchmove', touchmove);
return true;
} else {
$this.html('X: ' + deltaX + '<br> Y: ' + deltaY);
event.preventDefault();
}
}
}
function touchstart(event) {
var touches = event.originalEvent.touches;
if (touches && touches.length) {
startX = touches[0].pageX;
startY = touches[0].pageY;
$this.bind('touchmove', touchmove);
}
//event.preventDefault();
}
Aber ich kann die Fähigkeit zum Scrollen im "Wenn" -Fall nicht wiederherstellen ...
Danke für alle Tipps.
Ich habe meine eigenen Touch-Handler-Events geschrieben. Vielleicht hilft Ihnen das
es prüft auf:
schneller Klick: 'fc'
nach links streichen: 'swl'
nach rechts streichen: 'swr'
nach oben streichen: "swu"
nach unten streichen: 'swd'
jede Prüfung initialisiert ihr entsprechendes Ereignis. Sie können jedoch scrollen und alles tun, was Sie sonst noch tun. Sie haben gerade einige neue Ereignisse.
sie brauchen swl swr. Ich empfehle Ihnen auch, fc (fastclick) für Klickereignisse zu verwenden ... es ist viel schneller als normales Klicken.
window.onload = function() {
(function(d) {
var
ce = function(e, n) {
var a = document.createEvent("CustomEvent");
a.initCustomEvent(n, true, true, e.target);
e.target.dispatchEvent(a);
a = null;
return false
},
nm = true,
sp = {
x: 0,
y: 0
},
ep = {
x: 0,
y: 0
},
touch = {
touchstart: function(e) {
sp = {
x: e.touches[0].pageX,
y: e.touches[0].pageY
}
},
touchmove: function(e) {
nm = false;
ep = {
x: e.touches[0].pageX,
y: e.touches[0].pageY
}
},
touchend: function(e) {
if (nm) {
ce(e, 'fc')
} else {
var x = ep.x - sp.x,
xr = Math.abs(x),
y = ep.y - sp.y,
yr = Math.abs(y);
if (Math.max(xr, yr) > 20) {
ce(e, (xr > yr ? (x < 0 ? 'swl' : 'swr') : (y < 0 ? 'swu' : 'swd')))
}
};
nm = true
},
touchcancel: function(e) {
nm = false
}
};
for (var a in touch) {
d.addEventListener(a, touch[a], false);
}
})(document);
//EXAMPLE OF USE
var h = function(e) {
console.log(e.type, e)
};
document.body.addEventListener('fc', h, false); // 0-50ms vs 500ms with normal click
document.body.addEventListener('swl', h, false);
document.body.addEventListener('swr', h, false);
document.body.addEventListener('swu', h, false);
document.body.addEventListener('swd', h, false);
}
in diesem Fall ist h mein Handler für jede Art von Ereignis, und ich füge die Handler dem Körper hinzu.
für was ich deine Frage verstehe, musst du nur schreiben
YOURELEMENT.addEventListener('swr',YOURSWIPERIGHTFUNCTION,false);
YOURELEMENT.addEventListener('swl',YOURSWIPELEFTFUNCTION,false);
um mehrere Elemente und dieselbe Funktion zu behandeln, fügen Sie einfach einen Handler hinzu.
also wenn du hast
<ul id="ul"><li>1</li><li>2</li><li>3</li></ul>
sie machen:
var deleteli=function(e){
var li=e.target;
console.log('deleting '+li.textContent);
}
document.getElementById('ul').addEventListener('swl',deleteli,false);
gleiches für FC & SWR
es gibt einen Fehler in ios: Verwenden Sie nicht alert (). Es wird 2 mal ausgeführt.
Die akzeptierte Antwort enthält einen "Fehler". Wenn Sie Chrome nicht für Android verwenden, sondern den eingebauten Browser oder eine "Webansicht" (z. B. für eine HTML5-Hybrid-App), wird der Swipe-Vorgang nicht erkannt.
Ich habe herausgefunden, dass das Ereignis aufgrund des normalen Scrollverhaltens nicht ausgelöst wird. So fügen Sie "e.preventDefault ();" in touchmove würde das Problem beheben oder das Update von Eric Fuller in der akzeptierten Antwort.
Es ist ein schöner Schnipsel, aber in einer mobilen WebApp oder Website kann dies zu einem störenden Scrollen führen, da die Berührungsereignisse die ganze Zeit beobachtet werden.
Also habe ich beschlossen, etwas Neues zu bauen. Es ist nicht so komfortabel wie neue Event-Hörer, aber es ist bequem genug für meine Bedürfnisse und deren Leistung.
function detectswipe(el,func) {
swipe_det = new Object();
swipe_det.sX = 0;
swipe_det.sY = 0;
swipe_det.eX = 0;
swipe_det.eY = 0;
var min_x = 20; //min x swipe for horizontal swipe
var max_x = 40; //max x difference for vertical swipe
var min_y = 40; //min y swipe for vertical swipe
var max_y = 50; //max y difference for horizontal swipe
var direc = "";
ele = document.getElementById(el);
ele.addEventListener('touchstart',function(e){
var t = e.touches[0];
swipe_det.sX = t.screenX;
swipe_det.sY = t.screenY;
},false);
ele.addEventListener('touchmove',function(e){
e.preventDefault();
var t = e.touches[0];
swipe_det.eX = t.screenX;
swipe_det.eY = t.screenY;
},false);
ele.addEventListener('touchend',function(e){
//horizontal detection
if ((((swipe_det.eX - min_x > swipe_det.sX) || (swipe_det.eX + min_x < swipe_det.sX)) && ((swipe_det.eY < swipe_det.sY + max_y) && (swipe_det.sY > swipe_det.eY - max_y)))) {
if(swipe_det.eX > swipe_det.sX) direc = "r";
else direc = "l";
}
//vertical detection
if ((((swipe_det.eY - min_y > swipe_det.sY) || (swipe_det.eY + min_y < swipe_det.sY)) && ((swipe_det.eX < swipe_det.sX + max_x) && (swipe_det.sX > swipe_det.eX - max_x)))) {
if(swipe_det.eY > swipe_det.sY) direc = "d";
else direc = "u";
}
if (direc != "") {
if(typeof func == 'function') func(el,direc);
}
direc = "";
},false);
}
myfunction(el,d) {
alert("you swiped on element with id '"+el+"' to "+d+" direction");
}
Um die Funktion zu nutzen, benutzen Sie sie einfach wie
detectswipe('an_element_id',myfunction);
detectswipe('an_other_element_id',my_other_function);
Wird ein Swipe erkannt, wird die Funktion "myfunction" mit dem Parameter element-id und "l, r, u, d" (links, rechts, auf, ab) aufgerufen.
Beispiel: http://jsfiddle.net/rvuayqeo/1/
Alle diese Codes müssen verbessert werden (wie die meisten Codes, die Sie bei der Touch-Manipulation finden können).
Beachten Sie beim Spielen mit einem Berührungsereignis, dass der Benutzer mehr als ein Finger hat, dass eine Berührung einen Bezeichner hat und dass die Liste touches
alle aktuellen Berührungen auf der Oberfläche darstellt, sogar Berührungendie sich nicht bewegt haben.
Der Prozess ist also relativ einfach:
onuchstart: Die erste geänderte Berührung wird abgerufen (nicht die event.originalEvent.touches
-Eigenschaft, sondern event.originalEvent.changedTouches
). Registrieren Sie den Bezeichner mit event.originalEvent.changedTouches[0].identifier
und den Eigenschaften von touch, nach denen gesucht werden soll (pageX
/pageY
oder clientX
/clientY
, die in Kombination mit der DOMElement.getBoundingClientRect()
-Methode sehr nützlich sind);
onuchmove: Vergewissern Sie sich, dass die aktuelle Berührung mit event.originalEvent.changedTouches.identifiedTouch( identifier )
in der geändertenTouches-Liste enthalten ist. Wenn nichts zurückgegeben wird, bedeutet dies, dass der Benutzer eine weitere Berührung verschoben hat (nicht die, nach der Sie suchen). Registrieren Sie auch die Touch-Eigenschaften, nach denen Sie suchen und tun möchten, was Sie möchten.
touchend: Auch hier müssen Sie sich vergewissern, dass sich die aktuelle Berührung in der geändertenTouches-Liste befindet. Führen Sie die Arbeit mit den Berührungseigenschaften durch und verwerfen Sie schließlich Ihre aktuelle Berührungskennung.
Wenn Sie es stärker machen möchten, sollten Sie mehrere Berührungen berücksichtigen (nicht nur eine).
Weitere Informationen zu TouchEvent, TouchList und Touch unter: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Touch_events
Inspiriert von @cocco habe ich eine bessere (nicht minimierte) Version erstellt:
(function(d) {
// based on original source: https://stackoverflow.com/a/17567696/334451
var newEvent = function(e, name) {
// This style is already deprecated but very well supported in real world: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/initCustomEvent
// in future we want to use CustomEvent function: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
var a = document.createEvent("CustomEvent");
a.initCustomEvent(name, true, true, e.target);
e.target.dispatchEvent(a);
a = null;
return false
};
var debug = false; // emit info to JS console for all touch events?
var active = false; // flag to tell if touchend should complete the gesture
var min_gesture_length = 20; // minimum gesture length in pixels
var tolerance = 0.3; // value 0 means pixel perfect movement up or down/left or right is required, 0.5 or more means any diagonal will do, values between can be tweaked
var sp = { x: 0, y: 0, px: 0, py: 0 }; // start point
var ep = { x: 0, y: 0, px: 0, py: 0 }; // end point
var touch = {
touchstart: function(e) {
active = true;
t = e.touches[0];
sp = { x: t.screenX, y: t.screenY, px: t.pageX, py: t.pageY };
ep = sp; // make sure we have a sensible end poin in case next event is touchend
debug && console.log("start", sp);
},
touchmove: function(e) {
if (e.touches.length > 1) {
active = false;
debug && console.log("aborting gesture because multiple touches detected");
return;
}
t = e.touches[0];
ep = { x: t.screenX, y: t.screenY, px: t.pageX, py: t.pageY };
debug && console.log("move", ep, sp);
},
touchend: function(e) {
if (!active)
return;
debug && console.log("end", ep, sp);
var dx = Math.abs(ep.x - sp.x);
var dy = Math.abs(ep.y - sp.y);
if (Math.max(dx, dy) < min_gesture_length) {
debug && console.log("ignoring short gesture");
return; // too short gesture, ignore
}
if (dy > dx && dx/dy < tolerance && Math.abs(sp.py - ep.py) > min_gesture_length) { // up or down, ignore if page scrolled with touch
newEvent(e, (ep.y - sp.y < 0 ? 'gesture-up' : 'gesture-down'));
//e.cancelable && e.preventDefault();
}
else if (dx > dy && dy/dx < tolerance && Math.abs(sp.px - ep.px) > min_gesture_length) { // left or right, ignore if page scrolled with touch
newEvent(e, (ep.x - sp.x < 0 ? 'gesture-left' : 'gesture-right'));
//e.cancelable && e.preventDefault();
}
else {
debug && console.log("ignoring diagonal gesture or scrolled content");
}
active = false;
},
touchcancel: function(e) {
debug && console.log("cancelling gesture");
active = false;
}
};
for (var a in touch) {
d.addEventListener(a, touch[a], false);
// TODO: MSIE touch support: https://github.com/CamHenlin/TouchPolyfill
}
})(window.document);
Wichtige Änderungen gegenüber der Originalversion von @cocco:
event.touches[0].screenX/screenY
als Hauptinformationsquelle. Die pageX/pageY
-Eigenschaften stellen die Bewegung von Berührungen auf dem Bildschirm nicht korrekt dar. Wenn ein Teil der Seite mit der Berührung scrollt, wirkt sich dies auch auf die pageX/pageY
-Werte aus.pageX/pageY
, bevor Sie die Geste auslösen).Dinge, die in der Zukunft getan werden müssten:
CustomEvent()
function interface anstelle der createEvent()
-Methode.pageX/pageY
getrennt von screenX/screenY
konfigurieren?Die Verwendung ist wie folgt:
document.body.addEventListener('gesture-right', function (e) { ... });
oder Jquery-Stil
$("article").on("gesture-down", function (e) { ... });
Das Erkennen von links und rechts während der Berührung ist bewegt sich noch .
Dies erfolgt durch Speichern der letzten Position und Verwenden von timeout zum Löschen der letzten Position nach dem Touchmove-Stopp.
var currentX;
var lastX = 0;
var lastT;
$(document).bind('touchmove', function(e) {
// If still moving clear last setTimeout
clearTimeout(lastT);
currentX = e.originalEvent.touches[0].clientX;
// After stoping or first moving
if(lastX == 0) {
lastX = currentX;
}
if(currentX < lastX) {
// Left
} else if(currentX > lastX){
// Right
}
// Save last position
lastX = currentX;
// Check if moving is done
lastT = setTimeout(function() {
lastX = 0;
}, 100);
});