统一触控和鼠标:指针事件如何使 跨浏览器 触摸支持容易

分享于 

27分钟阅读

Web开发

  繁體 雙語

在10天内开发 Windows 8应用程序。

在手机和平板电脑上,我经常会遇到这样的问题:在手机和平板电脑上使用如此多的触摸设备? "还有"什么是构建触摸输入最简单的方法? 但是,在现代的浏览器中,它肯定是一种更加统一的方式来处理多触摸输入,在现代的触摸屏浏览器或者旧浏览器的回退 as。 in i using MSPointers,这是一种新兴的多触摸技术和 polyfills,使 跨浏览器 支持变得更加复杂,并减少了复杂的代码。 你还可以在自己的站点上使用并轻松使用的代码类型。

在web上,你需要查看 iOS touch事件模型和 MSPointers鼠标事件模型,以支持所有浏览器的事件模型,以支持所有浏览器。 然而,( 和愿意) 正逐渐支持标准化。 in,微软向W3C提交了标准化标准,昨天,我们已经到达了最后的调用草案: 女士Open团队最近还发布了一个初始指针事件 Prototype,用于 webkit

i MSPointers实验的原因不是基于设备共享- 因为微软的基本输入处理方式与目前在网络上 available handling,它应该有 look look。 这种区别在于开发者可以写更抽象的形式,叫做"指针。"指针,鼠标指针。笔。手指或者多个手指在屏幕上的任何接触。 所以你不需要为每一种输入分别浪费时间。

这些概念

我们首先回顾运行 inside IE 10的应用程序,它公开了MSPointer事件 API,然后解决了所有浏览器的解决方案。 之后,我们将了解如何利用IE10手势服务,帮助你以简单的方式处理JavaScript代码中的触摸。 由于 Windows 8和 Windows Phone 8共享相同的浏览器引擎,代码&概念与两个平台相同。 在本篇文章中,我们将学习的一切都将帮助你在使用 html5/js构建的应用程序中完成同样的任务,因为这同样是使用的同样的引擎。

MSPointer背后的思想是让你用一个与你已经知道的鼠标事件匹配的Pattern 来处理鼠标。笔&触摸设备,从而通过一个。 实际上,鼠标,笔 & touch有一些共同的特性: 可以移动指针,也可以在元素上单击,例如。 让我们通过同样的代码来解决这些场景 ! 指针将聚合这些公共属性,并以类似于鼠标事件的方式公开它们。

最明显的常见事件是: MSPointerDownMSPointerMove &MSPointerUp,它直接映射到鼠标事件等效的。 你将屏幕的X & Y 坐标作为输出。

你还具有以下特定事件: MSPointerOverMSPointerOut,MSPointerHover或者MSPointerCancel"

当然,也可以能有一些情况,你希望以不同的方式处理触摸,而不是默认的鼠标行为。 另外,由于多触摸屏,你可以轻松地让用户旋转,缩放或者平移一些元素。 笔/笔甚至可以给你一些压力信息,鼠标不能。 指针事件仍将聚合这些差异,并允许你为每个设备的具体细节生成一些自定义代码。

注意:如果你在 Windows 8/RT 设备上有触摸屏,或者使用 Windows Phone 8,那么最好测试下面的嵌入样本。 不过,你仍然可以有一些选择:

处理简单触控事件

步骤 1: 在JS中不做任何事情,而是添加一行 CSS

让我们从基础知识开始。 你可以轻松地采取任何现有的JavaScript代码来处理鼠标事件,它只是使用 IE 10中的一些笔或者触摸设备。 如果你不在代码中处理指针事件,IE10实际上是在将鼠标事件作为最后的。 所以即使开发者从来没有想过这样做,你也可以用手指或者任何网页上任何网页上的任何元素来做这个。 因此任何注册到mouvedown和/或者mouseup事件的代码都将在根本没有修改。 但是 mouvemove?

让我们回顾默认的行为来回答这个问题。 例如让我们使用下面的代码:

