TL;DR
サンプルコード があるのでそれでだいたい分かると思う。
はじめに
同じ DOM に対して クリック処理とドラッグ処理をさせたいときってありますよね?
rxjs6 ならそこそこ楽に書けますよ。
実装
まずこちらの html と css を用意して
<div id="sample" />
#sample {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background-color: #00a1e9;
}
#sample
に対するクリックとドラッグの識別をやってみます。
具体的には ドラッグ開始 と クリック を識別します。それぞれ以下と定義します。
- ドラッグ開始 … マウスが押されてから一定時間押しっぱなしであること
- クリック … マウスが押されてから一定時間にマウスが離されること
上記処理の 早く発火した方 を拾うことができればいいわけです。
まず source のストリームを作ります。
1.
2.
をそれぞれ of(e).pipe(delay(200))
、fromEvent(el, 'mouseup')
と実装しています。
これらのストリームを merge
して first
で早く発火したほうを次へ流します。
最後に share
で以降のドラッグとクリックの subscribe で同一のストリームを受け取るようにします。
const el = document.getElementById('sample')
const source = fromEvent(el, 'mousedown').pipe(
switchMap((e) =>{
// 200ms 遅延した mousedown イベント または
// mouseup イベントの
// どちらか早く発火した方を次へ流す
return merge(
of(e).pipe(delay(200)),
fromEvent(el, 'mouseup')
).pipe(first())
}),
share()
)
続いて subscribe の実装ですが、e.type === 'mouseup'
でクリックかドラッグ開始か判別しています。
あとは煮るなり焼くなりしてみてください。
// e.type でクリックかドラッグか識別する
const click = source.pipe(
filter((e) => e.type === 'mouseup')
).subscribe((e) => {
alert('click!')
})
const drag = source.pipe(
filter((e) => e.type !== 'mouseup')
).subscribe((e) => {
alert('drag!')
})
まとめ
楽ですね。