在Javascript中检测触摸板与鼠标

时间:2012-05-24 20:14:25

标签: javascript mouse touchpad trackpad

有没有办法检测客户端是否使用触摸板而不是使用Javascript鼠标?

或者至少要对使用触摸板而不是鼠标的用户数量进行一些合理估计?

9 个答案:

答案 0 :(得分:13)

这个主题可能已经解决,但答案是无法检测到它。我需要得到一个解决方案,这非常重要。所以我找到了一个可接受的解决方案来解决这个问题:

var scrolling = false;
var oldTime = 0;
var newTime = 0;
var isTouchPad;
var eventCount = 0;
var eventCountStart;

var mouseHandle = function (evt) {
    var isTouchPadDefined = isTouchPad || typeof isTouchPad !== "undefined";
    console.log(isTouchPadDefined);
    if (!isTouchPadDefined) {
        if (eventCount === 0) {
            eventCountStart = new Date().getTime();
        }

        eventCount++;

        if (new Date().getTime() - eventCountStart > 100) {
                if (eventCount > 10) {
                    isTouchPad = true;
                } else {
                    isTouchPad = false;
                }
            isTouchPadDefined = true;
        }
    }

    if (isTouchPadDefined) {
        // here you can do what you want
        // i just wanted the direction, for swiping, so i have to prevent
        // the multiple event calls to trigger multiple unwanted actions (trackpad)
        if (!evt) evt = event;
        var direction = (evt.detail<0 || evt.wheelDelta>0) ? 1 : -1;

        if (isTouchPad) {
            newTime = new Date().getTime();

            if (!scrolling && newTime-oldTime > 550 ) {
                scrolling = true;
                if (direction < 0) {
                    // swipe down
                } else {
                    // swipe up
                }
                setTimeout(function() {oldTime = new Date().getTime();scrolling = false}, 500);
            }
        } else {
            if (direction < 0) {
                // swipe down
            } else {
                // swipe up
            }
        }
    }
}

注册活动:

document.addEventListener("mousewheel", mouseHandle, false);
document.addEventListener("DOMMouseScroll", mouseHandle, false);

它可能需要一些优化,可能不完美,但它的工作原理!至少它可以检测到macbook触控板。但由于设计的原因,我认为它应该适用于pad引入大量事件调用的任何地方。

以下是它的工作原理:

当用户首次滚动时,它将检测并检查在50ms内触发的事件不超过5个,这对于普通鼠标来说是非常不寻常的,但对于触控板则不是。

然后是else部分,这对于检测并不重要,而是一次调用函数的技巧,就像用户滑动时一样。如果我不够清楚的话,请来找我,让这个工作变得非常棘手,当然不是理想的解决方法。

编辑:我尽可能地优化了代码。它第二次检测到mouseroll并立即在触控板上滑动。删除了很多重复和不必要的代码。

编辑2 我将时间检查的数字和调用的事件数分别从50更改为100和5到10。这应该可以产生更准确的检测。

答案 1 :(得分:7)

您可以检测JS事件。

除鼠标事件外,触控设备还会触发touchstart等触摸事件。

非触控设备只会触发鼠标事件。

答案 2 :(得分:4)

在一般情况下,没有办法做你想要的。 ActiveX 可能允许您查看和检查USB设备,但在最好的情况下,即使这在某种程度上可能,也会限制您使用IE用户。除此之外,没有办法知道。

您可能能够辨别触摸板用户移动光标的方式(或频率)与鼠标用户移动光标的方式。以这种方式区分物理输入设备是一个非常困难的前景,并且可能完全不可能,所以我在此仅包括完整性。

答案 3 :(得分:2)

劳里(Lauri)的上述答案似乎行得通,但是我花了一些时间来理解为什么。因此,在这里,我将提供一个稍微易读的版本以及概念上的解释。首先,以人类可读的方式写出相同的代码:

function detectTrackPad(e) {
  var isTrackpad = false;
  if (e.wheelDeltaY) {
    if (e.wheelDeltaY === (e.deltaY * -3)) {
      isTrackpad = true;
    }
  }
  else if (e.deltaMode === 0) {
    isTrackpad = true;
  }
  console.log(isTrackpad ? "Trackpad detected" : "Mousewheel detected");
}

document.addEventListener("mousewheel", detectTrackPad, false);
document.addEventListener("DOMMouseScroll", detectTrackPad, false);

