qt鼠标指针范围超出触摸屏
我经常从开发人员那里收到问题,例如“ 在手机和平板电脑上有这么多具有触摸功能的设备,我应该从哪里开始呢? ”和“ 建立触摸输入最简单的方法是什么? ”简短的回答: “这很复杂。”
当然,在现代的,支持触摸的浏览器中,或者作为较旧的浏览器的后备,确实存在一种更统一的方式来处理Web上的多点触摸输入。 在本文中,我想向您展示一些使用MSPointers的浏览器实验, 这是一种新兴的多点触摸技术和polyfills,它使跨浏览器的支持变得越来越 …… 简单 。 您还可以在自己的网站上尝试并轻松使用的那种代码。
首先,网络上正在发展许多触摸技术–要获得浏览器支持,除了MSPointers之外,您还需要查看iOS触摸事件模型和W3C鼠标事件模型,以支持所有浏览器。 然而,越来越多的支持(和愿意)进行标准化。 九月份,Microsoft将MSPointers提交给W3C进行标准化 ,我们已经达到了“最后征求意见稿”: http : //www.w3.org/TR/pointerevents 。 MS Open Tech团队最近还发布了Webkit的初始Pointer Events原型 。
与MSPointers我之所以实验不是基于设备共享-这是因为微软的基本输入处理方法比什么是目前可在网络上完全不同,值得一看什么,它可能成为 。
不同之处在于,开发人员可以编写更抽象的输入形式,称为“指针”。 指针可以是鼠标光标,钢笔,手指或多个手指在屏幕上的任何接触点。 因此,您不会浪费时间为每种类型的输入分别编码。
概念
我们将首先查看Internet Explorer 10中运行的,公开了MSPointer事件API的应用程序,然后是支持所有浏览器的解决方案。 之后,我们将看到您如何利用IE10手势服务,该服务将帮助您轻松地处理JavaScript代码中的触摸。 由于Windows 8和Windows Phone 8共享相同的浏览器引擎,因此两个平台的代码和概念相同。 此外,您将在本文中学到的所有内容都将帮助您在使用HTML5 / JS构建的Windows应用商店应用中完成相同的任务,因为这再次使用了相同的引擎。
MSPointer背后的想法是让您使用与您已经知道的经典鼠标事件相匹配的模式,通过单个代码库解决鼠标,笔和触摸设备的问题。 的确,鼠标,笔和触摸具有一些共同的属性:例如,您可以使用它们移动指针,并单击它们上的元素。 然后让我们通过同一段代码解决这些情况! 指针将聚合那些通用属性,并以类似于鼠标事件的方式公开它们。
然后,最明显的常见事件是: MSPointerDown , MSPointerMove和MSPointerUp ,它们直接映射到等效的鼠标事件。 您将具有屏幕的X和Y坐标作为输出。
您还具有特定的事件,例如: MSPointerOver , MSPointerOut , MSPointerHover或MSPointerCancel 。
但是,当然,在某些情况下,您可能希望使用与默认鼠标行为不同的方式解决触摸问题,以提供不同的UX。 此外,借助多点触摸屏,您可以轻松地让用户旋转,缩放或平移某些元素。 笔/手写笔甚至可以为您提供鼠标无法提供的一些压力信息。 指针事件将汇总这些差异,您将为每个设备的详细信息构建一些自定义代码。
注意:如果您在Windows 8 / RT设备上具有触摸屏(当然)或使用Windows Phone 8,则最好测试以下嵌入式示例。否则,您确实有一些选择:
1.使用免费的Visual Studio 2012 Express开发工具附带的Windows 8模拟器,获得第一级的体验。 有关其工作原理的更多详细信息,请阅读本文: 使用Windows 8 Simulator&VS 2012调试IE10触摸事件和您的响应式设计 。
2.观看此视频,该视频 演示了在支持触摸,笔和鼠标的Windows 8平板电脑上的以下所有示例 。
3.如果您无权访问Windows 8设备,请使用虚拟的跨浏览器测试服务(如BrowserStack)进行交互式测试。 您可以使用BrowserStack免费3个月时,Internet Explorer团队的礼貌modern.IE 。
处理简单的触摸事件
步骤1:在JS中不执行任何操作,但添加一行CSS
让我们从基础开始。 您可以轻松地使用任何现有的处理鼠标事件JavaScript代码,并且可以使用Internet Explorer 10中的某些笔或触摸设备按原样工作。实际上,如果您不处理Pointer,则IE10将触发鼠标事件作为最后的手段。代码中的事件。 这就是为什么即使开发人员从未想到某天有人会用这种方式用手指“点击”按钮或任何网页上的任何元素的原因。 因此,任何注册到mousedown和/或mouseup事件的代码都可以使用,而无需进行任何修改。 但是mousemove呢?
让我们回顾一下默认行为以回答该问题。 例如,让我们来看这段代码:
<! DOCTYPE html > < html > < head > < title > Touch article sample 1 </ title > </ head > < body > < canvas id ="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 >
它只是通过跟踪鼠标的移动在HTML5 canvas元素内绘制一些蓝色的10px x 10px的正方形。 要对其进行测试,请将鼠标移到该框中。 如果您有触摸屏,请尝试与画布进行交互以自行检查当前行为 :
默认样本 :不执行任何操作时的默认行为 结果 : 只有MouseDown / Up / Click可以触摸。 即,您只能在点击屏幕时用触摸绘制蓝色方块,而在屏幕上移动手指时则不能。 |
您会看到,当您在canvas元素内移动鼠标时,它将绘制一系列蓝色方块。 但是使用touch代替,它只会在您点击canvas元素的确切位置绘制一个唯一的正方形。 尝试在canvas元素中移动手指时,浏览器将尝试在页面内平移,因为这是已定义的默认行为。
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
因此,您需要指定您想要覆盖浏览器的默认行为,并告诉它将触摸事件重定向到您JavaScript代码,而不是尝试对其进行解释。 为此,将页面中不再对默认行为做出React的元素作为目标,并将此CSS规则应用于它们:
-ms-touch-action : auto | none | manipulation | double-tap-zoom | inherit ;
根据您要过滤或不过滤的内容,您有各种可用的值。 您将找到本文中描述的值: 构建触摸友好网站的准则 。
经典的用例是页面中有地图控件。 您想让用户在地图区域内平移和缩放,但保留页面其余部分的默认行为。 在这种情况下,您将仅在显示地图HTML容器上应用此CSS规则(-ms-touch-action:操作)。
在我们的例子中,添加以下CSS块:
< style > #drawSurface { -ms-touch-action : none ; /* Disable touch behaviors, like pan and zoom */ } </ style >
现在会产生以下结果:
步骤1 :添加-ms-touch-action之后 : 无 结果 :禁用默认浏览器平移,并且MouseMove可以工作,但只有一根手指 |
现在,当您在canvas元素内移动手指时,它的行为就像鼠标指针一样。 这很酷! 但是您很快就会问自己一个问题: “为什么这段代码只跟踪一根手指?” 好吧,这是因为我们正处于IE10提供最后的基本触摸体验的最后一件事:映射您的一根手指来模拟鼠标。 据我所知,我们一次只使用一只鼠标。 因此,使用这种方法,一只鼠标==一根手指最多。 那么,如何处理多点触控事件呢?
步骤2:使用MSPointer事件而不是鼠标事件
采取任何现有代码,然后将注册替换为“ MSPointerDown / Up / Move”,将其注册为“ mousedown / up / move”,您的代码将直接支持IE10内的多点触控体验!
例如,在上一个示例中,更改以下代码行:
canvas.addEventListener( "mousemove" , paint, false );
对此:
canvas.addEventListener( "MSPointerMove" , paint, false );
您将得到以下结果:
步骤2 :使用MSPointerMove代替mousemove 结果 : 多点触控作品 |
现在,您可以在系列中绘制与屏幕支持的接触点一样多的正方形! 更好的是,相同的代码适用于触摸,鼠标和笔。 例如,这意味着您可以用鼠标同时画一些线,而用手指画其他线。
如果您想根据输入的类型更改代码的行为,则可以通过pointerType
属性值进行测试。 例如,假设我们要为手指绘制一些10px x 10px的红色正方形,为笔绘制5px x 5px的绿色正方形,为鼠标绘制2px x 2px的蓝色正方形。 您需要用以下一个替换先前的处理程序(paint函数):
function paint(event) { if (event.pointerType) { switch (event.pointerType) { case event.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 ; case event.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 ; case event.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); } }
您可以在此处测试结果:
步骤2b :测试pointerType以测试触摸/笔或鼠标 结果 :您可以更改鼠标/笔/触摸的行为,但是由于2a,该代码现在仅在IE10 +中有效 |
如果您有幸拥有支持三种输入类型的设备(例如BUILD2011期间使用的某些设备,例如Sony Duo 11, Microsoft Surface Pro或Samsung Tablet ),您将能够看到基于三种类型的绘图在输入类型上。 很好,不是吗?
但是,此代码仍然存在问题。 现在,它可以在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 devices var squaresize = 2; context.fillStyle = "rgba(0, 0, 255, 0.5)" ; // Check for pointer type on IE10 if (event.pointerType) { switch (event.pointerType) { case event.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 ; case event.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 ; case event.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); }
同样,您可以在此处测试结果:
示例3 :检测msPointerEnabled以提供后备功能的功能 结果 :IE10的完整完整体验以及其他浏览器中的默认鼠标事件 |
步骤4:支持所有触控实现
如果您想进一步发展并支持所有浏览器和所有触摸实现,则有两种选择:
1 –编写代码以并行处理两个事件模型,如本文所述: 在所有浏览器中处理多点触摸和鼠标输入
2 –只需添加对HandJS的引用,HandJS是我的朋友David Catuhe编写的很棒JavaScript polyfill库,如他的文章所述: HandJS a polyfill用于在每个浏览器上支持指针事件
正如我在本文简介中提到的那样,Microsoft最近向W3C提交了MSPointer Events规范以进行标准化。 W3C创建了一个新的工作组,并且已经根据Microsoft的建议发布了最后的工作草案 。 MS Open Tech团队最近还发布了您可能感兴趣的Webkit初始Pointer Events原型 。
尽管Pointer Events规范还不是标准,但您仍然可以利用David's Polyfill来实现支持该规范的代码,并为在所有现代浏览器中实现Pointer Events成为标准做好准备。 使用David的库,事件将被传播到IE10上的MSPointer,基于Webkit的浏览器上的Touch Events,最后是鼠标事件,作为最后的选择。 真是太酷了! 查看他的文章以发现并理解它的工作原理。 请注意,此polyfill还将非常有用,以通过鼠标事件的优雅后备支持旧的浏览器。
要了解如何使用该库,请看一下本文: 感谢Hand.JS ,它为您展示了如何使用指针事件编写虚拟触摸操纵杆,从而创建了适用于所有Touch模型的通用虚拟触摸操纵杆 。 多亏了HandJS,它可以在具有相同代码库的Windows 8 / RT,Windows Phone 8,iPad / iPhone和Android设备上的IE10上运行!
识别简单手势
现在,我们已经了解了如何处理多点触摸,下面让我们了解如何识别简单的手势,例如轻击或按住元素,然后再识别一些更高级的手势,例如平移或缩放元素。
IE10提供了一个MSGesture对象,它将帮助我们。 请注意,此对象当前特定于IE10,而不是W3C提交的一部分。 用组合MSCSSMatrix元素(我们相当于WebKitCSSMatrix之一),你会看到,你可以建立一个非常简单的方法非常有趣的多点触控体验。 MSCSSMatrix实际上代表了一个4×4齐次矩阵,该矩阵使文档对象模型(DOM)脚本能够访问CSS 2-D和3-D Transforms功能。 但是在开始之前,让我们从基础开始。
基本概念是首先向MSPointerDown注册事件处理程序 。 然后在负责处理MSPointerDown的处理程序内部,您需要选择 要发送到MSGesture对象的指针,以使其检测特定的手势。 然后它将触发以下事件之一: MSGestureTap , MSGestureHold , MSGestureStart , MSGestureChange , MSGestureEnd , MSInertiaStart 。 然后,MSGesture对象将所有提交的指针作为输入参数,并将在它们之上应用手势识别器以提供一些格式化的数据作为输出。 您唯一需要做的就是选择/过滤哪些指针想要成为手势的一部分(基于它们的ID,屏幕上的坐标等等)。 之后,MSGesture对象将为您完成所有操作。
示例1:处理保持手势
我们将看到如何保存元素(一个简单的div,其中包含图像作为背景)。 保留元素后,我们将添加一些角以向用户表明他当前已选择此元素。 这些角将通过动态创建四个div来生成,这些div添加到图像每个角的顶部。 最后,一些CSS技巧将以一种聪明的方式使用变换和线性渐变来获得如下内容:
该序列将是以下序列:
1 –在您感兴趣HTML元素上注册MSPointerDown和MSPointerHold事件
2 –创建一个MSGesture对象,该对象将针对相同HTML元素
3 –在MSPointerDown处理程序中,将要监视的各种PointerID添加到MSGesture对象(根据您要实现的目标全部或部分)。
4 –在MSPointerHold事件处理程序内部,检查详细信息是否用户刚刚开始执行保持手势(MSGESTURE_FLAG_BEGIN标志)。 如果是这样,请添加角点。 如果不是,请将其删除。
这将导致以下代码:
<! DOCTYPE html > < html > < head > < title > Touch article sample 5: simple gesture handler </ title > < link rel ="stylesheet" type ="text/css" href ="toucharticle.css" /> < script src ="Corners.js"></ script > </ head > < body > < div id ="myGreatPicture" class ="container" /> < script > var myGreatPic = document.getElementById( "myGreatPicture" ); // Creating a new MSGesture that will monitor the myGreatPic DOM Element var 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 object function pointerdown(event) { myGreatPicAssociatedGesture.addPointer(event.pointerId); } // This event will be triggered by the MSGesture object // based on the pointers provided during the MSPointerDown event function holded(event) { // The gesture begins, we're adding the corners if (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 >
结果如下:
尝试仅点击或鼠标单击元素,什么也不会发生。 触摸并保持只用一根手指在图像上,或者长按鼠标在图像上,将出现角。 松开手指,角落消失。
触摸并保持两个或多个手指在图像上,仅当一根唯一的手指按住元素时,才会触发Hold手势,因此不会发生任何事情。
注意:白色边框,角落和背景图片是通过在toucharticle.css中定义CSS设置的。 Corners.js只需创建四个div(带有append函数),然后将它们放置在具有适当CSS类的每个角的主元素顶部。
不过,目前的结果让我有些不满意。 握住图片后,只要稍稍移动手指,MSGESTURE_FLAG_CANCEL标志就会被抬起并被处理程序捕获,该处理程序会去除角落。 我希望仅在用户在图片上方的任意位置松开手指时,或在用户将手指从图片界定的框内移出后,才移开边角。 为此,我们将只删除MSPointerUp或MSPointerOut上的角。 而是提供以下代码:
var myGreatPic = document.getElementById( "myGreatPicture" ); // Creating a new MSGesture that will monitor the myGreatPic DOM Element var 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 ); myGreatPic.addEventListener( "MSPointerUp" , removecorners, false ); myGreatPic.addEventListener( "MSPointerOut" , removecorners, false ); // Once touched, we're sending all pointers to the MSGesture object function pointerdown(event) { myGreatPicAssociatedGesture.addPointer(event.pointerId); } // This event will be triggered by the MSGesture object // based on the pointers provided during the MSPointerDown event function holded(event) { // The gesture begins, we're adding the corners if (event.detail === event.MSGESTURE_FLAG_BEGIN) { Corners.append(myGreatPic); } } // We're removing the corners on pointer Up or Out function 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 behavior myGreatPic.addEventListener( "contextmenu" , function (e) { e.preventDefault(); // Disables system menu }, false );
现在提供了我正在寻找的行为:
示例2:处理秤,平移和旋转
最后,如果要缩放,平移或旋转元素,只需编写几行代码即可。 您需要首先注册到MSGestureChange事件。 此事件将通过MSGestureEvent对象文档中描述的各种属性(例如当前应用于HTML元素的rotation , scale , translationX , translationY)发送给您。
更好的是,默认情况下,MSGesture对象免费提供惯性算法。 这意味着您可以拿起HTML元素,然后用手指将其扔到屏幕上,动画将为您处理。
最后,为了反映MSGesture发送的这些更改,您需要相应地移动元素。 最简单的方法是应用一些CSS转换来映射与手指手势匹配的旋转,缩放,平移细节。 为此,请使用MSCSSMatrix元素。
总之,如果您想处理所有先前示例中的酷手势,请像下面这样注册该事件:
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 element var 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 }
这为您提供了最终样本:
尝试用一根或多只手指将图像移动并扔到黑色区域内。 还尝试用两个或更多个手指缩放或旋转元素。 结果非常棒,并且代码非常简单,因为所有复杂性都由IE10本地处理。
直接链接到所有样本
如果您没有可用的IE10触摸屏体验,并且想知道此页面上的示例如何工作,则可以在此处单独查看每个示例:
– 简单的触摸默认示例,不执行任何操作
– 使用CSS -ms-touch-action的简单触摸示例步骤1
– 使用基本的MSPointerMove实现的简单触摸示例步骤2a
– 简单的触摸示例步骤2b,具有pointerType区分
– 简单的触摸示例步骤3,带有MSPointers和鼠标回退
– MSGesture示例1:MSGestureHold处理程序
– MSGesture示例1b:MSGestureHold处理程序
– MSGesture示例2:MSGestureChange
相关资源:
– 在所有浏览器中处理多点触摸和鼠标输入 :polyfill库,将来应该对很多开发人员有帮助
– 指针和手势事件
– IE Test Drive Browser Surface极大地启发了许多嵌入式演示
–尝试在IE10中使用Touch做一些很棒的游戏:
– Contre Jour ,阅读了一篇非常有趣的“ 幕后”文章
– Atari Arcade Games ,还请阅读这篇非常有用的文章: 使用CreateJS构建Atari,其中详细介绍了在所有平台上支持Touch的选择。
– BUILD会话3-140的记录: 触摸屏,触控笔和鼠标,天哪!
逻辑上,本文将共享所有详细信息以及与其他资源的关联链接, 您现在就可以在网站和Windows Store应用程序中实现MSPointer Events模型 。 然后,您就有机会轻松地增强用户在Internet Explorer 10中的体验。
翻译自: https://www.sitepoint.com/unifying-touch-and-mouse-with-pointer-events/
qt鼠标指针范围超出触摸屏