2015-10-23 15 views
5

entfernt Ich versuche, eine Drag-ähnliche Funktionalität mit dem nächsten Muster zu implementieren:Touch-Move-Ereignis nicht ausgelöst, nachdem Berühren Sie Start, Ziel ist

  • Abonnieren Pointer-Down-Ereignis Marker.
  • Wenn das Ereignis "Down" ausgelöst wird, werden die Ereignisse "Window Pointer Move and Up" und die Markierung "Marker entfernen" subskribiert.
  • Führen Sie einige Aktionen beim Verschieben aus.
  • Wenn Up-Ereignis ausgelöst wird, Abmelden von Move and Up.

Dies funktioniert für Mausereignisse, aber nicht für Berührungsereignisse. Sie werden nicht ausgelöst, nachdem das Touch Start-Zielelement entfernt wurde. Ich habe versucht, Pointer Events Polyfill zu verwenden, aber es funktioniert auch nicht.

Ich verwende Chrome-Entwicklungstools, um Berührungsereignisse zu emulieren. Siehe die Probe:

initTestBlock('mouse', { 
 
    start: 'mousedown', 
 
    move: 'mousemove', 
 
    end: 'mouseup' 
 
}); 
 
initTestBlock('touch', { 
 
    start: 'touchstart', 
 
    move: 'touchmove', 
 
    end: 'touchend' 
 
}); 
 
initTestBlock('touch-no-remove', { 
 
    start: 'touchstart', 
 
    move: 'touchmove', 
 
    end: 'touchend' 
 
}, true); 
 

 
function initTestBlock(id, events, noRemove) { 
 
    var block = document.getElementById(id); 
 
    var parent = block.querySelector('.parent'); 
 
    var target = block.querySelector('.target'); 
 
    target.addEventListener(events.start, function(e) { 
 
    console.log(e.type); 
 
    if (!noRemove) { 
 
     setTimeout(function() { 
 
     // Remove target 
 
     target.parentElement.removeChild(target); 
 
     }, 1000); 
 
    } 
 

 
    function onMove(e) { 
 
     console.log(e.type); 
 
     var pt = getCoords(e); 
 
     parent.style.left = pt.x + 'px'; 
 
     parent.style.top = pt.y + 'px'; 
 
    } 
 

 
    function onEnd(e) { 
 
     console.log(e.type); 
 
     window.removeEventListener(events.move, onMove); 
 
     window.removeEventListener(events.end, onEnd); 
 
    } 
 

 
    window.addEventListener(events.move, onMove); 
 
    window.addEventListener(events.end, onEnd); 
 

 
    }); 
 
} 
 

 
// Returns pointer coordinates 
 
function getCoords(e) { 
 
    if (e instanceof TouchEvent) { 
 
    return { 
 
     x: e.touches[0].pageX, 
 
     y: e.touches[0].pageY 
 
    }; 
 
    } 
 
    return { 
 
    x: e.pageX, 
 
    y: e.pageY 
 
    }; 
 
} 
 

 
window.addEventListener('selectstart', function() { 
 
    return false; 
 
}, true);
.parent { 
 
    background: darkred; 
 
    color: white; 
 
    width: 10em; 
 
    height: 10em; 
 
    position: absolute; 
 
} 
 
.target { 
 
    background: orange; 
 
    width: 4em; 
 
    height: 4em; 
 
} 
 
#mouse .parent { 
 
    left: 0em; 
 
} 
 
#touch .parent { 
 
    left: 11em; 
 
} 
 
#touch-no-remove .parent { 
 
    left: 22em; 
 
}
<div id="mouse"> 
 
    <div class="parent">Mouse events 
 
    <div class="target">Drag here</div> 
 
    </div> 
 
</div> 
 
<div id="touch"> 
 
    <div class="parent">Touch events 
 
    <div class="target">Drag here</div> 
 
    </div> 
 
</div> 
 
<div id="touch-no-remove"> 
 
    <div class="parent">Touch (no remove) 
 
    <div class="target">Drag here</div> 
 
    </div> 
 
</div>

+0

Ich habe ein verwandtes Problem. Hast du inzwischen eine Lösung gefunden? –

+0

@SebastianvomMeer Siehe meine Antwort http://StackOverflow.com/A/34980275/4137472 –

Antwort

2

Der Trick Element bis Touch bewegen Oberflächen zu verbergen, aber nicht um sie zu entfernen. Hier einige Beispiel ist (Touch-Modus in Chrome Dev-Tools ermöglichen und eine Vorrichtung oder verwenden reale Gerät wählen): https://jsfiddle.net/alexanderby/na3rumjg/

var marker = document.querySelector('circle'); 
 
var onStart = function(startEvt) { 
 
    startEvt.preventDefault(); // Prevent scroll 
 
    marker.style.visibility = 'hidden'; // Hide target element 
 
    var rect = document.querySelector('rect'); 
 
    var initial = { 
 
    x: +rect.getAttribute('x'), 
 
    y: +rect.getAttribute('y') 
 
    }; 
 
    var onMove = function(moveEvt) { 
 
    rect.setAttribute('x', initial.x + moveEvt.touches[0].clientX - startEvt.touches[0].clientX); 
 
    rect.setAttribute('y', initial.y + moveEvt.touches[0].clientY - startEvt.touches[0].clientY); 
 
    }; 
 
    var onEnd = function(endEvt) { 
 
    window.removeEventListener('touchmove', onMove); 
 
    window.removeEventListener('touchend', onEnd); 
 
    marker.removeEventListener('touchstart', onStart); 
 
    marker.parentElement.removeChild(marker); // Remove target element 
 
    }; 
 
    window.addEventListener('touchmove', onMove); 
 
    window.addEventListener('touchend', onEnd); 
 
}; 
 
marker.addEventListener('touchstart', onStart);
<svg> 
 
    <circle r="20" cx="50" cy="20" cursor="move"/> 
 
    <rect x="10" y="50" width="80" height="80" /> 
 
</svg>

3

Tatsächlich according to the docs,

Wenn die Zielelement wird aus dem Dokument entfernt, Ereignisse werden immer noch auf dieses Ziel gerichtet sein und werden daher nicht unbedingt bis zum Fenster 01 gesprungenoder Dokument nicht mehr. Wenn das Risiko besteht, dass ein Element entfernt wird, während es berührt wird, empfiehlt es sich, die Listener direkt an das Ziel anzuhängen.

Es stellt sich heraus, dass die Lösung touchmove und touchend Zuhörer auf die event.target selbst, zum Beispiel zu befestigen ist:

element.addEventListener("touchstart", (event) => { 
    const onTouchMove =() => { 
     // handle touchmove here 
    } 
    const onTouchEnd =() => { 
     event.target.removeEventListener("touchmove", onTouchMove); 
     event.target.removeEventListener("touchend", onTouchEnd); 
     // handle touchend here 
    } 
    event.target.addEventListener("touchmove", onTouchMove); 
    event.target.addEventListener("touchend", onTouchEnd); 
    // handle touchstart here 
}); 

Auch wenn das event.target Element aus dem DOM entfernt wird, wird auch weiterhin Ereignisse auszulösen normalerweise und geben Sie die richtigen Koordinaten ein.

+1

Dies rettete meinen Tag! : D – raeffs