我正在构建一个音频播放控件,让用户可以在音频文件中来回擦洗.它需要处理触摸和鼠标事件.我应该如何使用被动事件流来管理事件?
以下是我希望如何构建它的大致想法.
<div id="timeline"> <span id="scrubber"></span> </div>
然后,使用Bacon.js创建事件流
var mousedowns = $('#timeline').asEventStream('mousedown'); var touchstarts = $('#timeline').asEventStream('touchstart'); var starts = Bacon.mergeAll(mousedowns,touchstarts); var mousemoves = $('#timeline').asEventStream('mousemove'); var touchmoves = $('#timeline').asEventStream('touchmove'); var moves = Bacon.mergeAll(mousemoves,touchmoves); var mouseups = $('#timeline').asEventStream('mouseup'); var touchends = $('#timeline').asEventStream('touchend'); var ends = Bacon.mergeAll(mouseups,touchends); starts.onValue(function () { var repositionScrubber = moves.onValue(function (ev) { $('#scrubber').moveTo(ev.offsetX); }); ends.onValue(function () { repositionScrubber.stop(); }); });
我确定这是各种各样的错误,但我真的很擅长处理具有可观察流的事件,我还不知道它有什么好的烹饪书.任何帮助将不胜感激!
解决方法
这基本上是规范的
drag and drop recipe.
RxJS中的最小工作示例是这样的:
var $timeline = $('#timeline'); var $scrubber = $('#scrubber'); var mouseDown = Rx.Observable.merge( Rx.Observable.fromEvent($timeline,'mousedown'),Rx.Observable.fromEvent($timeline,'touchstart')); var mouseUp = Rx.Observable.merge( Rx.Observable.fromEvent($timeline,'mouseup'),'touchend')); var mouseMove = Rx.Observable.merge( Rx.Observable.fromEvent($timeline,'mousemove'),'touchmove')); var subscription = mouseDown.flatMapLatest(function(md) { // calculate offsets when mouse down var startX = md.offsetX; return mouseMove.takeUntil(mouseUp) .map(function(mm) { mm.preventDefault(); return { left: mm.clientX - startX,}; }); }) .subscribe(function(e) { $scrubber.css(e); });
var $timeline = $('#timeline'); var $scrubber = $('#scrubber'); var mouseDown = Rx.Observable.merge( Rx.Observable.fromEvent($timeline,'touchstart')); var mouseUp = Rx.Observable.merge( Rx.Observable.fromEvent($timeline,'touchend')); var mouseMove = Rx.Observable.merge( Rx.Observable.fromEvent($timeline,'touchmove')); var subscription = mouseDown.flatMapLatest(function(md) { // calculate offsets when mouse down var startX = md.offsetX; return mouseMove.takeUntil(mouseUp) .map(function(mm) { mm.preventDefault(); return { left: mm.clientX - startX,}; }); }) .subscribe(function(e) { $scrubber.css(e); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/2.5.3/rx.all.js"></script> <div id="timeline" style="height: 100px; width: 100px; background: yellow; position: absolute;"> <span id="scrubber" style="height: 20px; width: 30px; background: green; position: relative;">Foo</span> </div>