class Mouse {
/**
* Create and start mouse obj, args: a model, and a callback method.
*
* @param {Canvas|String} canvas The canvas upon which we track the mouse.
* If a string is given, get the HTML element by that name
* @param {world} world World instance
* @param {Function} callback callback(mouse) called on every mouse action
*/
// constructor(canvas, world, callback = (evt, mouse) => {}) {
constructor(model, view, callback) {
Object.assign(this, { model, view, callback })
this.canvas = view.canvas
this.world = model.world
// callMouseHandler: arrow fnc to insure "this" is mouse.
this.callMouseHandler = e => this.mouseHandler(e)
this.isRunning = this.mouseDown = false
this.x = this.y = this.action = null
this.setContinuous(false)
}
setContinuous(continuous = true) {
this.continuous = continuous
return this
}
/**
* Start the mouseListeners.
* @returns this Return this instance for chaining
*/
start() {
// Note: multiple calls safe
this.canvas.addEventListener('mousedown', this.callMouseHandler)
if (this.continuous) this.startMouse()
this.isRunning = true
return this // chaining
}
/**
* Start the mouseListeners.
* @returns this Return this instance for chaining
*/
stop() {
// Note: multiple calls safe
this.canvas.removeEventListener('mousedown', this.callMouseHandler)
this.stopMouse()
this.isRunning = false
return this // chaining
}
startMouse() {
document.body.addEventListener('mouseup', this.callMouseHandler)
this.canvas.addEventListener('mousemove', this.callMouseHandler)
}
stopMouse() {
document.body.removeEventListener('mouseup', this.callMouseHandler)
this.canvas.removeEventListener('mousemove', this.callMouseHandler)
}
mouseHandler(e) {
if (e.type === 'mousedown') {
if (!this.continuous) this.startMouse()
this.mouseDown = true
}
if (e.type === 'mouseup') {
if (!this.continuous) this.stopMouse()
this.mouseDown = false
}
this.action = e.type
if (e.type === 'mousemove' && this.mouseDown) {
this.action = 'mousedrag'
}
this.setXY(e)
this.callback(this)
}
// set x, y to be event location in turtle coordinates, floats.
setXY(e) {
const { canvas, world } = this
const patchSize = world.patchSize(canvas)
const rect = this.canvas.getBoundingClientRect()
const pixX = e.clientX - rect.left
const pixY = e.clientY - rect.top
const [x, y] = world.pixelXYtoPatchXY(pixX, pixY, patchSize)
Object.assign(this, { x, y })
}
}
export default Mouse