<!DOCTYPEhtml><html><head><title>Touch article sample 1</title></head><body><canvasid="drawSurface"width="400px"height="400px"style="border: 1px dashed black;"></canvas><script>var canvas = document.getElementById("drawSurface");
 var context = canvas.getContext("2d");
 context.fillStyle = "rgba(0, 0, 255, 0.5)";
 canvas.addEventListener("mousemove", paint, false);
 function paint(event) {
 context.fillRect(event.clientX, event.clientY, 10, 10);
 }
 </script></body></html>

它只是通过跟踪鼠标的移动来绘制一些蓝色的10px 到 10px 平方 inside的HTML5 Canvas 元素。

在移动鼠标 inside的画布元素时,它将会绘制一些蓝色方块。 但是使用触摸,它只会在你点击画布元素的位置绘制一个唯一的正方形。 当你尝试将手指移动到画布元素中时,浏览器将尝试平移 inside 页面,因为它是默认行为。

然后需要指定你希望重写浏览器的默认行为,并告诉它将触摸事件重定向到JavaScript代码。 为这里,将页面的元素目标化为默认行为并将这里CSS规则应用于它们:

-ms-touch-action: auto | none | manipulation | double-tap-zoom | inherit;

根据你想要筛选的内容,有多种可用的值。 你将找到本文中描述的值: 构建触摸友好站点的指南

典型的用例是当你在页面中有一个地图控件时。 你希望使用户平移&缩放 inside 映射区域,但保留页面它的余部分的默认行为。 在本例中,你将应用这个CSS规则( -ms-touch-action: 操作) 只在公开映射的HTML容器上。

在我们的例子中,添加这个 block的:

<style> #drawSurface {
 -ms-touch-action: none;/* Disable touch behaviors, like pan and zoom */ }</style>

现在,当你移动手指 inside的画布元素时,它的行为像鼠标指针。 很酷但是你很快会问自己这个问题: ! 为什么这个代码只跟踪 1个手指? 这是因为我们只是在IE10做的最后一件事情中提供了一个非常基本的触摸体验: 将手指映射到模拟鼠标。 我知道我们每次只用 1个鼠标。 因此 1鼠标 == 1手指最大使用这里方法。 那么,如何处理多个触摸事件?

步骤 2: 使用MSPointer事件而不是鼠标事件

使用现有的代码,用"MSPointerDown/Up/Move" 替换注册到"mousedown/up/move",代码将直接支持多触摸体验 inside IE10. !

例如在前面的示例中,更改这一行代码:

canvas.addEventListener("mousemove", paint, false);

对这个:

canvas.addEventListener("MSPointerMove", paint, false);

你现在可以画出你的屏幕所支持的方块数 ! 更好的是,同样的代码适用于触摸,鼠标&笔。 这意味着你可以用鼠标来绘制一些线,同时用手指绘制它的他线条。

如果要根据输入类型更改代码的行为,可以通过 pointerType 属性值测试。 比如,让我们想象一下,我们想绘制一些 10px的红正方形,5px 为pen绿色正方形,2px 为 2px 蓝色方块,鼠标为 for。 你需要用下面的方法替换前一个处理程序( 油漆功能):

function paint(event) {
 if (event.pointerType) {
 switch (event.pointerType) {
 caseevent.MSPOINTER_TYPE_TOUCH:
 // A touchscreen was used// Drawing in red with a square of 10 context.fillStyle = "rgba(255, 0, 0, 0.5)";
 squaresize = 10;
 break;
 caseevent.MSPOINTER_TYPE_PEN:
 // A pen was used// Drawing in green with a square of 5 context.fillStyle = "rgba(0, 255, 0, 0.5)";
 squaresize = 5;
 break;
 caseevent.MSPOINTER_TYPE_MOUSE:
 // A mouse was used// Drawing in blue with a squre of 2 context.fillStyle = "rgba(0, 0, 255, 0.5)";
 squaresize = 2;
 break;
 }
 context.fillRect(event.clientX, event.clientY, squaresize, squaresize);
 }
}

