Pointer Event叫浏览器的统一指针事件。
在早期的浏览器,输入的事件其实相对单纯,只有考虑到鼠标和键盘两种;而当时的鼠标事件,其实就是 click、mousedown、mouseup 等等的事件。但是当手机、平板开始流行时候,再移动装置上的主要操作界面,已经从鼠标变成是触控了~由于触控和鼠标的操作逻辑,算是有根本上的差异的,再加上大部分的装置又支持多点触控,所以虽然浏览器大多会把触控的事件对应回传统的鼠标事件,但是如果希望能有更细致的操作,传统的鼠标事件是不够用的。
而目前 W3C 针对触控操作的部分,则有两种事件模型可以使用,其中一个是专门为了触控设计的 Touch Event,这应该算是目前大部分移动浏览器所支持的事件架构;而另一种,则是由微软所提出的、试图统一所有指针装置的事件架构、Pointer Event。
相较于目前主流的 Touch Event (W3C)只有去处理触控的事件,微软提出的 Pointer Event 则是希望能把所有的指针事件都统一来做管理、让程序开发时能更简单地使用。下图就是官方的示意图。
以目前定义的标准来说,Pointer Event (W3C)能支持的指针装置包括了鼠标、触控(手指)、以及笔型装置;而除了能整合不同类型的指针装置外,Pointer Event 针对能支持的硬件,也多了相当多额外的参数,像是压力、宽度、高度,甚至比型装置的倾斜程度等等。
很遗憾的,目前基本上只有微软自家的 Internet Explorer(10+)有原生支持 Pointer event,其他的浏览器,都仅支持 Touch Even;而再加上 IE 本身并不支持 Touch Event,为了兼容其他浏览器,微软提供一个让其他浏览器也能支持 Pointer Event 的 JavaScript 函式库handjs
基本上只要在网页裡面引入这个 JavaScript 档后,Firefox 或 Chrome 也就都可以使用 Pointer Event 了~
事件的定义
Pointer Event 总共定义了八种事件,其列表如下:pointerdown
pointerup
pointercancel
pointermove
pointerover
pointerout
pointerenter
pointerleave
基本上,大部分的事件,都可以对应到本来的 mouse event(MSDN 参考),在 W3C 的网页上,也有针对这些事件的详细说明;实际上,如果浏览器侦测到指标是主要的(primary)指针的话,他也会送出鼠标的事件。 而当触发事件时,程序可以取得定义为 PointerEvent 的资料,它应该算是继承了 MouseEvent 的结构后,再附加了一些额外的的资料;其定义如下:interface PointerEvent : MouseEvent {其中,每一个指针都有属于自己的编号、也就是 pointerId;而透过 pointerType 则可以判断他是哪一种类型的指针,目前的标准包含了 mouse、pen、touch 这三种可能。
readonly attribute long pointerId;
readonly attribute long width;
readonly attribute long height;
readonly attribute float pressure;
readonly attribute long tiltX;
readonly attribute long tiltY;
readonly attribute DOMString pointerType;
readonly attribute boolean isPrimary;
};
而要取得指针的位置的时候,则是可以视需要使用 screenX /screenY,或是 clientX / clientY。
其他像是 width、height,就是代表这个指针的大小(应该是给触控用的),pressure 则是指针装置的压力(介于 0-1 之间),而 tileX 和 tileY 则是笔型装置的倾斜程度。
使用的话,由于 自己也是刚开始玩,所以这边就不自己写范例了。
在微软官方的博客文章《Hand.js: a polyfill for supporting pointer events on every browser》和《Unifying touch and mouse: how Pointer Events will make cross-browsers touch support easy》内,就有展示、以及使用范例了~有兴趣写的话,应该是参考这边就可以了。另外,它裡面也有提供一个范例网页(连结),可以做进一步的参考。
Windows 版的 FireFox 预设应该是把触控事件关闭的,需要手动开启,否则就算是在平板上用触控也只会抓到鼠标事件。他的开启方法是在 FireFox 打开「about:config」的页面,找到「dom.w3c_touch_events.enabled」这个项目,把他的值从「0」改成「1」。
MouseEvent 的定义(DOM Level 3、参考):
interface MouseEvent : UIEvent {
readonly attribute long screenX;
readonly attribute long screenY;
readonly attribute long clientX;
readonly attribute long clientY;
readonly attribute boolean ctrlKey;
readonly attribute boolean shiftKey;
readonly attribute boolean altKey;
readonly attribute boolean metaKey;
readonly attribute unsigned short button;
readonly attribute unsigned short buttons;
readonly attribute EventTarget? relatedTarget;
};
我们看看handjs的示例demo代码
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/hand.js"></script>
<style>
* {
-webkit-touch-callout: none;
/* prevent callout to copy image, etc when tap to hold */
-webkit-text-size-adjust: none;
/* prevent webkit from resizing text to fit */
/* make transparent link selection, adjust last value opacity 0 to 1.0 */
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-user-select: none;
/* prevent copy paste, to allow, change 'none' to 'text' */
-webkit-tap-highlight-color: rgba(0,0,0,0);
touch-action: none;
}
body {
background-color: #000000;
margin: 0px;
}
canvas {
background-color: #111133;
display: block;
position: absolute;
}
.container {
width: auto;
text-align: center;
background-color: #ff0000;
}
</style>
</head>
<body>
<div class="container">
<canvas id="canvasSurface"></canvas>
</div>
<script>
var Collection = function () {
this.count = 0;
this.collection = {};
this.add = function (key, item) {
if (this.collection[key] != undefined)
return undefined;
this.collection[key] = item;
return ++this.count
}
this.remove = function (key) {
if (this.collection[key] == undefined)
return undefined;
delete this.collection[key]
return --this.count
}
this.item = function (key) {
return this.collection[key];
}
this.forEach = function (block) {
for (key in this.collection) {
if (this.collection.hasOwnProperty(key)) {
block(this.collection[key]);
}
}
}
}
"use strict";
// shim layer with setTimeout fallback
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var touches; // collections of pointers
var canvas,
c; // c is the canvas' context 2D
document.addEventListener("DOMContentLoaded", init);
window.onorientationchange = resetCanvas;
window.onresize = resetCanvas;
function init() {
setupCanvas();
touches = new Collection();
canvas.addEventListener('pointerdown', onPointerDown, false);
canvas.addEventListener('pointermove', onPointerMove, false);
canvas.addEventListener('pointerup', onPointerUp, false);
canvas.addEventListener('pointerout', onPointerUp, false);
requestAnimFrame(draw);
}
function resetCanvas(e) {
// resize the canvas - but remember - this clears the canvas too.
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
//make sure we scroll to the top left.
window.scrollTo(0, 0);
}
function draw() {
c.clearRect(0, 0, canvas.width, canvas.height);
touches.forEach(function (touch) {
c.beginPath();
c.fillStyle = "white";
c.fillText(touch.type + " id : " + touch.identifier + " x:" + touch.x + " y:" + touch.y, touch.x + 30, touch.y - 30);
c.beginPath();
c.strokeStyle = touch.color;
c.lineWidth = "6";
c.arc(touch.x, touch.y, 40, 0, Math.PI * 2, true);
c.stroke();
});
requestAnimFrame(draw);
}
function createPointerObject(event) {
var type;
var color;
switch (event.pointerType) {
case event.POINTER_TYPE_MOUSE:
type = "MOUSE";
color = "red";
break;
case event.POINTER_TYPE_PEN:
type = "PEN";
color = "lime";
break;
case event.POINTER_TYPE_TOUCH:
type = "TOUCH";
color = "cyan";
break;
}
return {
identifier: event.pointerId,
x: event.clientX,
y: event.clientY,
type: type,
color: color
};
}
function onPointerDown(e) {
touches.add(e.pointerId, createPointerObject(e));
}
function onPointerMove(e) {
if (touches.item(e.pointerId)) {
touches.item(e.pointerId).x = e.clientX;
touches.item(e.pointerId).y = e.clientY;
}
}
function onPointerUp(e) {
touches.remove(e.pointerId);
}
function setupCanvas() {
canvas = document.getElementById('canvasSurface');
c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
c.strokeStyle = "#ffffff";
c.lineWidth = 2;
}
</script>
</body>
</html>
如果不需要插件兼容,那么下面的原生代码也做了兼容不同浏览器支持pointer event的处理,代码如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<style type="text/css">
/* Direct all pointer events to JavaScript code. */
.touch {
-ms-touch-action: none;
/* set for IE */
touch-action: none;
/* set for Edge */
}
#monitor{
height: 50px;
}
</style>
</head>
<body>
<h1>Touch event 不同浏览器的兼容测试</h1>
<br />
<div id="monitor">
Coordinate: X-0, Y-0
</div>
<div id="holder" class="touch" style="height:200px;background-color:rgb(103, 195, 215)">
在这个区域移动你的手指,看看坐标的变化.
</div>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/jquery.17.js"></script>
<script type="text/javascript">
window.onload = function() {
if (window.PointerEvent) //IE 11 & Edge
{
$('#holder').on('pointermove', printcoordinate);
} else if (window.MSPointerEvent) //IE10
{
$('#holder').on('MSPointerMove', printcoordinate);
} else //Chrome, Safari
{
$('#holder').on('touchmove', printcoordinate);
}
function printcoordinate(e) {
var pointerEnabled = window.PointerEvent || window.MSPointerEvent;
var touches = pointerEnabled ? e.originalEvent: e.originalEvent.touches[0];
$('#monitor').html("Coordinate: X-" + touches.pageX + ", Y-" + touches.pageY);
}
}
</script>
</body>
</html>
网友回复