软件项目技术点(6)——结合鼠标操作绘制动态canvas画布
AxeSlide软件项目梳理 canvas绘图系列知识点整理
我们创建一个类封装了所有鼠标需要处理的事件。
1 export class MouseEventInfo { 2 el: HTMLElement; 3 onmouseDown: Function; 4 ondragMove: Function; 5 ondragUp: Function; 6 onmouseMove: Function; 7 onmouseUp: Function; 8 mouseWheel: Function; 9 onContextMenu: Function; 10 constructor(ele: any, mouseDown: Function, dragMove: Function, dragUp: Function, mouseMove: Function, mouseUp: Function, mouseWheel: Function, contexMenu: Function) { 11 this.el = ele; 12 this.onmouseDown = mouseDown || null; 13 this.ondragMove = dragMove || null; 14 this.ondragUp = dragUp || null; 15 this.onmouseMove = mouseMove || null; 16 this.onmouseUp = mouseUp || null; 17 this.mouseWheel = mouseWheel || null 18 this.onContextMenu = contexMenu; 19 } 20 }
MouseEventClass就是绑定事件的过程,我们这里只列出部分代码,未列出的事件绑定的部分同理。
1 export class MouseEventClass { 2 x: number; 3 y: number; 4 down: boolean; 5 dragging: boolean; 6 scroll: boolean; 7 lastX: number; 8 lastY: number; 9 startX: number; 10 startY: number; 11 moveCount: number; 12 eventInfo: MouseEventInfo; 13 constructor(eInfo: MouseEventInfo) { 14 this.moveCount = 0; 15 this.x = 0; 16 this.y = 0; 17 this.lastX = 0; 18 this.lastY = 0; 19 this.startX = 0; 20 this.startY = 0; 21 this.down = false; 22 this.eventInfo = eInfo; 23 this.dragging = false; 24 this.scroll = false; 25 26 var on = impressEvent.on; 27 var self = this; 28 if (this.eventInfo.el) { 29 on(this.eventInfo.el, "mousedown", function (e) { 30 if (e.button == 1 || e.button == 2) { 31 e.preventDefault(); 32 return false; 33 } 34 self.mousedownHandler(e); 35 36 }); 37 (this.eventInfo.ondragMove || this.eventInfo.onmouseMove) && on(this.eventInfo.el, "mousemove", function (e) { 38 if (e.button == 1 || e.button == 2) { 39 e.preventDefault(); 40 return false; 41 } 42 self.mousemoveHandler(e); 43 }); 44 (this.eventInfo.ondragUp || this.eventInfo.onmouseUp) && on(this.eventInfo.el, "mouseup", function (e) { 45 if (e.button == 1 || e.button == 2) { 46 e.preventDefault(); 47 return false; 48 } 49 self.mouseupHandler(e); 50 }); 51 this.eventInfo.mouseWheel && on(this.eventInfo.el, "mousewheel", function (e) { 52 if (e.button == 1 || e.button == 2) { 53 e.preventDefault(); 54 return false; 55 } 56 self.mouseWheelHandler(e); 57 }); 58 this.eventInfo.onContextMenu && on(this.eventInfo.el, "contextmenu", function (e) { 59 if (e.button == 1) { 60 e.preventDefault(); 61 return false; 62 } 63 e.preventDefault(); 64 self.contextMenuHandler(e); 65 }) 66 }; 67 } 68 69 mousedownHandler = function (evt: MouseEvent) { 70 this.moveCount = 1; 71 this.down = true; 72 this.startX = evt.pageX; 73 this.startY = evt.pageY; 74 this.dragging = false; 75 this.eventInfo.el && this.eventInfo.onmouseDown && (this.eventInfo.onmouseDown({ 76 evt: evt, 77 target: this.eventInfo.el, 78 mouseX: this.startX - leftWidth, 79 mouseY: this.startY - topHeight - topAnimaitonHeight, 80 buttonCode: evt.button 81 })); 82 this.lastX = evt.pageX; 83 this.lastY = evt.pageY; 84 }; 85 mousemoveHandler = function (evt: MouseEvent) { 86 this.moveCount++; 87 this.x = evt.pageX; 88 this.y = evt.pageY; 89 if (this.down && (this.x - this.startX != 0 || this.y - this.startY != 0)) { 90 this.dragging = true; 91 } 92 if (this.dragging) { 93 this.eventInfo.ondragMove && this.eventInfo.ondragMove({ 94 evt: evt, 95 isFirstMove: this.moveCount == 1 ? true : false, 96 mouseX: this.x - leftWidth, 97 mouseY: this.y - topHeight - topAnimaitonHeight, 98 downX: this.startX - leftWidth, 99 downY: this.startY - topHeight - topAnimaitonHeight, 100 lastX: this.lastX - leftWidth, 101 lastY: this.lastY - topHeight - topAnimaitonHeight, 102 noRoteDiffX: this.x - this.lastX, 103 noRoteDiffY: this.y - this.lastY, 104 totalX: this.x - this.startX, 105 totalY: this.y - this.startY 106 }) 107 } else { 108 this.eventInfo.onmouseMove && this.eventInfo.onmouseMove({ 109 evt: evt, 110 mouseX: this.x - leftWidth, 111 mouseY: this.y - topHeight - topAnimaitonHeight, 112 downX: this.startX - leftWidth, 113 downY: this.startY - topHeight - topAnimaitonHeight, 114 lastX: this.lastX - leftWidth, 115 lastY: this.lastY - topHeight - topAnimaitonHeight, 116 noRoteDiffX: this.x - this.lastX, 117 noRoteDiffY: this.y - this.lastY, 118 totalX: this.x - this.startX, 119 totalY: this.y - this.startY 120 }) 121 } 122 this.lastX = evt.pageX; 123 this.lastY = evt.pageY; 124 };
如何使用上面我们创建的两个类呢
我们在使用的时候先将MouseEventInfo这个类初始化,然后再用MouseEventClass绑定事件。
this.mouseEventInfo = new Common.MouseEventInfo(document, this.mouseDown, this.dragMove, this.dragUp, this.mouseMove, this.mouseUp, this.mouseWheel, this.onContextMenu);
new Common.MouseEventClass(this.mouseEventInfo);
我们绑定事件的元素是document,操作软件的所有事件都会走我们绑定的以下函数:
当然最重要的操做画布的响应也依赖于我们的事件处理逻辑:
this.mouseDown:鼠标按下的事件处理逻辑,例如存储当前的鼠标值
this.dragMove:鼠标拖拽移动,例如移动某个元素或者移动画布
this.dragUp:鼠标松开(拖拽后松开鼠标),例如停止移动
this.mouseMove:鼠标移动(不是按住状态),例如让元素显示hover状态
this.mouseUp:鼠标松开(mousedown后马上松开),例如触发某个元素的编辑状态
this.mouseWheel:鼠标滚动,例如缩放画布
this.onContextMenu:鼠标点击右键,例如显示右键菜单