1

I'm working on a page where I have a draggable item (a map inside a container). When you click and drag with the mouse, the map moves and everything is fine. I then wanted to add the same functionality for touch devices (such as a smartphone or a tablet). I searched the net and found a working script that "changes" touch input to mouseinput and thus making it possible to drag the map without dragging the entire page (which is standard behaviour). This is done using the line

event.preventDefault() 

It is even possible to have click events as well by timing how long apart the touches are. I am no coding genius and all this programming was done by others. You can see the discussion at Javascript Drag and drop for touch devices (I have used the original code in the top answer as well as the timing code in the answer just below the top answer).

So far, so good. It is now possible to drag the map around and click any links on it or the page just as you would, if you were using a mouse. This works on all touch browsers I have tried (I haven't tried a lot, but the ones I've tried work). The only problem is, that you cannot drag the page itself around, since the default behaviour of the touch has been disabled. This is a problem when the content of the page (for instance the size of the map container) is larger than the browser window.

Luckily an answer was provided for this as well (it is the bottom-most answer on the page I linked to above): replacing

event.preventDefault()

with

if (touches.length > 1) event.preventDefault();

the default scrolling/resizing etc. of a touch works if you use one finger, but if you use more than one finger, the default behaviour is prevented. In other words: If you use two fingers, you can drag the map around without dragging the page (just as before), but if you use one finger, you can drag the page around! I really like this solution as it seems quite elegant to me.

Well, I added the line and tested on the default browser on my HTC Incredible phone (way to small screen but it is what I have). The default browser is just called "Internet". Everything works perfectly! So, I test on Firefox and Opera, and unfortunately, they are not working perfectly. It seems that once the

event.preventDefault()

is inside the "if" statement, it is completely ignored, so when I drag the map, it IS dragged (as the touch is still converted to a drag of the mouse), but the page itself is also dragged, regardless of the number of fingers I use. In short: The page behaves as if no

event.preventDefault()

is triggered.

I have looked around for several hours and have come to suspect that the event variable needs to be initialized or imported for Firefox and Opera to be able to use it, as described here: jQuery event.preventDefault() not working in Firefox (JSFiddle included)

My question (at long last): Could this be right, and how do I go about "importing" the event into the "if" statement?

The code is here (the init() function is triggered by body onload)

    <script type="text/javascript">
    
    var clickms = 400;
    var lastTouchDown = -1;
    
    function touchHandler(event)
    {
    
    var touches = event.changedTouches,
    first = touches[0],
    type = "";
    
    var d = new Date();
    switch(event.type)
    {
    case "touchstart": type = "mousedown"; lastTouchDown = d.getTime(); break;
    case "touchmove": type="mousemove"; lastTouchDown = -1; break;        
    case "touchend": if(lastTouchDown > -1 && (d.getTime() - lastTouchDown) < clickms){lastTouchDown = -1; type="click"; break;} type="mouseup"; break;
    default: return;
    }
    
    var simulatedEvent = document.createEvent("MouseEvent");
    simulatedEvent.initMouseEvent(type, true, true, window, 1,
                      first.screenX, first.screenY,
                      first.clientX, first.clientY, false,
                      false, false, false, 0/*left*/, null);
    
    first.target.dispatchEvent(simulatedEvent);
    if (touches.length > 1)
    {
    event.preventDefault();
    }
    
    }
    
    function init()
    {
    document.addEventListener("touchstart", touchHandler, true);
    document.addEventListener("touchmove", touchHandler, true);
    document.addEventListener("touchend", touchHandler, true);
    document.addEventListener("touchcancel", touchHandler, true);    
    }
    
    </script> 

Edit: I should add that I have tried inserting an alert statement into the if statement, just to see whether Firefox or Opera actually register that a two-finger gesture is performed. The alert is triggered without problems, so perhaps the problem is that once Firefox or Opera has started a two-finger gesture, the standard behaviour of the gesture (draggring or resizing the page) cannot be stopped, at least not in this way.

4

1 回答 1

0

我似乎已经解决了这个问题(至少在我可供测试的浏览器上)

我所做的是改变

    if (touches.length > 1) {
      event.preventDefault();
    }

    if (event.touches.length > 1) {
      event.preventDefault();
    }

现在可以使用两根手指拖动可拖动元素,而无需移动页面的其余部分。在 Firefox 和 Opera 上仍然可以用一根手指拖动地图,但这是小事,只要您采取“要拖动时只用两根手指”的态度。

唯一的小问题是 Firefox 和 Opera 似乎在他们选择关注的指尖之间来回跳跃,使得可拖动元素有些抖动,尤其是当手指有点分开时。此行为不会显示在“Internet”浏览器中。

于 2012-09-27T10:27:26.110 回答