概要
マウスドラッグのハンドリングに関するアイデア
提案
- mousedown で mousemove, mouseup を登録する関数を渡す
背景
ツール系アプリに鉛筆ツールや範囲選択ツールなど複数の機能を実装するにあたって、それぞれのツールをクラスとして作っていましたが、複雑だし this
がカッコ悪いなぁと思いました。
JavaScript ではなるべく普通の変数、関数を使うのが良いと最近思うので、そのように書き直してみました。
元々のクラス
export class PencilMouseHandler {
constructor(emitter) {
this.emitter = emitter
}
onMouseDown(e) {
const {offsetX, offsetY} = e
this.startPosition = {x: offsetX, y: offsetY}
this.emitter.trigger("start-pencil-drawing", this.startPosition)
}
onMouseMove(e) {
const {offsetX, offsetY} = e
this.emitter.trigger("move-pencil", {movement: {
x: offsetX - this.startPosition.x,
y: offsetY - this.startPosition.y
}})
}
onMouseUp() {}
}
関数版1
イベントを登録する関数 onMouseDown
, onMouseMove
を渡すことで
this.emitter
と this.startPosition
を普通の変数にできました。
function handlePencilMouse(emitter, onMouseDown, onMouseMove, onMouseUp) {
let startPosition
onMouseDown(e => {
const {offsetX, offsetY} = e
startPosition = {x: offsetX, y: offsetY}
emitter.trigger("start-pencil", startPosition)
})
onMouseMove(e => {
const {offsetX, offsetY} = e
emitter.trigger("move-pencil", {movement: {
x: offsetX - this.startPosition.x,
y: offsetY - this.startPosition.y
}})
})
}
(onMouseDown
, onMouseMove
, onMouseUp
で登録した関数は mouseup 後に破棄されることにします)
関数版2
このアプリではマウスダウン中のドラッグしか扱わないので、onMouseDown で onMouseMove, onMouseUp を渡します。(提案する部分です)
これで onMouseMove, onMouseUp が onMouseDown の後に呼ばれることがハッキリするのと、let startPosition
を const にできました。
function handlePencilMouse(emitter, onMouseDown) {
onMouseDown((e, onMouseMove, onMouseUp) => {
const {offsetX, offsetY} = e
const startPosition = {x: offsetX, y: offsetY}
emitter.trigger("start-pencil", startPosition)
onMouseMove(e => {
const {offsetX, offsetY} = e
emitter.trigger("move-pencil", {movement: {
x: offsetX - this.startPosition.x,
y: offsetY - this.startPosition.y
}})
})
})
}
関数版3
そもそも動作が onMouseDown から始まるので、関数自体を mousedown イベントに登録します
function handlePencilMouseDown(emitter, e, onMouseMove, onMouseUp) => {
const {offsetX, offsetY} = e
const startPosition = {x: offsetX, y: offsetY}
emitter.trigger("start-pencil", startPosition)
onMouseMove(e => {
const {offsetX, offsetY} = e
emitter.trigger("move-pencil", {movement: {
x: offsetX - this.startPosition.x,
y: offsetY - this.startPosition.y
}})
})
}
まとめ
- クラスよりも関数を使いたい
- mousedown 時に mouseup, mousemove を登録させると短くできる
オチ
読みづらいので実際のアプリでは関数版1を使いました