10 个有用的 Web API

导读

本文介绍的这些 Web API,很多目前还存在兼容性的问题,但是还是有必要了解一下的,文中的代码,我已经都测试过了。希望你看完之后能够有所收获。

你可能已经知道并使用更为流行的 Web APIs(Web Worker,Fetch等),但也有少数不那么流行的 API,我个人喜欢使用,并建议你也尝试一下。

这篇文章中描述的所有 Web API 示例都可以在这里找到。

1. Web Audio API

Web Audio API 允许你在 Web 上操作音频流。它可用于向网络上的音频源添加效果和滤镜。

音频源可以来自 <audio>,视频/音频源文件或音频网络流。

让我们看一个简单的例子。

HTML 代码如下:

<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>

对应的 Javascript 代码如下:

let audioFromAudioFile = (function () {
    var audioContext
    var volNode
    var pannerNode
    var mediaSource

    function init() {
        console.log("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 = document.getElementById('panner').value
    }

    return {
        init,
        play,
        pause,
        stop,
        changePan,
        changeVolume
    }
})();

此示例将音频从 <audio> 元素传递到 AudioContext。声音效果(例如声像)在添加到音频输出(扬声器)之前已添加到音频源。

单击 Init 按钮将调用 init 函数。这将创建一个 AudioContext 实例并将其设置为 audioContext。接下来,它创建一个媒体源 createMediaElementSource(audio),将音频元素作为音频源传递。

createGain 创建音量节点 volNode。在这里,我们调整音频的音量。接下来,使用 StereoPannerNode 设置声像效果;最后,将节点连接到媒体源。

我们有一个音量和声像的滑块,拖动它们会影响音量和音频的声像效果。

2. Fullscreen API

Fullscreen API 让我们能够在 Web app 中启用全屏模式。它使你可以选择要在全屏模式下查看的元素。在 Android 手机中,它将删除浏览器窗口和 Android 顶部状态栏(显示网络状态,电池状态等的地方)。

方法:

  • requestFullscreen 在系统上以全屏模式显示选定的元素,从而关闭其他应用程序以及浏览器和系统UI元素。
  • exitFullscreen 将全屏模式退出到正常模式。

让我们看一个简单的示例,其中我们可以使用全屏模式观看视频:

HTML 代码如下:

<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>

Javascript 代码如下:

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")
    }
}

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 实现文本到语音和语音到文本的转换。

HTML 代码:

<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>

Javascript 代码:

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()
}

第一个演示 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() 对象,将我们在输入框中输入的文本转换为语音。然后,调用语音对象 SpeechSynthesisspeak 函数,使输入框中的文本在我们的扬声器中放出。

第二个演示 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 回调中,我们提取文本并将其设置到文本区域。所以当我们对着麦克风说话时,这些内容会输出在文本区域中。

4. Bluetooth API

注:Bluetooth API 是一门实验技术

Bluetooth API 使得我们可以访问手机上的低功耗蓝牙设备,并使用它来将网页中的数据共享到另一台设备上。

想象一下能够创建一个 Web 聊天应用,该应用程序可以通过蓝牙发送和接收来自其他手机的消息。

基础 API 是 navigator.bluetooth.requestDevice。调用它将使浏览器提示用户选择一个设备,使他们可以选择一个设备或取消请求。

navigator.bluetooth.requestDevice 需要一个对象,该对象定义了用于返回与过滤器匹配的蓝牙设备的过滤器。

让我们看一个简单的演示。本演示将使用 navigator.bluetooth.requestDevice API 从 BLE 设备检索基本设备信息。

HTML 代码:

<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>

Javascript 代码:

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")
	}
}

设备的信息会展示出来。单击按钮 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

5. Channel Messaging API

Channel Messaging API 允许两个不同的脚本运行在同一个文档的不同浏览器上下文(比如两个 iframe,或者文档主体和一个 iframe,或者两个 worker)来直接通讯,在每端使用一个端口(port)通过双向频道(channel)向彼此传递消息。。

首先创建一个 MessageChannel 实例:

new MessageChannel();

这将返回一个 MessagePort 对象(通讯信道)。

然后,就可以通过 MessagePort.port1MessageChannel.port2 设置端口。

实例化 MessageChannel 的上下文将使用 MessagePort.port1,另一个上下文将使用 MessagePort.port2。然后,就可以使用 postMessage API 传递消息了。

每个浏览器上下文都使用 Message.onmessage 监听消息,并使用事件的 data 属性获取消息内容。

让我们看一个简单的示例,在这里我们可以使用 MessageChannel 在文档和 iframe 之间发送文本。

HTML 代码:

<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>

Javascript 代码:

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);
}

注意 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);
}


我们初始化了 MessageChannelport1 。我们向 iframe 添加了 load 监听。在这里,我们在 port1 注册了  onmessage 监听,然后使用 postMessage API 将消息发送到 iframe 。看到 port2 被向下发送到 iframe 。