之所以可行,是因为wheelDeltaY会测量实际硬件鼠标滚轮行进的物理距离,而deltaY会测量屏幕上产生的滚动量。常规鼠标的“滚动分辨率”通常比触控板低得多。也就是说,使用触控板您可以进行微小的动作并在屏幕上获得微小的滚动。传统鼠标滚动时会出现块状,低分辨率的点击。要完成鼠标滚轮的完整旋转,可能需要单击10次。没有单击或四分之一的点击。

对于传统鼠标,单次滚轮单击报告为120 wheelDeltaY“单位”,并导致〜100px的滚动值。实际的wheelDeltaY单位是一个完全任意的数字,它不测量英寸或度或类似的数字。已选择数字120 simply because it has a lot of useful factors。屏幕上的滚动量由deltaY表示,varies significantly by browser。 (旁注,deltaY通常是用“线”而不是像素来度量的,尽管它很复杂,请参见上一链接)。

mouse cutaway

与触控板进行交互在两个方面有所不同。首先,可以检测到wheelDeltaY值远小于120,因为可以检测到非常细微的手指手势。其次,wheelDeltaY正好是deltaY值的3倍(至少在我设法测试的每个浏览器中)。因此,例如,如果您做出等于12个单击单位的物理手指手势,则通常会导致滚动4个像素。劳里(Lauri)的代码使用第二个属性(Y1 = Y2 * 3)检测触控板的存在,但是您也可以通过检查abs(wheelDeltaY)是否等于120来成功实现

我还没有测试过,但是我认为它也可以工作:

function detectTrackPad(e) {
  var isTrackpad = false;
  if (e.wheelDeltaY) {
    if (Math.abs(e.wheelDeltaY) !== 120) {
      isTrackpad = true;
    }
  }
  else if (e.deltaMode === 0) {
    isTrackpad = true;
  }
  console.log(isTrackpad ? "Trackpad detected" : "Mousewheel detected");
}

document.addEventListener("mousewheel", detectTrackPad, false);
document.addEventListener("DOMMouseScroll", detectTrackPad, false);

答案 4 :(得分:1)

另一种选择是在Firefox中比较e.wheelDeltaY和e.deltaY或e.deltaMode

function handler(e) {
    var isTouchPad = e.wheelDeltaY ? e.wheelDeltaY === -3 * e.deltaY : e.deltaMode === 0
    // your code
    document.body.textContent = isTouchPad ? "isTouchPad" : "isMouse"
}
document.addEventListener("mousewheel", handler, false);
document.addEventListener("DOMMouseScroll", handler, false);

答案 5 :(得分:0)

您可以检查安装在本地软件包中的设备驱动程序软件是否正常运行。就像在windows synaptics,elan硬件中一样,对于UNIX(Linux),你可以检查安装在基本安装过程中安装的软件包。许多软件包在不同版本的Linux和Linux系统中都有不同的格式(完全不是linux),但它们对所有软件包使用相同的软件包名称。刚知道拉动它的代码。仍在努力。

答案 6 :(得分:0)

由触摸板触发的车轮事件将产生较小的事件。deltaY,1或2,但由鼠标滚轮触发的事件将产生100,200。

答案 7 :(得分:0)

从测试插入鼠标到具有触摸板以及带有Windows的Windows机器的Mac上,我可以总结一下如何工作。

  1. 检测导航器用户代理是否包含“ Mobile”或“ Mac OS”(如果有) 这些是正确的,它很可能是基于触摸的系统,但可以 消除那个。将boolean hasTouchPad设置为true

  2. 如果以上情况为真,请检测“鼠标”事件并运行高电平测试     数字或非整数频率或卡尔曼滤波。

  3. 将这些保留在队列中,如果该队列的总和超过阈值,     禁用hasTouchpad变量并断开事件连接。

let isMouseCounts: Array<number> = []

if (Client.hasTouchpad) {
    document.addEventListener('wheel', detectMouseType);
}

function detectMouseType(e:WheelEvent) {
    if (!Client.hasTouchpad) return

    let isMouse = e.deltaX === 0 && !Number.isInteger(e.deltaY)

    isMouseCounts.push(isMouse ? 1 : 0)
    if (isMouseCounts.length > 5) isMouseCounts.shift()

    let sum = isMouseCounts.reduce(function(a, b) { return a + b; });

    if (sum > 3 && e.type === "wheel") {
        console.log("Touchpad disabled")
        document.removeEventListener('wheel', detectMouseType);
        Client.hasTouchpad = false;
    }
}

答案 8 :(得分:-3)

这应该有效:

if ("ontouchstart" in window) ...