123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- import { getTowPointDistance } from './utils'
- import EventEmitter from 'eventemitter3'
- // 事件类
- export default class Event extends EventEmitter {
- constructor(app) {
- super()
- this.app = app
- this.coordinate = app.coordinate
- // 鼠标是否按下
- this.isMousedown = false
- // 按下时的鼠标位置
- this.mousedownPos = {
- x: 0,
- y: 0,
- unGridClientX: 0,
- unGridClientY: 0,
- originClientX: 0,
- originClientY: 0
- }
- // 鼠标当前位置和按下时位置的差值
- this.mouseOffset = {
- x: 0,
- y: 0,
- originX: 0,
- originY: 0
- }
- // 记录上一时刻的鼠标位置
- this.lastMousePos = {
- x: 0,
- y: 0
- }
- // 前一瞬间的鼠标移动距离
- this.mouseDistance = 0
- // 记录上一时刻的时间
- this.lastMouseTime = Date.now()
- // 前一瞬间的时间
- this.mouseDuration = 0
- // 前一瞬间的鼠标移动速度
- this.mouseSpeed = 0
- // 绑定事件
- this.onMousedown = this.onMousedown.bind(this)
- this.onMousemove = this.onMousemove.bind(this)
- this.onMouseup = this.onMouseup.bind(this)
- this.onDblclick = this.onDblclick.bind(this)
- this.onMousewheel = this.onMousewheel.bind(this)
- this.onKeydown = this.onKeydown.bind(this)
- this.onKeyup = this.onKeyup.bind(this)
- this.onContextmenu = this.onContextmenu.bind(this)
- this.bindEvent()
- }
- // 绑定canvas事件
- bindEvent() {
- this.app.container.addEventListener('mousedown', this.onMousedown)
- this.app.container.addEventListener('mousemove', this.onMousemove)
- this.app.container.addEventListener('mouseup', this.onMouseup)
- this.app.container.addEventListener('dblclick', this.onDblclick)
- this.app.container.addEventListener('mousewheel', this.onMousewheel)
- this.app.container.addEventListener('contextmenu', this.onContextmenu)
- window.addEventListener('keydown', this.onKeydown)
- window.addEventListener('keyup', this.onKeyup)
- }
- // 解绑事件
- unbindEvent() {
- this.app.container.removeEventListener('mousedown', this.onMousedown)
- this.app.container.removeEventListener('mousemove', this.onMousemove)
- this.app.container.removeEventListener('mouseup', this.onMouseup)
- this.app.container.removeEventListener('dblclick', this.onDblclick)
- this.app.container.removeEventListener('mousewheel', this.onMousewheel)
- this.app.container.removeEventListener('contextmenu', this.onContextmenu)
- window.removeEventListener('keydown', this.onKeydown)
- window.removeEventListener('keyup', this.onKeyup)
- }
- // 转换事件对象e
- // 1.将相当于浏览器窗口左上角的坐标转换成相对容器左上角
- // 2.如果画布进行了缩放,那么鼠标坐标要反向进行缩放
- // 3.x、y坐标加上了画布水平和垂直的滚动距离scrollX和scrollY
- // 4.如果开启了网格,那么坐标要吸附到网格上
- transformEvent(e) {
- let { coordinate } = this.app
- // 容器和窗口左上角存在距离时转换
- let wp = coordinate.windowToContainer(e.clientX, e.clientY)
- // 元素缩放是*scale,所以视觉上我们点击到了元素,但是实际上元素的位置还是原来的x,y,所以鼠标的坐标需要/scale
- let { x, y } = coordinate.reverseScale(wp.x, wp.y)
- // 加上滚动偏移
- x = coordinate.addScrollX(x)
- y = coordinate.addScrollY(y)
- // 保存未吸附到网格的坐标,用于位置检测等不需要吸附的场景
- let unGridClientX = x
- let unGridClientY = y
- // 如果开启了网格,那么要坐标要吸附到网格
- let gp = coordinate.gridAdsorbent(x, y)
- let newEvent = {
- originEvent: e,
- unGridClientX,
- unGridClientY,
- clientX: gp.x,
- clientY: gp.y // 向下滚动scroll值为正,而canvas坐标系向下为正,所以要造成元素向上滚动的效果显示的时候元素的y坐标需要减去scroll值,但是元素真实的y值并未改变,所以对于鼠标坐标来说需要加上scroll值,这样才能匹配元素真实的y坐标,水平方向也是一样的。
- }
- return newEvent
- }
- // 鼠标按下事件
- onMousedown(e) {
- e = this.transformEvent(e)
- this.isMousedown = true
- this.mousedownPos.x = e.clientX
- this.mousedownPos.y = e.clientY
- this.mousedownPos.unGridClientX = e.unGridClientX
- this.mousedownPos.unGridClientY = e.unGridClientY
- this.mousedownPos.originClientX = e.originEvent.clientX
- this.mousedownPos.originClientY = e.originEvent.clientY
- this.emit('mousedown', e, this)
- }
- // 鼠标移动事件
- onMousemove(e) {
- e = this.transformEvent(e)
- let x = e.clientX
- let y = e.clientY
- // 鼠标按下状态
- if (this.isMousedown) {
- this.mouseOffset.x = x - this.mousedownPos.x
- this.mouseOffset.y = y - this.mousedownPos.y
- this.mouseOffset.originX =
- e.originEvent.clientX - this.mousedownPos.originClientX
- this.mouseOffset.originY =
- e.originEvent.clientY - this.mousedownPos.originClientY
- }
- let curTime = Date.now()
- // 距离上一次的时间
- this.mouseDuration = curTime - this.lastMouseTime
- // 距离上一次的距离
- this.mouseDistance = getTowPointDistance(
- x,
- y,
- this.lastMousePos.x,
- this.lastMousePos.y
- )
- // 鼠标移动速度
- this.mouseSpeed = this.mouseDistance / this.mouseDuration
- this.emit('mousemove', e, this)
- // 更新变量
- this.lastMouseTime = curTime
- this.lastMousePos.x = x
- this.lastMousePos.y = y
- }
- // 鼠标松开事件
- onMouseup(e) {
- e = this.transformEvent(e)
- // 复位
- this.isMousedown = false
- this.mousedownPos.x = 0
- this.mousedownPos.y = 0
- this.emit('mouseup', e, this)
- }
- // 双击事件
- onDblclick(e) {
- e = this.transformEvent(e)
- this.emit('dblclick', e, this)
- }
- // 鼠标滚动事件
- onMousewheel(e) {
- e = this.transformEvent(e)
- this.emit('mousewheel', e.originEvent.wheelDelta < 0 ? 'down' : 'up')
- }
- // 右键菜单事件
- onContextmenu(e) {
- e.stopPropagation()
- e.preventDefault()
- e = this.transformEvent(e)
- this.emit('contextmenu', e, this)
- }
- // 按键按下事件
- onKeydown(e) {
- this.emit('keydown', e, this)
- }
- // 按键松开事件
- onKeyup(e) {
- this.emit('keyup', e, this)
- }
- }
|