幸运的是,如果有足够的设备支持 3种输入类型,就可以根据输入类型查看种图形。 很好,不是?

但是,这里代码仍然存在问题。 现在在IE10中正确处理所有输入,但对于不支持MSPointer事件( 如 IE9.Chrome。Firefox。Opera & Safari )的浏览器来说,它根本就不工作。

步骤 3: 进行特征检测以提供回退代码

你可能已经知道,处理多浏览器支持的最佳方法是进行特性检测。 在我们的示例中,你需要测试:

window.navigator.msPointerEnabled

注意,这只会告诉你当前浏览器是否支持 MSPointer。 它不会告诉你是否支持触摸。 要测试触摸的支持,你需要检查 msMaxTouchPoints。

总之,要在IE10中支持MSPointer并在其他浏览器中正常回退到鼠标事件,你需要这样的代码:

var canvas = document.getElementById("drawSurface");var context = canvas.getContext("2d");
context.fillStyle = "rgba(0, 0, 255, 0.5)";if (window.navigator.msPointerEnabled) {
 // Pointer events are supported. canvas.addEventListener("MSPointerMove", paint, false);
}else {
 canvas.addEventListener("mousemove", paint, false);
}
function paint(event) {
 // Default behavior for mouse on non-IE10 devicesvar squaresize = 2;
 context.fillStyle = "rgba(0, 0, 255, 0.5)";
 // Check for pointer type on IE10if (event.pointerType) {
 switch (event.pointerType) {
 caseevent.MSPOINTER_TYPE_TOUCH:
 // A touchscreen was used// Drawing in red with a square of 10 context.fillStyle = "rgba(255, 0, 0, 0.5)";
 squaresize = 10;
 break;
 caseevent.MSPOINTER_TYPE_PEN:
 // A pen was used// Drawing in green with a square of 5 context.fillStyle = "rgba(0, 255, 0, 0.5)";
 squaresize = 5;
 break;
 caseevent.MSPOINTER_TYPE_MOUSE:
 // A mouse was used// Drawing in blue with a square of 2 context.fillStyle = "rgba(0, 0, 255, 0.5)";
 squaresize = 2;
 break;
 }
 }
 context.fillRect(event.clientX, event.clientY, squaresize, squaresize);
}

步骤 4: 支持所有触控实现

如果你希望更进一步地支持所有浏览器&的所有触摸实现,你有 2种选择:

就像我在介绍本文中提到的,微软最近将事件规范提交给 W3C,用于标准化。 W3C创建了一个新工作组,并且它已经根据微软的建议发布了最后一次工作草案( Working )。 MS技术团队最近还发布了的初始指针事件 Prototype,你可能希望对。

尽管指针事件规范还不是标准,但是仍然可以实现支持它利用 david的代码,并且在所有现代浏览器的标准实现中都可以使用它。 使用david库将事件传播到IE10上的MSPointer,以便在基于 webkit的浏览器和 finally 上触摸事件。 这很酷看看他的文章发现和理解它是如何工作的。 注意,这个polyfill也将非常有用,支持旧的浏览器,以优雅的回退鼠标事件。

要了解如何使用这里库,请查看本文: 为你创建一个通用的虚拟触控游戏杆,适用于所有的触摸模型,这将向你展示如何使用指针事件编写一个虚拟触摸游戏游戏。 由于 HandJS,它将在 Windows 8/RT, Windows Phone 8,ipad/iphone & Android设备上使用相同代码库的IE10. !

识别简单手势

现在我们已经看到了如何处理多触摸,让我们看看如何识别简单的手势。

IE10提供了一个MSGesture对象,它将帮助我们。 注意,这个对象目前特定于 IE10,而不是W3C提交的一部分。 将元素( 我们的等价于WebKitCSSMatrix ) 结合起来,你将看到你可以非常简单的方式创建非常有趣的多触摸体验。 MSCSSMatrix实际上表示 4 ×4同构矩阵,它允许文档对象模型( DOM ) 脚本访问 CSS 2-D 和 3-D 转换功能。 但在玩这个之前先从基本的开始。

