function getMouse(e) { var element = canvas,offsetX = 0,offsetY = 0; if (element.offsetParent) { do { offsetX += element.offsetLeft; offsetY += element.offsetTop; } while ((element = element.offsetParent)); } mx = (e.pageX - offsetX) - LINE_WIDTH; my =( e.pageY - offsetY )- LINE_WIDTH; } function mouseDown(e){ getMouse(e); clear(fctx); var l = lines.length; for (var i = l-1; i >= 0; i--) { draw(fctx,lines[i]); var imageData = fctx.getImageData(mx,my,1,1); if (imageData.data[3] > 0) { selectedObject = lines[i]; isDrag = true; canvas.onmousemove = drag; clear(fctx); } } } function mouseUp(){ isDrag = false; } canvas.onmousedown = mouseDown; canvas.onmouseup = mouseUp; canvas.addEventListener('touchstart',mouseDown,false); canvas.addEventListener('touchend',mouseUp,false);
你可以在这里看到工作部分:http://codepen.io/nirajmchauhan/pen/yYdMJR
解决方法
好的,在这里看到这个问题已经有一段时间了,没有人会提出一个答案我会给你一个.
与鼠标事件不同,触摸事件涉及与UI的许多接触点.为了适应这种情况,触摸事件提供了一系列接触点.由于鼠标不能同时在两个地方,因此应该分别处理两种交互方法以获得最佳用户体验. OP因为您没有询问有关检测设备是触摸还是鼠标驱动的问题,我已将其留给另一个人询问.
处理两者
鼠标和触摸事件可以共存.在没有一个或另一个的设备上添加鼠标或触摸事件的侦听器不是问题.缺少的输入接口根本不会生成任何事件.这样可以轻松实现页面的透明解决方案.
它取决于您喜欢哪个接口,并在其硬件不可用时模拟该接口.在这种情况下,我将从创建的任何触摸事件中模拟鼠标.
以编程方式创建事件.
该代码使用MouseEvent对象来创建和分派事件.它使用简单,事件与真正的鼠标事件无法区分.有关MouseEvents goto MDN MouseEvent的详细说明
最基本的.
创建鼠标单击事件并将其分派给文档
var event = new MouseEvent( "click",{'view': window,'bubbles': true,'cancelable': true}); document.dispatchEvent(event);
您还可以将事件分派给各个元素.
document.getElementById("someButton").dispatchEvent(event);
收听事件就像听实际的鼠标一样.
document.getElementById("someButton").addEventListener(function(event){ // your code ));
MouseEvent函数中的第二个参数是您可以添加有关该事件的额外信息的位置.比如说clientX和clientY,例如鼠标的位置,或按下按钮的按钮.
如果你曾经看过mouseEvent,你就会知道有很多属性.因此,您在鼠标事件中发送的内容将取决于您的事件侦听器正在使用的内容.
触摸事件.
触摸事件与鼠标类似.有touchstart,touchmove和touchend.它们的不同之处在于它们提供了一系列位置,每个接触点都有一个项目.不确定最大值是什么,但对于这个答案我们只对一个感兴趣.有关详细信息,请参阅MDN touchEvent.
我们需要做的是触摸事件只涉及一个我们想要在同一位置生成相应鼠标事件的接触点.如果触摸事件返回多个联系点,我们无法知道他们的目标焦点在哪,所以我们将忽略它们.
function touchEventHandler(event){ if (event.touches.length > 1){ // Ignor multi touch events return; } }
所以现在我们知道触摸单个联系人我们可以根据触摸事件中的信息创建鼠标事件.
最基本的
touch = event.changedTouches[0]; // get the position information if(type === "touchmove"){ mouseEventType = "mousemove"; // get the name of the mouse event // this touch will emulate }else if(type === "touchstart"){ mouseEventType = "mousedown"; // mouse event to create }else if(type === "touchend"){ mouseEventType = "mouseup"; // ignore mouse up if click only } var mouseEvent = new MouseEvent( // create event mouseEventType,// type of event { 'view': event.target.ownerDocument.defaultView,'cancelable': true,'screenX':touch.screenX,// get the touch coords 'screenY':touch.screenY,// and add them to the 'clientX':touch.clientX,// mouse event 'clientY':touch.clientY,}); // send it to the same target as the touch event contact point. touch.target.dispatchEvent(mouseEvent);
现在,当用户仅在一个位置触摸设备时,您的鼠标侦听器将接收mousedown,mousemove和mouseup事件.
缺少点击
到目前为止一切都很好但是缺少一个鼠标事件,这也是必需的. “onClick”我不确定是否存在等效的触摸事件,并且正如我所看到的那样,我们必须决定是否可以将一组触摸事件视为点击.
这将取决于开始和结束触摸事件的距离,超过几个像素和它的拖动.它还取决于多长时间. (虽然与鼠标不同)我发现人们倾向于点击,而鼠标可以被保持,代替释放上的构造,或者拖走取消,这不是人们使用触摸界面的方式.
所以我记录了touchStart事件发生的时间. event.timeStamp及其开始的位置.然后在touchEnd事件中,我找到它移动的距离和时间.如果它们都在我设置的限制之下,我还会生成鼠标单击事件以及鼠标按下事件.
这是将触摸事件转换为鼠标事件的基本方法.
一些CODE
下面是一个名为mouseTouch的微型API,它完成了我刚刚解释过的内容.它涵盖了简单绘图应用程序中所需的最基本的鼠标交互.
// _______ _ // |__ __| | | // _ __ ___ ___ _ _ ___ ___| | ___ _ _ ___| |__ // | '_ ` _ \ / _ \| | | / __|/ _ \ |/ _ \| | | |/ __| '_ \ // | | | | | | (_) | |_| \__ \ __/ | (_) | |_| | (__| | | | // |_| |_| |_|\___/ \__,_|___/\___|_|\___/ \__,_|\___|_| |_| // // // Demonstration of a simple mouse emulation API using touch events. // Using touch to simulate a mouse. // Keeping it clean with touchMouse the only pubic reference. // See Usage instructions at bottom. var touchMouse = (function(){ "use strict"; var timeStart,touchStart,mouseTouch,listeningElement,hypot; mouseTouch = {}; // the public object // public properties. mouseTouch.clickRadius = 3; // if touch start and end within 3 pixels then may be a click mouseTouch.clickTime = 200; // if touch start and end in under this time in ms then may be a click mouseTouch.generateClick = true; // if true simulates onClick event // if false only generate mousedown,mousemove,and mouseup mouseTouch.clickOnly = false; // if true on generate click events mouseTouch.status = "Started."; // just for debugging // ES6 new math function // not sure the extent of support for Math.hypot so hav simple poly fill if(typeof Math.hypot === 'function'){ hypot = Math.hypot; }else{ hypot = function(x,y){ // Untested return Math.sqrt(Math.pow(x,2)+Math.pow(y,2)); }; } // Use the new API and MouseEvent object function triggerMouseEvemt(type,fromTouch,fromEvent){ var mouseEvent = new MouseEvent( type,{ 'view': fromEvent.target.ownerDocument.defaultView,'screenX':fromTouch.screenX,'screenY':fromTouch.screenY,'clientX':fromTouch.clientX,'clientY':fromTouch.clientY,'offsetX':fromTouch.clientX,// this is for old Chrome 'offsetY':fromTouch.clientY,'ctrlKey':fromEvent.ctrlKey,'altKey':fromEvent.altKey,'shiftKey':fromEvent.shiftKey,'MetaKey':fromEvent.MetaKey,'button':0,'buttons':1,}); // to do. // dispatch returns cancelled you will have to // add code here if needed fromTouch.target.dispatchEvent(mouseEvent); } // touch listener. Listens to Touch start,move and end. // dispatches mouse events as needed. Also sends a click event // if click falls within supplied thresholds and conditions function emulateMouse(event) { var type,time,touch,isClick,mouseEventType,x,y,dx,dy,dist; event.preventDefault(); // stop any default happenings interfering type = event.type ; // the type. // ignore multi touch input if (event.touches.length > 1){ if(touchStart !== undefined){ // don't leave the mouse down triggerMouseEvent("mouseup",event.changedTouches[0],event); } touchStart = undefined; return; } mouseEventType = ""; isClick = false; // default no click // check for each event type I have the most numorus move event first,Good practice to always think about the efficancy for conditional coding. if(type === "touchmove" && !mouseTouch.clickOnly){ // touchMove touch = event.changedTouches[0]; mouseEventType = "mousemove"; // not much to do just move the mouse }else if(type === "touchstart"){ touch = touchStart = event.changedTouches[0]; // save the touch start for dist check timeStart = event.timeStamp; // save the start time mouseEventType = !mouseTouch.clickOnly?"mousedown":""; // mouse event to create }else if(type === "touchend"){ // end check time and distance touch = event.changedTouches[0]; mouseEventType = !mouseTouch.clickOnly?"mouseup":""; // ignore mouse up if click only // if click generator active if(touchStart !== undefined && mouseTouch.generateClick){ time = event.timeStamp - timeStart; // how long since touch start // if time is right if(time < mouseTouch.clickTime){ // get the distance from the start touch dx = touchStart.clientX-touch.clientX; dy = touchStart.clientY-touch.clientY; dist = hypot(dx,dy); if(dist < mouseTouch.clickRadius){ isClick = true; } } } } // send mouse basic events if any if(mouseEventType !== ""){ // send the event triggerMouseEvent(mouseEventType,event); } // if a click also generates a mouse click event if(isClick){ // generate mouse click triggerMouseEvent("click",event); } } // remove events function removeTouchEvents(){ listeningElement.removeEventListener("touchstart",emulateMouse); listeningElement.removeEventListener("touchend",emulateMouse); listeningElement.removeEventListener("touchmove",emulateMouse); listeningElement = undefined; } // start adds listeners and makes it all happen. // element is optional and will default to document. // or will Listen to element. function startTouchEvents(element){ if(listeningElement !== undefined){ // untested // throws to stop cut and past useage of this example code. // Overwriting the listeningElement can result in a memory leak. // You can remove this condition block and it will work // BUT IT IS NOT RECOGMENDED throw new ReferanceError("touchMouse says!!!! API limits functionality to one element."); } if(element === undefined){ element = document; } listeningElement = element; listeningElement.addEventListener("touchstart",emulateMouse); listeningElement.addEventListener("touchend",emulateMouse); listeningElement.addEventListener("touchmove",emulateMouse); } // add the start event to public object. mouseTouch.start = startTouchEvents; // stops event listeners and remove them from the DOM mouseTouch.stop = removeTouchEvents; return mouseTouch; })(); // How to use touchMouse.start(); // done using defaults will emulate mouse on the entier page // For one element and only clicks // HTML <input value="touch click me" id="touchButton" type="button"></input> // Script var el = document.getElementById("touchButton"); if(el !== null){ touchMouse.clickOnly = true; touchMouse.start(el); } // For drawing on a canvas <canvas id="touchCanvas"></canvas> // script var el = document.getElementById("touchButton"); if(el !== null){ touchMouse.generateClick = false; // no mouse clicks please touchMouse.start(el); } // For switching elements call stop then call start on the new element // warning touchMouse retained a reference to the element you // pass it with start. Dereferencing touchMouse will not delete it. // Once you have called start you must call stop in order to delete it. // API //--------------------------------------------------------------- // To dereference call the stop method if you have called start . Then dereference touchMouse // Example touchMouse.stop(); touchMouse = undefined; // Methods. //--------------------------------------------------------------- // touchMouse.start(element); // element optional. Element is the element to attach listeners to. // Calling start a second time without calling stop will // throw a reference error. This is to stop memory leaks. // YOU Have been warned... // touchMouse.stop(); // removes listeners and dereferences any DOM objects held //--------------------------------------------------------------- // Properties // mouseTouch.clickRadius = 3; // Number. Default 3. If touch start and end within 3 pixels then may be a click // mouseTouch.clickTime = 200; // Number. Default 200. If touch start and end in under this time in ms then may be a click // mouseTouch.generateClick; // Boolean. Default true. If true simulates onClick event // // if false only generate mousedown,and mouseup // mouseTouch.clickOnly; // Boolean. Default false. If true only generate click events Default false // mouseTouch.status; // String. Just for debugging kinda pointless really.
希望能帮助您完成代码.