Pointer Lock
Pointer Lock API
指针锁定(以前叫做 鼠标锁定) 提供了一种输入方法,这种方法是基于鼠标随着时间推移的运动的(也就是说,deltas),而不仅是鼠标光标的绝对位置。通过它可以访问原始的鼠标运动,把鼠标事件的目标锁定到一个单独的元素,这就消除了鼠标在一个单独的方向上到底可以移动多远这方面的限制,并从视图中删去光标。
这个 API 对于需要大量的鼠标输入来控制运动,旋转物体,以及更改项目的应用程序来说非常有用。对高度视觉化的应用程序尤其重要,例如那些使用第一人称视角的应用程序,以及 3D 视图和建模。
举例来说,你可以创建让你的用户简单地通过移动鼠标而不需要点击任何按钮就可以控制视角的应用。那么这些按钮就可以被用作其他动作。这类鼠标输入对于查看地图,卫星图像,或者第一人称场景(例如在一个游戏中或者一个全景视频中)是非常方便使用的。
即使在光标移到浏览器或者屏幕区域之外,指针锁定也能够让你访问鼠标事件。例如,你的用户可以通过不断地移动鼠标来持续旋转或操纵一个 3D 模型。如果没有指针锁定的话,这些旋转或操纵会在指针到达浏览器或者屏幕边缘的那一刻停止。尤其是游戏玩家将会因为此功能而兴奋不已,因为他们可以疯狂地点击按钮,来回地滑动鼠标光标,而不必担心离开了游戏区域,进而不小心误点到另外一个应用程序上,结果将鼠标焦点移离了游戏。杯具了!
基本概念
指针锁定和 鼠标捕获有关。鼠标捕获在一个鼠标被拖曳时可以向一个目标元素持续传递有关事件,但是当鼠标按钮被放开时就会停止。指针锁定和鼠标捕获在以下方面有所不同:
- 它是持久性的。指针锁定不释放鼠标,直到作出一个显式的 API 调用或是用户使用一个专门的释放手势。
- 它不局限于浏览器或者屏幕边界。
- 它持续发送事件,而不管鼠标按钮状态如何。
- 它隐藏光标。
示例
下面是一个如何在你的网页中设置指针锁定的示例。
<button onclick="lockPointer();">锁住它!</button>
<div id="pointer-lock-element"></div>
<script>
// 注意: 截止本文撰写时, 仅有 Mozilla 和 WebKit 支持指针锁定。 // 我们将要使之全屏并指针锁定的元素。
var elem; document.addEventListener("mousemove", function(e) {
var movementX = e.movementX ||
e.mozMovementX ||
e.webkitMovementX ||
0,
movementY = e.movementY ||
e.mozMovementY ||
e.webkitMovementY ||
0; // 打印鼠标移动的增量值。
console.log("movementX=" + movementX, "movementY=" + movementY);
}, false); function fullscreenChange() {
if (document.webkitFullscreenElement === elem ||
document.mozFullscreenElement === elem ||
document.mozFullScreenElement === elem) { // 较旧的 API 大写 'S'.
// 元素进入全屏模式了,现在我们可以请求指针锁定。
elem.requestPointerLock = elem.requestPointerLock ||
elem.mozRequestPointerLock ||
elem.webkitRequestPointerLock;
elem.requestPointerLock();
}
} document.addEventListener('fullscreenchange', fullscreenChange, false);
document.addEventListener('mozfullscreenchange', fullscreenChange, false);
document.addEventListener('webkitfullscreenchange', fullscreenChange, false); function pointerLockChange() {
if (document.mozPointerLockElement === elem ||
document.webkitPointerLockElement === elem) {
console.log("指针锁定成功了。");
} else {
console.log("指针锁定已丢失。");
}
} document.addEventListener('pointerlockchange', pointerLockChange, false);
document.addEventListener('mozpointerlockchange', pointerLockChange, false);
document.addEventListener('webkitpointerlockchange', pointerLockChange, false); function pointerLockError() {
console.log("锁定指针时出错。");
} document.addEventListener('pointerlockerror', pointerLockError, false);
document.addEventListener('mozpointerlockerror', pointerLockError, false);
document.addEventListener('webkitpointerlockerror', pointerLockError, false); function lockPointer() {
elem = document.getElementById("pointer-lock-element");
// 开始于使元素进入全屏模式。目前的实现
// 要求元素在请求指针锁定前要处于全屏模式下
// -- 这在以后可能会发生改变。
elem.requestFullscreen = elem.requestFullscreen ||
elem.mozRequestFullscreen ||
elem.mozRequestFullScreen || // 较旧的 API 把 ‘S’ 大写
elem.webkitRequestFullscreen;
elem.requestFullscreen();
}
</script>
方法/属性 概述
Pointer lock API, 和 Fullscreen API 类似,通过添加新方法来扩展 DOM 元素, requestPointerLock
, 目前还是厂商前缀。按下面这样来写:
element.webkitRequestPointerLock(); // Chrome element.mozRequestPointerLock(); // Firefox
目前 requestPointerLock
的实现还是和 requestFullScreen
以及 Fullscreen API 紧紧地绑在一起的。一个元素在能够被指针锁定之前,必须首先进入全屏模式。就像上面演示的那样,锁定指针的过程是异步的,使用 (pointerlockchange
, pointerlockerror
) 事件来表明请求是成功还是失败了。这和 Fullscreen API 的工作方式是一致的,它使用 requestFullScreen
方法,以及 fullscreenchange
和 fullscreenerror
事件。
Pointer lock API 还扩展了 document
接口,添加了一个新的属性和一个新的方法。新的属性被用于访问当前被锁定的元素(如果有的话),并被命名为 pointerLockElement
,目前也使用厂商前缀。 document
添加的新方法是 exitPointerLock
,顾名思义,它是用来退出指针锁定的。
pointerLockElement
属性适用于确定当前是否有被指针锁定的元素(例如,用来做一个布尔检查),以及当有元素被锁定时获取该元素的一个引用。下面是这两种用法的一个例子:
document.pointerLockElement = document.pointerLockElement ||
document.mozPointerLockElement ||
document.webkitPointerLockElement; // 1) 用于布尔检查--我们被指针锁定了吗?
if (!!document.pointerLockElement) {
// 指针被锁定
} else {
// 指针未被锁定
} // 2) 用于访问指针锁定的元素
if (document.pointerLockElement === someElement) {
// someElement 当前被指针锁定
}
document
的 exitPointerLock
方法被用来退出指针锁定,而且和 requestPointerLock 一样,使用 pointerlockchange
和 pointerlockerror
事件以异步方式工作:
document.exitPointerLock = document.exitPointerLock ||
document.mozExitPointerLock ||
document.webkitExitPointerLock; function pointerLockChange() {
document.pointerLockElement = document.pointerLockElement ||
document.mozPointerLockElement ||
document.webkitPointerLockElement; if (!!document.pointerLockElement) {
console.log("目前还是被锁定。");
} else {
console.log("已经退出锁定。");
}
} document.addEventListener('pointerlockchange', pointerLockChange, false);
document.addEventListener('mozpointerlockchange', pointerLockChange, false);
document.addEventListener('webkitpointerlockchange', pointerLockChange, false); // 试图解除锁定
document.exitPointerLock();
pointerlockchange 事件
当指针锁定状态改变时 – 例如,当调用 requestPointerLock
, exitPointerLock
,用户按下 ESC 键,等等。— pointerlockchange
事件被分发到document
。 这是一个简单事件所以不包含任何的额外数据。
mozpointerlockchange
,在 Chrome 中是 webkitpointerlockchange
。pointerlockerror 事件
当调用 requestPointerLock
或 exitPointerLock
而引发错误时, pointerlockerror
事件被分发到 document
。这是一个简单事件所以不包含任何的额外数据。
mozpointerlockerror
,在 Chrome 中为 webkitpointerlockerror
。鼠标事件扩展
Pointer lock API 使用 movement 属性扩展了标准的 MouseEvent
。
partial interface MouseEvent {
readonly attribute long movementX;
readonly attribute long movementY;
};
.mozMovementX
和 .mozMovementY
, 在 Chrome 中为.webkitMovementX
和 .webkitMovementY
。鼠标事件的两个新参数—movementX
和 movementY
—提供了鼠标位置的变化情况。这两个参数的值,等于两个MouseEvent
属性(screenX
和 screenY)
之间值的变化程度,这些 MouseEvent 属性被存储在两个连续的鼠标移动事件( eNow
和 ePrevious
)中。换言之,指针锁定参数 movementX = eNow.screenX - ePrevious.screenX
。(译注:不存在名为 eNow 或 ePrevious 的事件或属性,eNow 代指当前的鼠标移动事件,ePrevious 代指前一个鼠标移动事件)
锁定状态
当指针锁定被启动之后,正常的 MouseEvent
属性 clientX
, clientY
, screenX
, 和 screenY
,保持不变,就像鼠标没有在移动一样。movementX
和 movementY
属性持续提供鼠标的位置变化。如果鼠标在一个方向上持续移动,movementX
和 movementY
的值是没有限制的。不存在鼠标光标的概念,而且光标无法移到窗口之外,而且也不会被屏幕边缘所固定。
未锁定状态
无论鼠标锁定状态是怎样的, movementX
和 movementY
参数一直有效,并且为了方便起见,甚至在未锁定状态也是有效的。
当鼠标被解除锁定,系统光标可以退出并重新进入浏览器窗口。如果发生这种情况,movementX
和 movementY
可能会被设置成0。
iframe 的限制
指针锁定一次只能锁定一个 iframe。如果你锁定了一个 iframe,你不能试图锁定另外一个 iframe 然后把目标转移到这个 iframe 上;指针锁定将会出错。为了避免这一问题,首先解锁那个锁定的 iframe,然后再锁定另外一个。
在 iframe 默认的情况下, “sandboxed” iframes 会阻止指针锁定。避免这种限制的能力,即以属性/值 <iframe sandbox="allow-pointer-lock">
组合的形式 , 有望很快在 Chrome 中出现。
译自:https://developer.mozilla.org/en-US/docs/API/Pointer_Lock_API;原文地址:http://www.tfan.org/pointer-lock-api
Pointer Lock的更多相关文章
- Pointer Lock API(3/3):一个Demo
简单的Demo演练 点击跳转至Code Pen以查看演示和源码 完整代码 <!DOCTYPE HTML> <html lang="en-US"> <h ...
- Pointer Lock API(2/3):属性、方法、事件
Pointer Lock API 提供了三个属性.两个方法.两个事件 Tabel Of Content 属性 Document.pointerLockElement Document.onpointe ...
- Pointer Lock API(1/3):Pointer Lock 的总体认识
前言 指针锁定(Pointer Lock),以前也叫鼠标锁定,提供了基于鼠标随时间的移动(如deltaΔ)的输入方法,不仅仅是视窗区域鼠标的绝对位置.指针锁定让你能够访问原始的鼠标移动,将鼠标事件的目 ...
- 指针锁定 Pointer Lock API 用法
指针锁定 Pointer Lock API 通过它可以访问原始的鼠标运动(基于指针的相对位移 movementX / movementY),把鼠标事件的目标锁定到一个特定的元素,同时隐藏视图中的指针光 ...
- HTML5 game engines
The following are few examples of game engines implemented with HTML5 and JavaScript: Construct 2: O ...
- Golang网络库中socket阻塞调度源码剖析
本文分析了Golang的socket文件描述符和goroutine阻塞调度的原理.代码中大部分是Go代码,小部分是汇编代码.完整理解本文需要Go语言知识,并且用Golang写过网络程序.更重要的是,需 ...
- HTML5入门总结 HTML5API
w3cshools MDN英文 MDN中文 HTML5 HTML5 is the latest evolution of the standard that defines HTML. The t ...
- Go学习笔记02-源码
第二部分 源码 基于 Go 1.4,相关文件位于 src/runtime 目录.文章忽略了 32bit 代码,有兴趣的可自行查看源码文件.为便于阅读,示例代码做过裁剪. 1. Memory Alloc ...
- C# ConcurrentBag实现
ConcurrentBag可以理解为是一个线程安全无序集合,API比我们的list要弱一点,那我们来看看它的实现: public class ConcurrentBag<T> : IPro ...
随机推荐
- Ubuntu16.04下安装CUDA8.0和tensorflow
GPU版的Tensorflow无疑是深度学习的一大神器,当然caffe之类的框架也可以用GPU来加速训练. 注意:以下安装默认为python2.7 1. 安装依赖包 $ sudo apt-get in ...
- linux环境中,如何使用tar来创建压缩包?解压缩?
需求说明: 今天需要将一个tomcat目录打成压缩包,使用zip感觉有点慢,所以就想用tar来试试,之前一直使用tar的解压缩命令, 今天试试tar的压缩命令 操作过程: 1.通过tar的zcf选项进 ...
- Linux-PAM认证机制
http://www.cnblogs.com/marility/articles/9235522.html https://www.jianshu.com/p/342c05b51b7c https:/ ...
- SpringMVC由浅入深day02_4springmvc校验
4 springmvc校验 4.1 校验Validation理解 b/s系统中对http请求数据的校验多数在客户端进行,这也是出于简单及用户体验性上考虑,但是在一些安全性要求高的系统中服务端校验是不可 ...
- vue中使用动态echart图表
<template> <div class="block"> <div class="title">展会实时人流里统计< ...
- mysql字段集合中如何去除其中一个元素
在一对多方案中,我们用逗号拼接进行存储,避免存储多条,或者分表,那么此时出现了存储上如果需要修改的话 就带来了难度,比如规则记录表如下 如果2号规则被删除,那么这张表的所有有2的记录也要被清除掉,此时 ...
- 有人在群里问mysql如何选择性更新部分条件的问题
有人在群里问这个问题 update xt_kh set zhye=zhye+1,hzyj=hzyj+1 where dlgh='kiss0451' and hzms=1 如果这样写 hzms不等于1的 ...
- Python学习--字符串slicing
Found this great table at http://wiki.python.org/moin/MovingToPythonFromOtherLanguages Python indexe ...
- Django 添加应用
一个项目可以添加多个应用,可以使用以下两种方法来添加应用: [root@localhost web]$ python manage.py startapp blog [root@localhost w ...
- 使用 Beautiful Soup
Beautiful Soup 用法: (1) 前面我们爬取一个网页,都是使用正则表达式来提取想要的信息,但是这种方式比较复杂,一旦有一个地方写错,就匹配不出来了,因此我们可以使用 Beautiful ...