基本概念是将一个事件处理程序。 然后处理处理程序,你需要为你希望发送到MSGesture对象的指针选择1 ,让它检测到特定的手势。 然后它将触发其中一个事件: /, MSGestureStart, MSGestureChange, MSGestureEnd, MSInertiaStart。 然后MSGesture对象将所有提交的指针作为输入参数,并在它们上面应用一个手势识别器,以提供一些格式化数据作为输出。 你需要做的唯一事情是选择/过滤哪些指针,你希望成为笔势( 根据他们的身份证,屏幕上的坐标,不管什么。)的一部分。 这个MSGesture对象将为你完成所有的魔术。

示例 1: 处理保持手势

我们将看到如何保存元素( 一个包含图像作为背景的简单 DIV )。 一旦元素将被保存,我们将添加一些角度来指向他当前选择这个元素的用户。 通过动态创建在图像的每个角落添加 4个div来生成角。 finally,一些CSS技巧将使用变换和线性渐变来获得类似这样的东西:

image

序列将如下所示:

  • - register 到 MSPointerDown & MSPointerHold events你所感兴趣的HTML元素上的事件
  • 创建一个MSGesture对象,该对象将针对这个非常相同的HTML元素
  • 在MSPointerDown处理程序中,添加到MSGesture对象,你希望监视的各种 PointerID ( 根据你想要实现的内容)。
  • 如果用户刚刚启动了 hold ( MSGESTURE_FLAG_BEGIN标志),请在MSPointerHold事件处理程序内检查详细信息。 如果是这样,添加转角。 如果没有,请删除它们。

这将导致以下代码:

<!DOCTYPEhtml><html><head><title>Touch article sample 5: simple gesture handler</title><linkrel="stylesheet"type="text/css"href="toucharticle.css"/><scriptsrc="Corners.js"></script></head><body><divid="myGreatPicture"class="container"/><script>var myGreatPic = document.getElementById("myGreatPicture");
 // Creating a new MSGesture that will monitor the myGreatPic DOM Elementvar myGreatPicAssociatedGesture = new MSGesture();
 myGreatPicAssociatedGesture.target = myGreatPic;
 // You need to first register to MSPointerDown to be able to// have access to more complex Gesture events myGreatPic.addEventListener("MSPointerDown", pointerdown, false);
 myGreatPic.addEventListener("MSGestureHold", holded, false);
 // Once pointer down raised, we're sending all pointers to the MSGesture objectfunction pointerdown(event) {
 myGreatPicAssociatedGesture.addPointer(event.pointerId);
 }
 // This event will be triggered by the MSGesture object// based on the pointers provided during the MSPointerDown eventfunction holded(event) {
 // The gesture begins, we're adding the cornersif (event.detail === event.MSGESTURE_FLAG_BEGIN) {
 Corners.append(myGreatPic);
 }
 else {
 // The user has released his finger, the gesture ends// We're removing the corners Corners.remove(myGreatPic);
 }
 }
 // To avoid having the equivalent of the contextual //"right click" menu being displayed on the MSPointerUp event, // we're preventing the default behavior myGreatPic.addEventListener("contextmenu", function (e) {
 e.preventDefault(); // Disables system menu }, false);
 </script></body></html>

尝试只点击或者鼠标单击该元素,无发生。 触摸&只保留 1个手指上的图像或者做一个长鼠标点击它,角出现。 放开你的手指,角落消失。

触摸&在图像上维持 2或者更多的手指,只有当 1个独特手指只有is手指触发时才会发生。

注意:白色边框,corners &图像通过CSS定义的CSS设置。 简单的创建 4个 div ( 使用附加函数),并将它们放在每个角的主元素上,并带有适当的CSS类。

但是,在当前的结果中,我并不满意。 一旦你拿着图片,一旦你轻轻移动你的手指,MSGESTURE_FLAG_CANCEL 标志就会被移动的处理器引起。 i 用户放开图片或者只要他把手指从图片中移出,我宁愿删除他的手指。 为此,我们将只在MSPointerUp或者MSPointerOut上删除角。 这里代码提供了以下代码:

