有没有办法检测客户端是否使用触摸板而不是使用Javascript鼠标?
或者至少要对使用触摸板而不是鼠标的用户数量进行一些合理估计?
答案 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通常是用“线”而不是像素来度量的,尽管它很复杂,请参见上一链接)。
与触控板进行交互在两个方面有所不同。首先,可以检测到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上,我可以总结一下如何工作。
检测导航器用户代理是否包含“ Mobile”或“ Mac OS”(如果有) 这些是正确的,它很可能是基于触摸的系统,但可以 消除那个。将boolean hasTouchPad设置为true
如果以上情况为真,请检测“鼠标”事件并运行高电平测试 数字或非整数频率或卡尔曼滤波。
将这些保留在队列中,如果该队列的总和超过阈值, 禁用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) ...