让我们看一下 iframe 的 iframe.content.html

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>

对应的 Javascript 代码:

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);
}

在这里,我们注册了一个消息事件处理函数。我们检索 port2 并在其上设置 onmessage 事件处理函数。现在,我们可以从 iframe 接收消息并将其发送到其父文档。

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](全零数组)来停止振动。

我们看一个简单的演示:

HTML 代码:

<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>

Javascript 代码:

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");
}

我们有输入和一个按钮。在输入框中输入振动的持续时间,然后点击按钮。设备将在输入的时间内振动。

7. Broadcast Channel API

Broadcast Channel API 允许相同源下的不同浏览上下文的消息或数据进行通信。浏览上下文可以是窗口、iframe 等。

BroadcastChannel 类用于创建或加入频道。

const politicsChannel = new BroadcastChannel("politics");

politics 将是频道的名称。任何通过 politics 来初始化 BroadcastChannel 构造函数的上下文都将加入频道,它将接收在该频道上发送的任何消息,并且可以将消息发送到该频道。

如果是第一个使用 BroadcastChannel 的构造函数,politics 则会创建该频道。

要发布到频道,请使用 BroadcastChannel.postMessageAPI

要订阅频道(收听消息),请使用该 BroadcastChannel.onmessage 事件。

为了演示广播频道的用法,我构建了一个简单的聊天应用程序。

HTML 代码:

<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>

Javascript 代码:

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;
}

初始化了 politicsChannel ,并在 politicsChannel 上设置了一个 onmessage 事件监听器,以便它可以接收和显示消息。

点击按钮时,会调用 sendMsg 函数。它通过 BroadcastChannel#postMessage API 将消息发送到 politicsChannel。初始化相同脚本的 tab 页,iframe 或 worker 都将接收从此处发送的消息,因此该页面可以接收其他上下文发送的消息。

8. Payment Request API

Payment Request API 提供了为商品和服务选择支付途径的方法。

该 API 提供了一种一致的方式来向不同的商家提供付款细节,而无需用户再次输入细节。

它向商家提供账单地址,收货地址,卡详细信息等信息。

注意: 此 API 提供了用户付款明细,但并不会带来新的付款方式。

让我们看一个演示如何使用付款请求 API 接受信用卡付款的演示。

HTML 代码:

<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>

Javascript 代码:

const networks = ["visa", "amex"];
const types = ["debit", "credit"];

const supportedInstruments = [{
	supportedMethods: "basic-card",
	data: {
		supportedNetworks: networks,
		supportedTypes: types
	}
}];

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)
	});
}

networkstypessupportedTypes 都是描述付款方式。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 的示例。

HTML 代码:

<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>

Javascript 代码:

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`;
}

我们在这里有范围滑块。如果我们滑动它们,它们将改变 div#resizeBox 的宽高。我们在 div#resizeBox 上注册了 ResizeObserver 观察器,指示该消息指示框已被调整大小以及其高度和宽度的当前值。

尝试滑动范围滑块,你将看到 div#resizeBox 宽高的变化,此外,我们还将看到 div#stat 框中显示的信息。

10. Pointer Lock API

Pointer Lock API 对于需要大量的鼠标输入来控制运动,旋转物体,以及更改项目的应用程序来说非常有用。对高度视觉化的应用程序尤其重要,例如那些使用第一人称视角的应用程序,以及 3D 视图和建模。

支持的方法:

  • requestPointerLock:此方法将从浏览器中删除鼠标并发送鼠标状态事件。这将持续到调用 document.exitPointerLock 为止。
  • document.exitPointerLock:此 API 释放鼠标指针锁定并恢复鼠标光标。

让我们来看一个例子。

HTML 代码:

<!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: 100%;
            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>
</html>

Javascript 代码:

let box = document.querySelector("#box");
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";
	});
});

我们在 div#box 上设置了一个 click 事件,当单击它时会调用 requestPointerLock() 方法,这会使光标消失。

PointerLock 有一个 pointerlockchange 事件监听器。当指针锁定状态更改时,将触发此事件。在其回调中,我们将其添加到 mousemove 事件。在当前浏览器选项卡上移动鼠标时,将触发其回调。在此回调中,因此我们使用它来获取鼠标的当前X和Y位置。使用此信息,我们可以设置 div#balltopleft 样式属性,因此,当鼠标移动时,我们会看到一个跳舞的球。

鼠标事件的两个新参数 — movementXmovementY 提供了鼠标位置的变化情况。当指针锁定被启动之后,正常的 MouseEvent 属性 clientX, clientY, screenX, 和 screenY ,保持不变,就像鼠标没有在移动一样。

总结

Web 应用日趋复杂,越来越多的原生功能正在使用中,这是因为 Web 用户的数量远远大于原生 APP 用户。用户在原生应用上的体验被带到 Web 上,这样他们无需去使用原生应用。希望本文提到的这些 Web API 对你了解最新的前端技术提供一定的帮助。

分享