javascript – Canvas在移动网络上获得触摸位置

我有一个代码,它将(x,y)坐标中的一条线拖到新的鼠标(x,y)坐标上.这在桌面浏览器中运行良好,但由于某种原因,它在移动浏览器中不起作用.我添加了触摸事件监听器,但我想坐标是一些如何变得不正确.继承我的代码
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.

希望能帮助您完成代码.

相关文章

事件冒泡和事件捕获 起因:今天在封装一个bind函数的时候,发现el.addEventListener函数支持第三个参数...
js小数运算会出现精度问题 js number类型 JS 数字类型只有number类型,number类型相当于其他强类型语言...
什么是跨域 跨域 : 广义的跨域包含一下内容 : 1.资源跳转(链接跳转,重定向跳转,表单提交) 2.资源...
@ &quot;TOC&quot; 常见对base64的认知(不完全正确) 首先对base64常见的认知,也是须知的必须有...
搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : 的缩写,说都能直接说出来 :模型, :视图, :视图模...
首先我们需要一个html代码的框架如下: 我们的目的是实现ul中的内容进行横向的一点一点滚动。ul中的内容...