10个打开了我新世界大门的 WebAPI

原来我对这些 Web API 一无所知,又又又打开了个人新世界,将来 Web 能够作到更多,早日一统江湖吧,吼吼吼。html

虽然这些 API 不少目前还存在兼容性的问题,可是仍是有必要了解一下的,文中的代码,我已经都测试过了。但愿你看完以后可以有所收获。git

原文连接: https://blog.bitsrc.io/10-use...

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

这篇文章中描述的全部 Web API 示例均可以在这里找到:web

1. Web Audio API

Web Audio API MDNapi

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),将音频元素做为音频源传递。app

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

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

这个例子有问题,因此该连接也没法正常使用,能够拷贝上面的代码在本地运行

try it

2. Fullscreen API

Fullscreen API MDN

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() ,从而返回到普通视图。

try it

注:该连接中的视频资源找不到了,可是全屏功能是正常的,你们也能够在本地测试

3. Web Speech API

Web Speech API MDN

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() 对象,将咱们在输入框中输入的文本转换为语音。而后,调用语音对象 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 回调中,咱们提取文本并将其设置到文本区域。因此当咱们对着麦克风说话时,这些内容会输出在文本区域中。

try it

译者:个人爪机和电脑 Chrome(V83) 都不能支持该 API

4. Bluetooth API

Bluetooth API MDN

实验技术

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

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

基础 APInavigator.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

try it

译者注:电脑上 Chrome 浏览器上测试了下,是支持该API的。

5. Channel Messaging API

Channel Messaging API MDN

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 之间发送文本。

译者注:这个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)
}

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

让咱们看一下 iframeiframe.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 it

译者注:这个 try 不起来哈,能够拷贝我上面的代码在本地尝试

6. Vibration API

Vibration API MDN

大多数现代移动设备包括振动硬件,其容许软件代码经过使设备摇动来向用户提供物理反馈。Vibration APIWeb 应用程序提供访问此硬件(若是存在)的功能,若是设备不支持此功能,则不会执行任何操做。

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>

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

try it

译者注:在安卓手机上测试正常

7. Broadcast Channel API

Broadcast Channel API MDN

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 页,iframeworker 都将接收今后处发送的消息,所以该页面能够接收其余上下文发送的消息。

Try it

8. Payment Request API

Payment Request API MDN

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 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)
        })
    }
</script>

networkstypessupportedTypes 都是描述付款方式。details 列出了咱们的购买商品和总费用。

构建 PaymentRequest 实例,paymentRequest.show() 将在浏览器中显示付款界面。并在 Promise 成功的回调中处理用户的数据。

它们是使用 Payment API 进行付款的许多配置,至少经过上面的示例,咱们已经了解了 Payment Request API 的使用方式和工做方式。

try it

译者注:测试了下,可是没有走彻底流程,毕竟我坚定不付款的~

9. Resize Observer API

Resize Observer API MDN

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 框中显示的信息。

try it

10. Pointer Lock API

Pointer Lock API MDN

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: 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>
<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#boxdiv#ball

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

PointerLock 有一个 pointerlockchange 事件监听器。当指针锁定状态更改时,将触发此事件。在其回调中,咱们将其添加到 mousemove 事件。在当前浏览器选项卡上移动鼠标时,将触发其回调。在此回调中,所以咱们使用它来获取鼠标的当前X和Y位置。使用此信息,咱们能够设置 div#balltopleft 样式属性,所以,当鼠标移动时,咱们会看到一个跳舞的球(译者注:原文的demo中没有设置div#ball的定位,所以修改 topleft 值时,小球位置没有变化)。

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

try it

译者注:这个demo有点问题,所以try不起来,你们能够拷贝我上面的代码在本地 try.

总结

Web日趋复杂。愈来愈多的原生功能正在使用中,这是由于Web用户的数量远远大于原生APP用户。用户在原生应用上的体验被带到Web上,这样他们无需去使用原生应用。

好嘛,若是看到这里,说明是真爱了。要不要给个人 Github 增长一个 star。

关注公众号,加入技术交流群

WechatIMG167.jpeg

相关文章
相关标签/搜索