原来我对好多 Web API
一无所知,打开了我新世界的大门,未来 Web
可以做到更多,早日一统江湖吧,吼吼吼。
虽然这些 API
很多目前还存在兼容性的问题,但是还是有必要了解一下的,文中的代码,我已经都测试过了。希望你看完之后能够有所收获。
你可能已经知道并使用更为流行的 Web APIs
(Web Worker
,Fetch
等),但也有少数不那么流行的 API
,我个人喜欢使用,并建议你也尝试一下。
这篇文章中描述的所有 Web API
示例都可以在这里找到:
1. Web Audio API
Web Audio API
允许你在 Web
上操作音频流。它可用于向网络上的音频源添加效果和滤镜。
音频源可以来自 <audio>
,视频/音频源文件或音频网络流。
让我们看一个简单的例子:
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head"> Demo - Audio </div>
<div class="web-api-card-body">
<div id="error" class="close"></div>
<div>
<audio controls src="./lovely.mp4" id="audio"></audio>
</div>
<div>
<button onclick="audioFromAudioFile.init()">Init</button>
<button onclick="audioFromAudioFile.play()">Play</button>
<button onclick="audioFromAudioFile.pause()">Pause</button>
<button onclick="audioFromAudioFile.stop()">Stop</button>
</div>
<div>
<span>Vol: <input onchange="audioFromAudioFile.changeVolume()" type="range" id="vol" min="1" max="3"
step="0.01" value="1" /></span>
<span>Pan: <input onchange="audioFromAudioFile.changePan()" type="range" id="panner" min="-1"
max="1" step="0.01" value="0" /></span>
</div>
</div>
</div>
</div>
</body>
<script>
const l = console.log
let audioFromAudioFile = (function () {
var audioContext
var volNode
var pannerNode
var mediaSource
function init() {
l("Init")
try {
audioContext = new AudioContext()
mediaSource = audioContext.createMediaElementSource(audio)
volNode = audioContext.createGain()
volNode.gain.value = 1
pannerNode = new StereoPannerNode(audioContext, { pan: 0 })
mediaSource.connect(volNode).connect(pannerNode).connect(audioContext.destination)
console.log(volNode)
}
catch (e) {
error.innerHTML = "The Web Audio API is not supported in this device."
error.classList.remove("close")
}
}
function play() {
audio.play()
}
function pause() {
audio.pause()
}
function stop() {
audio.stop()
}
function changeVolume() {
volNode.gain.value = document.getElementById('vol').value
}
function changePan() {
pannerNode.gain.value = tdocument.getElementById('panner').value
}
return {
init,
play,
pause,
stop,
changePan,
changeVolume
}
})()
</script>
复制代码
译者注:源代码有点小问题,上面的代码我已经修改过,可以运行,不过mp4文件换成自己本地有的。
此示例将音频从 <audio>
元素传递到 AudioContext
。声音效果(例如声像)在添加到音频输出(扬声器)之前已添加到音频源。
单击 Init
按钮将调用 init
函数。这将创建一个 AudioContext
实例并将其设置为 audioContext
。接下来,它创建一个媒体源 createMediaElementSource(audio)
,将音频元素作为音频源传递。
createGain
创建音量节点 volNode
。在这里,我们调整音频的音量。接下来,使用 StereoPannerNode
设置声像效果。后,将节点连接到媒体源。
我们有一个音量和声像的滑块,拖动它们会影响音量和音频的声像效果。
这个例子有问题,所以该链接也无法正常使用,可以拷贝上面的代码在本地运行
2. Fullscreen API
Fullscreen API
让我们能够在 Web app
中启用全屏模式。它使你可以选择要在全屏模式下查看的元素。在 Android
手机中,它将删除浏览器窗口和 Android
顶部状态栏(显示网络状态,电池状态等的地方)。
方法:
-
requestFullscreen
在系统上以全屏模式显示选定的元素,从而关闭其他应用程序以及浏览器和系统UI元素。 -
exitFullscreen
将全屏模式退出到正常模式。
让我们看一个简单的示例,其中我们可以使用全屏模式观看视频:
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head"> Demo - Fullscreen </div>
<div class="web-api-card-body">
<div id="error" class="close"></div>
<div> This API makes fullscreen-mode of our webpage possible. It lets you select the Element you want to
view in fullscreen-mode, then it shuts off the browsers window features like URL bar, the window
pane, and presents the Element to take the entire width and height of the system. In Android phones,
it will remove the browsers window and the Android UI where the network status, battery status are
displayed, and display the Element in full width of the Android system. </div>
<div class="video-stage">
<video id="video" src="./lovely.mp4"></video>
<button onclick="toggle()">Toogle Fullscreen</button>
</div>
<div> This API makes fullscreen-mode of our webpage possible. It lets you select the Element you want to
view in fullscreen-mode, then it shuts off the browsers window features like URL bar, the window
pane, and presents the Element to take the entire width and height of the system. In Android phones,
it will remove the browsers window and the Android UI where the network status, battery status are
displayed, and display the Element in full width of the Android system. </div>
</div>
</div>
</div>
</body>
<script>
const l = console.log
function toggle() {
const videoStageEl = document.querySelector(".video-stage")
console.log(videoStageEl.requestFullscreen)
if (videoStageEl.requestFullscreen) {
if (!document.fullscreenElement) {
videoStageEl.requestFullscreen()
}
else {
document.exitFullscreen()
}
} else {
error.innerHTML = "Fullscreen API not supported in this device."
error.classList.remove("close")
}
}
</script>
复制代码
video
元素在 div#video-stage
元素中,并带有一个按钮 Toggle Fullscreen
。
当我们单击 Toggle Fullscreen
按钮时,我们希望使元素 div#video-stage
变为全屏显示。
看一下 toggle
这个函数:
function toggle() {
const videoStageEl = document.querySelector(".video-stage")
if(!document.fullscreenElement)
videoStageEl.requestFullscreen()
else
document.exitFullscreen()
}
复制代码
获取 div#video-stage
元素,并将其实例保留在 videoStageEl
上。
我们用过 document.fullsreenElement
属性可以知道该元素是否处于全屏模式,如果不是全屏模式,可以调用 videoStageEl
上的 requestFullscreen()
方法,使 div#video-stage
接管整个设备视图。
如果在全屏模式下点击 Toggle Fullscreen
按钮,将会调用 document.exitFullcreen()
,从而返回到普通视图。
注:该链接中的视频资源找不到了,但是全屏功能是正常的,大家也可以在本地测试
3. Web Speech API
Web Speech API
让我们可以将语音合成和语音识别功能添加到Web应用中。
使用此 API
,我们将能够向Web应用发出语音命令,就像在 Android
上通过其 Google Speech
或像在Windows
中使用 Cortana
一样。
让我们看一个简单的例子。我们将看到如何使用 Web Speech API
实现文本到语音和语音到文本的转换。
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div id="error" class="close"></div>
<div class="web-api-card">
<div class="web-api-card-head"> Demo - Text to Speech </div>
<div class="web-api-card-body">
<div>
<input placeholder="Enter text here" type="text" id="textToSpeech" />
</div>
<div>
<button onclick="speak()">Tap to Speak</button>
</div>
</div>
</div>
<div class="web-api-card">
<div class="web-api-card-head"> Demo - Speech to Text </div>
<div class="web-api-card-body">
<div>
<textarea placeholder="Text will appear here when you start speeaking."
id="speechToText"></textarea>
</div>
<div>
<button onclick="tapToSpeak()">Tap and Speak into Mic</button>
</div>
</div>
</div>
</div>
</body>
<script>
try {
var speech = new SpeechSynthesisUtterance()
var recognition = new SpeechRecognition()
} catch (e) {
error.innerHTML = "Web Speech API not supported in this device."
error.classList.remove("close")
}
function speak() {
speech.text = textToSpeech.value
speech.volume = 1
speech.rate = 1
speech.pitch = 1
alert(window.speechSynthesis)
window.speechSynthesis.speak(speech)
}
function tapToSpeak() {
recognition.onstart = function () { }
recognition.onresult = function (event) {
const curr = event.resultIndex
const transcript = event.results[curr][0].transcript
speechToText.value = transcript
}
recognition.onerror = function (ev) {
console.error(ev)
}
recognition.start()
}
</script>
复制代码
个演示 Demo - Text to Speech
演示了通过一个简单的输入框接收输入的文字以及一个按钮点击后输出语音的功能。
看一下
speak
函数:
function speak() {
speech.text = textToSpeech.value
speech.volume = 1
speech.rate = 1
speech.pitch = 1
window.speechSynthesis.speak(speech)
}
复制代码
它实例化 SpeechSynthesisUtterance()
对象,将我们在输入框中输入的文本转换为语音。然后,调用语音对象 SpeechSynthesis
的 speak
函数,使输入框中的文本在我们的扬声器中放出。
第二个演示 Demo - Speech to Text
是语音识别演示。我们点击 Tap and Speak into Mic
按钮,对着麦克风说话,我们说的单词就被翻译成了文本。
Tap and Speak into Mic
按钮单击后调用 tapToSpeak
函数:
function tapToSpeak() {
recognition.onstart = function () { }
recognition.onresult = function (event) {
const curr = event.resultIndex
const transcript = event.results[curr][0].transcript
speechToText.value = transcript
}
recognition.onerror = function (ev) {
console.error(ev)
}
recognition.start()
}
复制代码
很简单,实例化 SpeechRecognition
,然后注册事件处理程序和回调。在语音识别开始时调用 onstart
,在发生错误时调用 onerror
。每当语音识别捕获到一条线时,就会调用 onresult
。
可以看到,在 onresult
回调中,我们提取文本并将其设置到文本区域。所以当我们对着麦克风说话时,这些内容会输出在文本区域中。
译者:我的爪机和电脑 Chrome
(V83) 都不能支持该 API
。
4. Bluetooth API
实验技术
Bluetooth API
使得我们可以访问手机上的低功耗蓝牙设备,并使用它来将网页中的数据共享到另一台设备上。
想象一下能够创建一个Web聊天应用,该应用程序可以通过蓝牙发送和接收来自其他手机的消息。
基础 API
是 navigator.bluetooth.requestDevice
。调用它将使浏览器提示用户选择一个设备,使他们可以选择一个设备或取消请求。
navigator.bluetooth.requestDevice
需要一个对象。该对象定义了用于返回与过滤器匹配的蓝牙设备的过滤器。
让我们看一个简单的演示。本演示将使用 navigator.bluetooth.requestDeviceAPI
从BLE设备检索基本设备信息。
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head"> Demo - Bluetooth </div>
<div class="web-api-card-body">
<div id="error" class="close"></div>
<div>
<div>Device Name: <span id="dname"></span></div>
<div>Device ID: <span id="did"></span></div>
<div>Device Connected: <span id="dconnected"></span></div>
</div>
<div>
<button onclick="bluetoothAction()">Get BLE Device</button>
</div>
</div>
</div>
</div>
</body>
<script>
function bluetoothAction() {
if (navigator.bluetooth) {
navigator.bluetooth.requestDevice({
acceptAllDevices: true
}).then(device => {
dname.innerHTML = device.name
did.innerHTML = device.id
dconnected.innerHTML = device.connected
}).catch(err => {
error.innerHTML = "Oh my!! Something went wrong."
error.classList.remove("close")
})
} else {
error.innerHTML = "Bluetooth is not supported."
error.classList.remove("close")
}
}
</script>
复制代码
设备的信息会展示出来。单击按钮 Get BLE Device
则调用 bluetoothAction
函数。
function bluetoothAction() {
if (navigator.bluetooth) {
navigator.bluetooth.requestDevice({
acceptAllDevices: true
}).then(device => {
dname.innerHTML = device.name
did.innerHTML = device.id
dconnected.innerHTML = device.connected
}).catch(err => {
error.innerHTML = "Oh my!! Something went wrong."
error.classList.remove("close")
})
} else {
error.innerHTML = "Bluetooth is not supported."
error.classList.remove("close")
}
}
复制代码
该 bluetoothAction
函数调用 navigator.bluetooth.requestDevice
API,参数设置为 acceptAllDevices: true
,这将使其扫描并列出附近所有开启了蓝牙的设备。它返回的是一个 Promise
。
译者注:电脑上 Chrome
浏览器上测试了下,是支持该API的。
5. Channel Messaging API
Channel Messaging API
允许两个不同的脚本运行在同一个文档的不同浏览器上下文(比如两个 iframe
,或者文档主体和一个 iframe
,或者两个 worker
)来直接通讯,在每端使用一个端口(port
)通过双向频道(channel
)向彼此传递消息。。
首先创建一个 MessageChannel
实例:
new MessageChannel()
复制代码
这将返回一个 MessagePort
对象(通讯信道)。
然后,就可以通过 MessagePort.port1
或 MessageChannel.port2
设置端口。
实例化 MessageChannel
的上下文将使用 MessagePort.port1
,另一个上下文将使用 MessagePort.port2
。然后,就可以使用 postMessage API
传递消息了。
每个浏览器上下文都使用 Message.onmessage
监听消息,并使用事件的 data
属性获取消息内容。
让我们看一个简单的示例,在这里我们可以使用 MessageChannel
在文档和 iframe
之间发送文本。
译者注:这个demo,原文中代码有错误,译者对代码进行了修改,亲测可以正常运行
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head"> Demo - MessageChannel </div>
<div class="web-api-card-body">
<div id="error" class="close"></div>
<div id="displayMsg">
</div>
<div>
<input id="input" type="text" placeholder="Send message to iframe" />
</div>
<div>
<button onclick="sendMsg()">Send Msg</button>
</div>
<div>
<iframe id="iframe" src="./iframe.content.html"></iframe>
</div>
</div>
</div>
</div>
</body>
<script>
try {
var channel = new MessageChannel()
var port1 = channel.port1
} catch (e) {
error.innerHTML = "MessageChannel API not supported in this device."
error.classList.remove("close")
}
iframe.addEventListener("load", onLoad)
function onLoad() {
port1.onmessage = onMessage
iframe.contentWindow.postMessage("load", '*', [channel.port2])
}
function onMessage(e) {
const newHTML = "<div>" + e.data + "</div>"
displayMsg.innerHTML = displayMsg.innerHTML + newHTML
}
function sendMsg() {
port1.postMessage(input.value)
}
</script>
复制代码
注意 iframe
的标签,我们在上面加载了一个 iframe.content.html
文件。按钮和文本是我们键入文字并向 iframe
发送消息的地方。
const channel = new MessageChannel()
const port1 = channel.port1
iframe.addEventListener("load", onLoad)
function onLoad() {
port1.onmessage = onMessage
iframe.contentWindow.postMessage("load", '*', [channel.port2])
}
function onMessage(e) {
const newHTML = "<div>" + e.data + "</div>"
displayMsg.innerHTML = displayMsg.innerHTML + newHTML
}
function sendMsg() {
port1.postMessage(input.value)
}
复制代码
我们初始化了 MessageChannel
和 port1
。我们向 iframe
添加了 load
监听。在这里,我们在port1
注册了 onmessage
监听,然后使用 postMessageAPI
将消息发送到 iframe
。看到 port2
被向下发送到 iframe
。
让我们看一下
iframe
的iframe.content.html
:
<body>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head">
Running inside an <i>iframe</i>
</div>
<div class="web-api-card-body">
<div id="iframeDisplayMsg">
</div>
<div>
<input placeholder="Type message.." id="iframeInput" />
</div>
<div>
<button onclick="sendMsgiframe()">Send Msg from <i>iframe</i></button>
</div>
</div>
</div>
</div>
</body>
<script>
var port2
window.addEventListener("message", function(e) {
port2 = e.ports[0]
port2.onmessage = onMessage
})
function onMessage(e) {
const newHTML = "<div>"+e.data+"</div>"
iframeDisplayMsg.innerHTML = iframeDisplayMsg.innerHTML + newHTML
}
function sendMsgiframe(){
port2.postMessage(iframeInput.value)
}
</script>
复制代码
在这里,我们注册了一个消息事件处理函数。我们检索 port2
并在其上设置 onmessage
事件处理函数。现在,我们可以从 iframe
接收消息并将其发送到其父文档。
译者注:这个 try 不起来哈,可以拷贝我上面的代码在本地尝试
6. Vibration API
大多数现代移动设备包括振动硬件,其允许软件代码通过使设备摇动来向用户提供物理反馈。Vibration API
为 Web
应用程序提供访问此硬件(如果存在)的功能,如果设备不支持此功能,则不会执行任何操作。
navigator.vibrate(pattern)
控制振动,pattern
是描述振动模式的单个数字或数字数组。
navigator.vibrate(200);
navigator.vibrate([200]);
复制代码
以上两个例子都可以使设备振动 200 ms 并停止.
navigator.vibrate([200,300,400])
复制代码
这将使设备振动200毫秒,暂停300毫秒,振动400毫秒,然后停止。
可以通过传递0,[]
,[0,0,0]
(全零数组)来停止振动。
我们看一个简单的演示:
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head">
Demo - Vibration
</div>
<div class="web-api-card-body">
<div id="error" class="close"></div>
<div>
<input id="vibTime" type="number" placeholder="Vibration time" />
</div>
<div>
<button onclick="vibrate()">Vibrate</button>
</div>
</div>
</div>
</div>
</body>
<script>
if(navigator.vibrate) {
function vibrate() {
const time = vibTime.value
if(time != "")
navigator.vibrate(time)
}
} else {
error.innerHTML = "Vibrate API not supported in this device."
error.classList.remove("close")
}
</script>
复制代码
我们有输入和一个按钮。在输入框中输入振动的持续时间,然后点击按钮。设备将在输入的时间内振动
译者注:在安卓手机上测试正常
7. Broadcast Channel API
Broadcast Channel API
允许相同源下的不同浏览上下文的消息或数据进行通信。浏览上下文可以是窗口、iframe
等。
BroadcastChannel
类用于创建或加入频道。
const politicsChannel = new BroadcastChannel("politics")
复制代码
politics
将是频道的名称。任何通过 politics
来初始化 BroadcastChannel
构造函数的上下文都将加入频道,它将接收在该频道上发送的任何消息,并且可以将消息发送到该频道。
如果是个使用 BroadcastChannel
的构造函数,politics
则会创建该频道。
要发布到频道,请使用 BroadcastChannel.postMessageAPI
要订阅频道(收听消息),请使用该 BroadcastChannel.onmessage
事件。
为了演示广播频道的用法,我构建了一个简单的聊天应用程序:
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head"> Demo - BroadcastChannel </div>
<div class="web-api-card-body">
<div class="page-info">Open this page in another <i>tab</i>, <i>window</i> or <i>iframe</i> to chat with
them.</div>
<div id="error" class="close"></div>
<div id="displayMsg" style="font-size:19px;text-align:left;">
</div>
<div class="chatArea">
<input id="input" type="text" placeholder="Type your message" />
<button onclick="sendMsg()">Send Msg to Channel</button>
</div>
</div>
</div>
</div>
</body>
<script>
const l = console.log;
try {
var politicsChannel = new BroadcastChannel("politics")
politicsChannel.onmessage = onMessage
var userId = Date.now()
} catch (e) {
error.innerHTML = "BroadcastChannel API not supported in this device."
error.classList.remove("close")
}
input.addEventListener("keydown", (e) => {
if (e.keyCode === 13 && e.target.value.trim().length > 0) {
sendMsg()
}
})
function onMessage(e) {
const { msg, id } = e.data
const newHTML = "<div class='chat-msg'><span><i>" + id + "</i>: " + msg + "</span></div>"
displayMsg.innerHTML = displayMsg.innerHTML + newHTML
displayMsg.scrollTop = displayMsg.scrollHeight
}
function sendMsg() {
politicsChannel.postMessage({ msg: input.value, id: userId })
const newHTML = "<div class='chat-msg'><span><i>Me</i>: " + input.value + "</span></div>"
displayMsg.innerHTML = displayMsg.innerHTML + newHTML
input.value = ""
displayMsg.scrollTop = displayMsg.scrollHeight
}
</script>
复制代码
初始化了 politicsChannel
,并在 politicsChannel
上设置了一个 onmessage
事件监听器,以便它可以接收和显示消息。
点击按钮时,会调用 sendMsg
函数。它通过 BroadcastChannel#postMessageAPI
将消息发送到 politicsChannel
。初始化相同脚本的 tab
页,iframe
或 worker
都将接收从此处发送的消息,因此该页面可以接收其他上下文发送的消息。
8. Payment Request API
Payment Request API
提供了为商品和服务选择支付途径的方法。
该 API
提供了一种一致的方式来向不同的商家提供付款细节,而无需用户再次输入细节。
它向商家提供账单地址,收货地址,卡详细信息等信息。
注意: 此 API
提供了用户付款明细,但并不会带来新的付款方式。
让我们看一个演示如何使用付款请求
API
接受信用卡付款的演示:
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head"> Demo - Credit Card Payment </div>
<div class="web-api-card-body">
<div id="error" class="close"></div>
<div>
<button onclick="buy()">Buy</button>
</div>
</div>
</div>
</div>
</body>
<script>
const networks = ["visa", "amex"]
const * = ["debit", "credit"]
const supportedInstruments = [
{
supportedMethods: "basic-card",
data: {
supportedNetworks: networks,
supported*: *
}
}
]
const details = {
total: {
label: "Total",
amount: {
currency: "USD",
value: "100"
}
},
displayItems: [
{
label: "Item 1",
amount: {
currency: "USD",
value: "50"
}
},
{
label: "Item 2",
amount: {
currency: "USD",
value: "50"
}
},
]
}
try {
var paymentRequest = new PaymentRequest(supportedInstruments, details)
} catch (e) {
error.innerHTML = "PaymentRequest API not supported in this device."
error.classList.remove("close")
}
function buy() {
paymentRequest.show().then(response => {
console.log(response)
})
}
</script>
复制代码
networks
,*
和 supported*
都是描述付款方式。details
列出了我们的购买商品和总费用。
构建 PaymentRequest
实例,paymentRequest.show()
将在浏览器中显示付款界面。并在 Promise
成功的回调中处理用户的数据。
它们是使用 Payment API
进行付款的许多配置,至少通过上面的示例,我们已经了解了 Payment Request API
的使用方式和工作方式。
译者注:测试了下,但是没有走完全流程,毕竟我坚决不付款的~
9. Resize Observer API
Resize Observer API
提供了一种方式,以任何方式调整了注册观察者的元素的大小,都通知观察者。
ResizeObserver
类提供了一个观察器,该观察器将在每个 resize
事件上调用。
const resizeObserver = new ResizeObserver(entries => {
for(const entry of entries) {
if(entry.contentBoxSize)
consoleo.log("element re-sized")
}
})
resizeObserver.observe(document.querySelector("div"))
复制代码
每当调整 div
大小时,控制台上都会打印 "element re-sized"
。
让我们看一下如何使用
Resize Observer API
的示例:
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head">
Demo - ResizeObserver
</div>
<div class="web-api-card-body">
<div id="error" class="close"></div>
<div id="stat"></div>
<div id="resizeBoxCnt">
<div id="resizeBox"></div>
</div>
<div>
<span>Resize Width:<input onchange="resizeWidth(this.value)" type="range" min="0" max="100" value="0" /></span>
</div>
<div>
<span>Resize Height:<input onchange="resizeHeight(this.value)" type="range" min="0" max="100" value="0" /></span>
</div>
</div>
</div>
</div>
</body>
<script>
try {
var resizeObserver = new ResizeObserver(entries => {
for(const entry of entries) {
stat.innerHTML = "Box re-sized. Height:" + entry.target.style.height + " - Width:" + entry.target.style.width
}
})
resizeObserver.observe(resizeBox)
} catch(e) {
error.innerHTML = "ResizeObserver API not supported in this device."
error.classList.remove("close")
}
function resizeWidth(e) {
resizeBox.style.width = `${e}px`
}
function resizeHeight(e) {
resizeBox.style.height = `${e}px`
}
</script>
复制代码
我们在这里有范围滑块。如果我们滑动它们,它们将改变 idv#resizeBox
的宽高。我们在div#resizeBox
上注册了 ResizeObserver
观察器,指示该消息指示框已被调整大小以及其高度和宽度的当前值。
尝试滑动范围滑块,你将看到 div#resizeBox
宽高的变化,此外,我们还将看到 div#stat
框中显示的信息。
10. Pointer Lock API
Pointer Lock API
对于需要大量的鼠标输入来控制运动,旋转物体,以及更改项目的应用程序来说非常有用。对高度视觉化的应用程序尤其重要,例如那些使用人称视角的应用程序,以及 3D 视图和建模。
方法:
-
requestPointerLock
:此方法将从浏览器中删除鼠标并发送鼠标状态事件。这将持续到调用document.exitPointerLock
为止。 -
document.exitPointerLock
:此API
释放鼠标指针锁定并恢复鼠标光标。
让我们来看一个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#box {
background-color: green;
width: ;
height: 400px;
position: relative;
}
#ball {
border-radius: 50%;
background-color: red;
width: 50px;
height: 50px;
position: absolute;
}
</style>
</head>
<body>
<header>
<h2>Web APIs<h2>
</header>
<div class="web-api-cnt">
<div class="web-api-card">
<div class="web-api-card-head"> Demo - PointerLock </div>
<div class="web-api-card-body">
<div id="error" class="close"></div>
<div id="box">
<div id="ball"></div>
</div>
</div>
</div>
</div>
</body>
<script>
const l = console.log
box.addEventListener("click", () => {
if (box.requestPointerLock)
box.requestPointerLock()
else {
error.innerHTML = "PointerLock API not supported in this device."
error.classList.remove("close")
}
})
document.addEventListener("pointerlockchange", (e) => {
document.addEventListener("mousemove", (e) => {
const { movementX, movementY } = e
ball.style.top = movementX + "px"
ball.style.left = movementY + "px"
})
})
</script>
</html>
复制代码
在 div#box
中我们有一个 div#box
和 div#ball
。
我们在 div#box
上设置了一个 click
事件,当单击它时会调用 requestPointerLock()
,这会使光标消失。
PointerLock
有一个 pointerlockchange
事件监听器。当指针锁定状态更改时,将触发此事件。在其回调中,我们将其添加到 mousemove
事件。在当前浏览器选项卡上移动鼠标时,将触发其回调。在此回调中,因此我们使用它来获取鼠标的当前X和Y位置。使用此信息,我们可以设置 div#ball
的 top
和 left
样式属性,因此,当鼠标移动时,我们会看到一个跳舞的球(译者注:原文的demo中没有设置div#ball
的定位,因此修改 top
和 left
值时,小球位置没有变化)。
鼠标事件的两个新参数 —— movementX
和 movementY
提供了鼠标位置的变化情况。当指针锁定被启动之后,正常的 MouseEvent
属性 clientX
, clientY
, screenX
, 和 screenY
,保持不变,就像鼠标没有在移动一样。
译者注:这个demo有点问题,因此try不起来,大家可以拷贝我上面的代码在本地 try.
总结
Web日趋复杂。越来越多的原生功能正在使用中,这是因为Web用户的数量远远大于原生APP用户。用户在原生应用上的体验被带到Web上,这样他们无需去使用原生应用。
好嘛,如果看到这里,说明是真爱了。要不要给我的 Github 增加一个 star。
如有翻译不当的地方,多多包涵,欢迎在评论区指正~