var myGreatPic = document.getElementById("myGreatPicture");// Creating a new MSGesture that will monitor the myGreatPic DOM Elementvar myGreatPicAssociatedGesture = new MSGesture();
myGreatPicAssociatedGesture.target = myGreatPic;// You need to first register to MSPointerDown to be able to// have access to more complex Gesture eventsmyGreatPic.addEventListener("MSPointerDown", pointerdown, false);
myGreatPic.addEventListener("MSGestureHold", holded, false);
myGreatPic.addEventListener("MSPointerUp", removecorners, false);
myGreatPic.addEventListener("MSPointerOut", removecorners, false);// Once touched, we're sending all pointers to the MSGesture objectfunction pointerdown(event) {
 myGreatPicAssociatedGesture.addPointer(event.pointerId);
}// This event will be triggered by the MSGesture object// based on the pointers provided during the MSPointerDown eventfunction holded(event) {
 // The gesture begins, we're adding the cornersif (event.detail === event.MSGESTURE_FLAG_BEGIN) {
 Corners.append(myGreatPic);
 }
}// We're removing the corners on pointer Up or Outfunction removecorners(event) {
 Corners.remove(myGreatPic);
}// To avoid having the equivalent of the contextual //"right click" menu being displayed on the MSPointerUp event, // we're preventing the default behaviormyGreatPic.addEventListener("contextmenu", function (e) {
 e.preventDefault(); // Disables system menu}, false);

示例 2: 处理比例,转换&旋转

最后,如果要缩放。翻译或者旋转一个元素,只需编写一个非常少的代码行。 你首先需要到 MSGestureChange事件处理事件。 这个事件将通过 MSGestureEvent对象( 如旋转缩放,translationX,当前应用到你的HTML元素中的文档来发送你的各种属性。

在默认情况下,MSGesture对象提供了一个自由的惯性算法。 这意味着你可以使用HTML元素,并使用手指将它扔在屏幕上,动画将被处理。

最后,为了反映MSGesture发送的这些更改,你需要相应地移动元素。 最简单的方法就是应用一些CSS转换映射旋转。比例。翻译细节与手指手势匹配。 为此,请使用 MSCSSMatrix 元素。

总之,如果你希望处理以前的示例中的所有这些酷的手势,则 register 对于以下事件:

myGreatPic.addEventListener("MSGestureChange", manipulateElement, false);

并使用以下处理程序:

function manipulateElement(e) {
 // Uncomment the following code if you want to disable the built-in inertia // provided by dynamic gesture recognition// if (e.detail == e.MSGESTURE_FLAG_INERTIA)// return;// Get the latest CSS transform on the elementvar m = new MSCSSMatrix(e.target.currentStyle.transform); 
 e.target.style.transform = m
. translate(e.offsetX, e.offsetY) // Move the transform origin under the center of the gesture. rotate(e.rotation * 180/Math.PI) // Apply Rotation. scale(e.scale) // Apply Scale. translate(e.translationX, e.translationY) // Apply Translation. translate(-e.offsetX, -e.offsetY); // Move the transform origin back}

尝试移动并将图像 inside 移动到 black 区域的1个上的手指。 尝试缩放或者旋转包含 2个上手指的元素。 结果非常出色,而且代码非常简单,因为所有的复杂性都是由IE10本身处理的。

你也可以在这里看到他们:

相关资源

从逻辑上讲,在本文中共享所有细节和相关链接,你现在可以在你的网站 & Windows 存储应用程序中实现MSPointer事件模型。 这样,你就有了在 IE 10中轻松地增强用户体验的机会。

David Rousset
David是微软的一位开发者,专攻HTML5和web开发。 阅读他的博客在MSDN上或者跟随他的 @davrous 在上。

本文是来自 IE 团队的HTML5技术系列的一部分。 在本文中试用 3个月的免费 BrowserStack 跨浏览器 测试 @ http://modern.IE


bro  SUP  event  触摸  事件