精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

前端與硬件設(shè)備交互探秘,最全總結(jié)!

開發(fā) 前端
在現(xiàn)代Web開發(fā)中,處理用戶輸入事件是構(gòu)建交互式應(yīng)用的關(guān)鍵部分。這些輸入事件可以來自多種設(shè)備,包括鍵盤、鼠標(biāo)(或觸控板)、觸摸屏以及游戲控制器等。

隨著技術(shù)的發(fā)展,前端技術(shù)與硬件設(shè)備的交互模式正變得日益豐富多樣。從基礎(chǔ)的點擊、滑動操作,進化到高級的傳感器數(shù)據(jù)捕獲及設(shè)備遠(yuǎn)程操控,前端技術(shù)正持續(xù)跨越傳統(tǒng)的交互壁壘,為用戶塑造出更為便捷且智能的使用體驗。本文就來對前端與硬件交互多種方式進行全面盤點。

接收設(shè)備的輸入

在現(xiàn)代Web開發(fā)中,處理用戶輸入事件是構(gòu)建交互式應(yīng)用的關(guān)鍵部分。這些輸入事件可以來自多種設(shè)備,包括鍵盤、鼠標(biāo)(或觸控板)、觸摸屏以及游戲控制器等。

鍵盤事件

鍵盤事件是最常見的用戶輸入方式之一,包括按鍵按下(keydown)、按鍵釋放(keyup)等事件。

  • keydown:當(dāng)按鍵被按下時觸發(fā)。
  • keyup:當(dāng)按鍵被釋放時觸發(fā)。

監(jiān)聽鍵盤事件的基本方法是使用addEventListener方法:

document.addEventListener('keydown', function(event) {  
    // 使用event.key來獲取按鍵的值  
    console.log('Key down:', event.key);  
});

Pointer事件

Pointer 事件是一個統(tǒng)一的指針輸入模型,旨在處理所有類型的指針輸入,包括鼠標(biāo)、觸控筆和觸摸。Pointer事件包括pointerdown、pointerup、pointermove等。

  • pointerdown:當(dāng)指針按下時觸發(fā)。
  • pointerup:當(dāng)指針釋放時觸發(fā)。
  • pointermove:當(dāng)指針移動時觸發(fā)。

監(jiān)聽Pointer事件的例子:

document.addEventListener('pointerdown', function(event) {
    console.log('Pointer down at:', event.clientX, event.clientY);  
});

還可以直接使用鼠標(biāo)事件,常見的鼠標(biāo)事件包括:

  • click:單擊鼠標(biāo)左鍵時觸發(fā)。
  • dblclick:雙擊鼠標(biāo)左鍵時觸發(fā)。
  • mousedown:鼠標(biāo)按鈕被按下時觸發(fā)。
  • mouseup:鼠標(biāo)按鈕被松開時觸發(fā)。
  • mousemove:鼠標(biāo)在元素上移動時觸發(fā)。
  • mouseenter:鼠標(biāo)進入元素時觸發(fā)。
  • mouseleave:鼠標(biāo)離開元素時觸發(fā)。
  • contextmenu:用戶右鍵點擊時觸發(fā)。
  • wheel:鼠標(biāo)滾輪滾動時觸發(fā)。
  • auxclick:輔助鍵(如中鍵或右鍵)被點擊時觸發(fā)。

例子:

document.addEventListener('mousedown', function(event) {  
    // 使用event.button來判斷哪個鼠標(biāo)按鈕被按下  
    let buttonPressed;  
    switch (event.button) {  
        case 0:  
            buttonPressed = 'Left button';  
            break;  
        case 1:  
            buttonPressed = 'Middle button';  
            break;  
        case 2:  
            buttonPressed = 'Right button';  
            break;  
        default:  
            buttonPressed = 'Unknown button';  
    }  

    console.log(buttonPressed);

    // 如果按下了右鍵,則阻止默認(rèn)的上下文菜單  
    if (event.button === 2) {  
        event.preventDefault();
    }  
});

mousedown事件對象的button屬性表示被按下的鼠標(biāo)按鈕。這個屬性的值如下:

  • 0:表示主按鈕(通常是左鍵)。
  • 1:表示中間按鈕(通常是滾輪按鈕,但不是所有鼠標(biāo)都有)。
  • 2:表示次按鈕(通常是右鍵)。

游戲控制器

Gamepad API 允許 Web 應(yīng)用檢測并響應(yīng)來自游戲控制器的輸入,包括按鈕按壓和軸移動。這對于開發(fā)需要精確控制的游戲或應(yīng)用非常有用。

使用 Gamepad API,首先需要檢查是否有連接的游戲控制器:

function checkGamepads() {  
    const gamepads = navigator.getGamepads();  
    for (let i = 0; i < gamepads.length; i++) {  
        if (gamepads[i]) {  
            console.log('Gamepad connected:', gamepads[i]);  
            // 處理游戲控制器輸入  
        }  
    }  
}  
  
// 定期檢查是否有游戲控制器連接  
setInterval(checkGamepads, 100);

一旦檢測到游戲控制器,可以訪問其buttons和axes屬性來讀取按鈕狀態(tài)和軸位置:

if (gamepad.buttons[0].pressed) {  
    console.log('Button 0 pressed');  
}  
  
console.log('Axis 0:', gamepad.axes[0]); // 通常表示左右移動  
console.log('Axis 1:', gamepad.axes[1]); // 通常表示上下移動

獲取音頻和視頻

在現(xiàn)代Web開發(fā)中,訪問和處理音頻與視頻流是一項強大的功能,它允許開發(fā)者創(chuàng)建實時通信應(yīng)用、視頻錄制工具、音頻處理應(yīng)用等。MediaDevices.getUserMedia() API 是實現(xiàn)這一功能的關(guān)鍵接口,它允許Web應(yīng)用請求訪問用戶的音頻和/或視頻設(shè)備(如攝像頭和麥克風(fēng)),并獲取實時媒體流。

獲取實時音頻和視頻流

MediaDevices.getUserMedia() 是一個異步函數(shù),它提示用戶允許Web應(yīng)用訪問其音頻和/或視頻設(shè)備。一旦用戶授權(quán),該函數(shù)返回一個 Promise,該 Promise 解析為一個 MediaStream 對象,該對象包含了來自音頻和/或視頻設(shè)備的實時數(shù)據(jù)。

navigator.mediaDevices.getUserMedia({ audio: true, video: true })  
  .then(function(stream) {  
    // 使用視頻流,例如將其顯示在video元素上  
    var video = document.querySelector('video');  
    video.srcObject = stream;  
    video.play();  
  })  
  .catch(function(err) {  
    console.error("Error accessing media devices.", err);  
  });

注意,要使用攝像頭或麥克風(fēng),需要申請權(quán)限。navigator.mediaDevices.getUserMedia() 的第一個參數(shù)是一個對象,用于指定詳細(xì)信息和每種媒體類型的要求例如,如果要訪問攝像頭,則第一個參數(shù)應(yīng)為 {video: true}。如需同時使用麥克風(fēng)和攝像頭,就要傳遞 {video: true, audio: true}。

瀏覽器在調(diào)用 navigator.mediaDevices.getUserMedia() 時顯示權(quán)限對話框, 讓用戶能夠選擇授予或拒絕對其攝像頭/麥克風(fēng)的訪問權(quán)限。

控制攝像頭

在訪問用戶攝像頭前,需要獲取用戶的授權(quán)。這里還是調(diào)用navigator.mediaDevices.getUserMedia()方法來實現(xiàn),它會返回一個Promise對象。當(dāng)用戶同意或拒絕訪問攝像頭時,Promise對象會相應(yīng)地resolve或reject。

const constraints = { video: true, audio: true };  
try {  
  const stream = await navigator.mediaDevices.getUserMedia(constraints);  
  // 成功獲取到視頻流,可以在這里進行后續(xù)處理  
} catch (err) {  
  // 用戶拒絕或其他錯誤,可以在這里處理錯誤  
  console.error("Error accessing media devices.", err);  
}

成功獲取到視頻流后,可以將其賦值給HTML中的元素的srcObject屬性,并調(diào)用play()方法播放視頻流。

<video id="video" width="640" height="480" autoplay></video>  
<script>  
  const video = document.querySelector('#video');  
  navigator.mediaDevices.getUserMedia({ video: true, audio: false })  
    .then(function(stream) {  
      video.srcObject = stream;  
      video.play();  
    })  
    .catch(function(err) {  
      console.error("Error accessing media devices.", err);  
    });  
</script>

可以通過MediaStream API提供的getVideoTracks()方法可以獲取到視頻軌道,并通過enabled屬性來打開或關(guān)閉攝像頭。

const tracks = stream.getVideoTracks();  
tracks[0].enabled = false; // 關(guān)閉第一條視頻軌道(即攝像頭)

可以使用MediaRecorder API來錄制視頻并保存為文件。

const mediaRecorder = new MediaRecorder(stream);  
let chunks = [];  
  
mediaRecorder.ondataavailable = function(event) {  
  chunks.push(event.data);  
};  
  
mediaRecorder.onstop = function() {  
  const blob = new Blob(chunks, { type: 'video/mp4' });  
  const videoURL = window.URL.createObjectURL(blob);  
  // 這里可以將videoURL賦值給某個<video>元素的src屬性來播放錄制的視頻  
  // 或者將blob對象上傳到服務(wù)器  
  chunks = []; // 清空chunks數(shù)組,以便下次錄制  
};  
  
// 開始錄制  
mediaRecorder.start();  
  
// 停止錄制  
// mediaRecorder.stop(); // 可以在需要的時候調(diào)用

可以使用Canvas API對當(dāng)前攝像頭畫面進行截圖。

const canvas = document.createElement('canvas');  
canvas.width = video.videoWidth;  
canvas.height = video.videoHeight;  
const ctx = canvas.getContext('2d');  
ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);  
// 將canvas內(nèi)容轉(zhuǎn)換為圖片URL并顯示或下載  
const imageURL = canvas.toDataURL('image/png');  
// 可以在這里將imageURL賦值給某個<img>元素的src屬性來顯示圖片,或者使用a標(biāo)簽的download屬性來下載圖片

使用設(shè)備進行打印

當(dāng)調(diào)用 window.print() 方法時,瀏覽器會顯示一個打印對話框,允許用戶配置打印設(shè)置(如頁面布局、紙張大小、打印份數(shù)等)。

使用設(shè)備進行身份驗證

Web Authentication API 是一個現(xiàn)代、開放標(biāo)準(zhǔn)的 API,旨在通過公鑰加密技術(shù)來簡化用戶認(rèn)證過程,同時增強安全性。它支持多種身份驗證方式,包括使用藍(lán)牙、NFC(近場通信)、USB漫游設(shè)備(如U2F或FIDO2身份驗證器)以及平臺身份驗證器(如內(nèi)置在筆記本電腦或智能手機中的指紋識別器或屏幕鎖定機制)。Authentication 它利用公鑰密碼學(xué),在用戶的設(shè)備上生成密鑰對(公鑰和私鑰),其中公鑰存儲在服務(wù)器上,私鑰則安全地保存在用戶設(shè)備上。

注意:在 Web Authentication API 中,“挑戰(zhàn)”(challenge)指的是一個由服務(wù)器生成的唯一、隨機的數(shù)據(jù)字符串。它有助于防止重放攻擊、增強安全性,并確保請求的真實性和完整性。

注冊過程

  • 生成挑戰(zhàn):服務(wù)器生成一個唯一的挑戰(zhàn)(通常是一個隨機字節(jié)數(shù)組),并將其發(fā)送給客戶端。
  • 調(diào)用API:客戶端使用navigator.credentials.create()方法開始注冊過程。該方法接受一個包含多個選項的對象作為參數(shù),包括應(yīng)用ID(通常是域名的哈希值)、用戶ID(如用戶名或郵箱地址)、公鑰參數(shù)(指定使用的公鑰算法和類型)以及挑戰(zhàn)等。
  • 用戶交互:用戶被提示選擇或插入一個身份驗證器,并按照設(shè)備要求進行身份驗證(如輸入PIN碼、指紋識別等)。
  • 生成并返回憑據(jù):身份驗證器生成一個公鑰憑據(jù),并將其與用戶的私鑰一起存儲。公鑰和必要的元數(shù)據(jù)(如認(rèn)證器類型、公鑰算法等)被封裝在一個響應(yīng)對象中,并返回給客戶端。
  • 存儲憑據(jù):客戶端將響應(yīng)對象發(fā)送回服務(wù)器,服務(wù)器提取公鑰并存儲在數(shù)據(jù)庫中,與用戶ID相關(guān)聯(lián)。

認(rèn)證過程

  • 生成挑戰(zhàn):與注冊過程類似,服務(wù)器生成一個新的挑戰(zhàn)。
  • 調(diào)用API:客戶端使用navigator.credentials.get()方法開始認(rèn)證過程。該方法接受一個包含挑戰(zhàn)、應(yīng)用ID以及允許重用的憑據(jù)列表(可選)的對象作為參數(shù)。
  • 用戶交互:用戶再次被提示選擇或插入身份驗證器,并按照設(shè)備要求進行身份驗證。
  • 生成并返回斷言:身份驗證器使用私鑰簽署挑戰(zhàn),并將簽名連同憑據(jù)ID封裝在一個斷言對象中,返回給客戶端。
  • 驗證斷言:客戶端將斷言對象發(fā)送回服務(wù)器,服務(wù)器使用存儲的公鑰驗證簽名,以確認(rèn)用戶身份。

訪問設(shè)備上的文件

在Web開發(fā)中,處理本地文件的需求很常見。隨著Web技術(shù)的發(fā)展,現(xiàn)代瀏覽器提供了幾種API來處理用戶文件,其中包括File System Access API和較老的File API。

File System Access API

File System Access API 提供了 showOpenFilePicker 和 showSaveFilePicker 方法,分別用于打開文件選擇對話框和保存文件對話框。

async function readFileAndSave() {
  try {
    // 打開文件選擇對話框
    const [fileHandle] = await window.showOpenFilePicker();
    
    // 讀取文件內(nèi)容
    const file = await fileHandle.getFile();
    const contents = await file.text();
    
    console.log('文件內(nèi)容:', contents);
    
    // 打開保存文件對話框
    const saveOptions = {
      suggestedName: 'saved-file.txt',
      types: [
        {
          description: 'Text files',
          accept: {
            'text/plain': ['.txt'],
          },
        },
      ],
    };
    
    const saveHandle = await window.showSaveFilePicker(saveOptions);
    
    // 寫入文件內(nèi)容
    const writableStream = await saveHandle.createWritable();
    await writableStream.write(contents);
    await writableureStream.close();
    
    console.log('文件已保存');
  } catch (error) {
    console.error('發(fā)生錯誤:', error);
  }
}

File API

如果 File System Access API 不可用,可以使用 File API 來實現(xiàn)類似的功能。File API 提供了 FileReader 對象,用于讀取文件內(nèi)容。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>讀取文件</title>

</head>

<body>
  <input type="file" id="fileInput" multiple>
  <pre id="fileContent"></pre>

  <script>
    document.getElementById('fileInput').addEventListener('change', function(event) {
      const files = event.target.files;
      const fileContentElement = document.getElementById('fileContent');
      
      fileContentElement.textContent = '';
      
      for (const file of files) {
        const reader = new FileReader();
        
        reader.onload = function(e) {
          fileContentElement.textContent += e.target.result + '\n';
        };
        
        reader.readAsText(file);
      }
    });
  </script>

</body>

</html>

在這個例子中,創(chuàng)建了一個文件輸入框,用戶可以通過它選擇本地文件。當(dāng)用戶選擇文件后,使用 FileReader 對象來讀取文件內(nèi)容,并將其顯示在頁面上。

訪問設(shè)備上的傳感器

通用傳感器 API(Generic Sensor API)是一種允許 Web 應(yīng)用訪問設(shè)備上的傳感器數(shù)據(jù)的標(biāo)準(zhǔn)。這些傳感器包括移動傳感器(如加速度計和陀螺儀)以及環(huán)境傳感器(如環(huán)境光傳感器和磁力計)。這些API使得網(wǎng)頁和應(yīng)用能夠利用設(shè)備的硬件傳感器來提供更豐富的用戶體驗。

通用傳感器 API 的主要組件如下:

  • Sensor API:提供了一個通用的接口來訪問各種類型的傳感器數(shù)據(jù)。
  • Motion Sensors:包括加速度計(Accelerometer)和陀螺儀(Gyroscope)。
  • Orientation Sensors:通常與設(shè)備的方向有關(guān),可以提供關(guān)于設(shè)備方向的詳細(xì)信息。
  • Environmental Sensors:包括環(huán)境光傳感器和磁力計。

使用加速度計:

if ('Accelerometer' in window) {
  const accelerometer = new Accelerometer();

  accelerometer.addEventListener('reading', () => {
    console.log('Acceleration X:', accelerometer.x);
    console.log('Acceleration Y:', accelerometer.y);
    console.log('Acceleration Z:', accelerometer.z);
  });

  accelerometer.start();

  // 停止傳感器
  // accelerometer.stop();
} else {
  console.log('Accelerometer is not supported on this device.');
}

使用環(huán)境光傳感器:

if ('AmbientLightSensor' in window) {
  const ambientLightSensor = new AmbientLightSensor();

  ambientLightSensor.addEventListener('reading', () => {
    console.log('Ambient Light Level:', ambientLightSensor.illuminance);
  });

  ambientLightSensor.start();
} else {
  console.log('AmbientLightSensor is not supported on this device.');
}

DeviceMotion和DeviceOrientation

如果通用傳感器API不可用,可以使用DeviceMotion和DeviceOrientation事件來訪問設(shè)備的加速度計、陀螺儀和羅盤數(shù)據(jù)。

使用DeviceMotion事件獲取加速度計數(shù)據(jù):

window.addEventListener('devicemotion', (event) => {
  console.log('Acceleration X:', event.acceleration.x);
  console.log('Acceleration Y:', event.acceleration.y);
  console.log('Acceleration Z:', event.acceleration.z);

  console.log('Acceleration Including Gravity X:', event.accelerationIncludingGravity.x);
  console.log('Acceleration Including Gravity Y:', event.accelerationIncludingGravity.y);
  console.log('Acceleration Including Gravity Z:', event.accelerationIncludingGravity.z);
});

使用DeviceOrientation事件獲取陀螺儀和羅盤數(shù)據(jù):

window.addEventListener('deviceorientation', (event) => {
  console.log('Alpha:', event.alpha); // 繞Z軸旋轉(zhuǎn)(羅盤方向)
  console.log('Beta:', event.beta);   // 繞X軸旋轉(zhuǎn)(前后傾斜)
  console.log('Gamma:', event.gamma); // 繞Y軸旋轉(zhuǎn)(左右傾斜)
});

訪問 GPS 坐標(biāo)

在 web 上可以使用 Geolocation API 獲取設(shè)備的當(dāng)前地理位置(通常是經(jīng)緯度坐標(biāo))。

首先,網(wǎng)頁需要請求用戶的權(quán)限來獲取其地理位置。這是因為地理位置信息屬于用戶的隱私數(shù)據(jù),必須得到用戶的明確同意。一旦用戶授予權(quán)限,可以使用navigator.geolocation.getCurrentPosition()方法來獲取當(dāng)前位置。這個方法接受兩個回調(diào)函數(shù)作為參數(shù):成功回調(diào)和失敗回調(diào)。

  • 成功回調(diào):當(dāng)成功獲取到位置信息時調(diào)用,接收一個位置對象作為參數(shù)。
  • 失敗回調(diào):當(dāng)獲取位置信息失敗時調(diào)用,接收一個錯誤對象作為參數(shù)。
// 請求用戶位置  
if (navigator.geolocation) {  
  navigator.geolocation.getCurrentPosition(successCallback, errorCallback);  
} else {  
  console.log("Geolocation is not supported by this browser.");  
}  
  
// 成功回調(diào)  
function successCallback(position) {  
  const latitude = position.coords.latitude;  
  const longitude = position.coords.longitude;  
  console.log(`Latitude: ${latitude}, Longitude: ${longitude}`);  
}  
  
// 失敗回調(diào)  
function errorCallback(error) {  
  switch(error.code) {  
    case error.PERMISSION_DENIED:  
      console.log("User denied the request for Geolocation.");  
      break;  
    case error.POSITION_UNAVAILABLE:  
      console.log("Location information is unavailable.");  
      break;  
    case error.TIMEOUT:  
      console.log("The request to get user location timed out.");  
      break;  
    case error.UNKNOWN_ERROR:  
      console.log("An unknown error occurred.");  
      break;  
  }  
}

檢查設(shè)備電池電量

使用Battery API確實可以獲取關(guān)于電池電量的信息,并且在電池電量或充電狀態(tài)發(fā)生變化時收到通知。

獲取電量信息

  1. 檢測瀏覽器支持
  • 在使用Battery API之前,開發(fā)者需要先檢測用戶所使用的瀏覽器是否支持該API。
  • 可以通過if ('getBattery' in navigator)來判斷瀏覽器是否支持Battery API。
  1. 獲取電池對象
  • 如果瀏覽器支持Battery API,可以通過調(diào)用navigator.getBattery()方法來獲取一個Promise對象。
  • 這個Promise對象在成功時會傳遞一個BatteryManager對象,該對象包含了電池的各種信息。
  1. 讀取電池信息
  • battery.level:表示當(dāng)前電池的電量,范圍從0到1,可以通過乘以100來轉(zhuǎn)換為百分比形式。
  • battery.charging:一個布爾值,表示設(shè)備當(dāng)前是否在充電。
  • battery.chargingTime:表示設(shè)備預(yù)計還需要多長時間充滿,單位為秒(如果設(shè)備已經(jīng)在充電且即將充滿,則可能為0或接近0)。
  • battery.dischargingTime:表示設(shè)備預(yù)計還能使用多長時間,單位為秒(如果設(shè)備正在放電且電量即將耗盡,則可能為一個較大的值或Infinity)。
  • 一旦獲取到BatteryManager對象,開發(fā)者就可以通過該對象的屬性和事件來獲取電池信息。
  • 主要的屬性包括:

電池、電量狀態(tài)通知

  1. 監(jiān)聽電池狀態(tài)變化
  • 為了更加精準(zhǔn)地捕捉和響應(yīng)用戶設(shè)備的電池狀態(tài)動態(tài),開發(fā)者需要實時監(jiān)聽電池狀態(tài)的變化。
  • 可以通過為BatteryManager對象注冊事件監(jiān)聽器來實現(xiàn)這一功能。
  1. 事件類型
  • levelchange:當(dāng)設(shè)備電量發(fā)生變化時觸發(fā)。
  • chargingchange:當(dāng)設(shè)備的充電狀態(tài)發(fā)生變化時觸發(fā)(例如,從充電狀態(tài)變?yōu)槲闯潆姞顟B(tài),或反之)。
  • chargingtimechange:當(dāng)設(shè)備充滿電所需時間發(fā)生變化時觸發(fā)(這通常發(fā)生在充電速率改變時)。
  • dischargingtimechange:當(dāng)設(shè)備放空電所需時間發(fā)生變化時觸發(fā)(這通常發(fā)生在電池使用量或放電速率改變時)。
  1. 實現(xiàn)方式
  • 使用battery.addEventListener()方法來為上述事件類型注冊監(jiān)聽器。
  • 在監(jiān)聽器的回調(diào)函數(shù)中,可以更新UI或執(zhí)行其他邏輯來響應(yīng)電池狀態(tài)的變化。

以下是一個簡單的例子:

if ('getBattery' in navigator) {  
  navigator.getBattery().then(function(battery) {  
    // 初始獲取電池信息  
    console.log('當(dāng)前電池電量: ' + battery.level * 100 + '%');  
    console.log('充電狀態(tài): ' + (battery.charging ? '正在充電' : '未充電'));  
    console.log('充滿電所需時間: ' + battery.chargingTime + '秒');  
    console.log('防空電所需時間: ' + battery.dischargingTime + '秒');  
  
    // 監(jiān)聽電池狀態(tài)變化  
    battery.addEventListener('levelchange', function() {  
      console.log('電量已更新: 當(dāng)前電量為' + (battery.level * 100) + '%');  
    });  
  
    battery.addEventListener('chargingchange', function() {  
      console.log('充電狀態(tài)已變更: ' + (battery.charging ? '正在充電' : '未在充電'));  
    });  
  
    battery.addEventListener('chargingtimechange', function() {  
      console.log('充滿電所需時間更新: 剩余' + battery.chargingTime + '秒');  
    });  
  
    battery.addEventListener('dischargingtimechange', function() {  
      console.log('放空電所需時間更新: 剩余' + battery.dischargingTime + '秒');  
    });  
  }).catch(function(error) {  
    // 處理獲取電池對象失敗的情況  
    console.error('獲取電池信息失敗:', error);  
  });  
} else {  
  // 處理瀏覽器不支持Battery API的情況  
  console.log('當(dāng)前瀏覽器不支持Battery API');  
}

本地網(wǎng)絡(luò)中的多媒體播放控制

Remote Playback API

Remote Playback API 允許網(wǎng)頁應(yīng)用將音頻和視頻內(nèi)容發(fā)送到遠(yuǎn)程播放設(shè)備(如智能電視、無線音箱等)進行播放。這對于構(gòu)建家庭娛樂系統(tǒng)或跨設(shè)備媒體共享功能特別有用。

工作原理

  1. 檢測支持:首先,應(yīng)用需要檢測瀏覽器是否支持 Remote Playback API。
  2. 獲取可用設(shè)備:通過調(diào)用 navigator.mediaDevices.enumerateDevices() 并過濾出支持 Remote Playback 的設(shè)備,可以獲取到當(dāng)前網(wǎng)絡(luò)中的可用設(shè)備列表。但請注意,Remote Playback API 并不直接提供設(shè)備枚舉功能;通常,設(shè)備發(fā)現(xiàn)是通過其他機制(如 UPnP、DLNA 等)或用戶選擇來實現(xiàn)的。
  3. 建立連接:一旦選擇了目標(biāo)設(shè)備,應(yīng)用就可以通過 navigator.remotePlayback.requestRemotePlayback() 方法嘗試與該設(shè)備建立連接。
  4. 發(fā)送媒體:連接建立后,應(yīng)用可以開始將媒體內(nèi)容發(fā)送到遠(yuǎn)程設(shè)備進行播放。

假設(shè)有一個網(wǎng)頁應(yīng)用,它允許用戶選擇并播放存儲在本地服務(wù)器上的視頻文件。該應(yīng)用可以使用 Remote Playback API 將所選視頻發(fā)送到用戶的智能電視進行播放。

// 偽代碼示例,具體實現(xiàn)可能因設(shè)備和瀏覽器而異  
if ('remotePlayback' in navigator.mediaDevices) {  
  // 假設(shè)已經(jīng)通過某種方式選擇了目標(biāo)設(shè)備  
  const remoteDevice = selectedDevice;  
    
  navigator.mediaDevices.requestRemotePlayback(remoteDevice)  
    .then(remote => {  
      // 成功建立連接,開始播放媒體  
      const mediaElement = document.querySelector('video'); // 假設(shè)頁面上有一個 <video> 元素  
      remote.loadVideo(URL.createObjectURL(mediaElement.currentSrc));  
      remote.play();  
    })  
    .catch(error => {  
      // 處理連接失敗的情況  
      console.error('Remote playback failed:', error);  
    });  
} else {  
  console.log('Remote Playback API is not supported in this browser.');  
}

Presentation API

Presentation API 則用于在第二屏幕(如輔助屏幕、HDMI 連接的顯示屏、無線連接的智能電視等)上呈現(xiàn)網(wǎng)頁內(nèi)容。它允許開發(fā)者將網(wǎng)頁的一部分或全部內(nèi)容投影到另一個屏幕上,這對于會議演示、家庭娛樂等場景非常有用。

工作原理

  1. 檢測支持:首先,應(yīng)用需要檢測瀏覽器是否支持 Presentation API。
  2. 獲取可用屏幕:通過調(diào)用 navigator.presentation.getAvailability() 和 navigator.presentation.requestSession() 方法,應(yīng)用可以獲取到當(dāng)前可用的第二屏幕列表,并請求與其中一個屏幕建立會話。
  3. 建立連接并發(fā)送內(nèi)容:一旦會話建立,應(yīng)用就可以開始將內(nèi)容發(fā)送到第二屏幕進行顯示。

假設(shè)有一個網(wǎng)頁應(yīng)用,它允許用戶將當(dāng)前頁面或某個特定部分的內(nèi)容投影到連接在同一本地網(wǎng)絡(luò)上的智能電視上進行顯示。

if ('presentation' in navigator) {  
  navigator.presentation.getAvailability().then(availability => {  
    if (availability === 'available') {  
      // 請求與第二屏幕建立會話  
      navigator.presentation.requestSession().then(presentationSession => {  
        // 會話建立成功,開始發(fā)送內(nèi)容  
        // 假設(shè)我們有一個要投影的 <div> 元素  
        const contentToPresent = document.querySelector('#content-to-present');  
          
        // 創(chuàng)建一個新的 HTML 文檔,并將要投影的內(nèi)容添加到其中  
        const presentationDocument = presentationSession.urls[0]; // 獲取用于投影的 URL  
        const iframe = document.createElement('iframe');  
        iframe.src = presentationDocument;  
        iframe.onload = () => {  
          const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;  
          iframeDoc.open();  
          iframeDoc.write(`  
            <!DOCTYPE html>  
            <html>  
            <head><title>Presentation</title></head>  
            <body>${contentToPresent.innerHTML}</body>  
            </html>  
          `);  
          iframeDoc.close();  
        };  
          
        // 將 iframe 添加到當(dāng)前頁面中(雖然實際上它不會在當(dāng)前頁面顯示)  
        // 這是為了觸發(fā) onload 事件并加載投影內(nèi)容  
        document.body.appendChild(iframe);  
          
        // 稍后可以從 DOM 中移除 iframe,因為它不再需要  
        // document.body.removeChild(iframe);  
          
      }).catch(error => {  
        // 處理請求會話失敗的情況  
        console.error('Presentation session request failed:', error);  
      });  
    } else {  
      console.log('No second screens available.');  
    }  
  }).catch(error => {  
    // 處理獲取可用性失敗的情況  
    console.error('Presentation API availability check failed:', error);  
  });  
} else {  
  console.log('Presentation API is not supported in this browser.');  
}
責(zé)任編輯:姜華 來源: 前端充電寶
相關(guān)推薦

2024-03-22 15:32:21

機器學(xué)習(xí)算法

2010-08-10 17:01:48

FlexJavaScript

2023-12-05 07:45:35

SQL數(shù)據(jù)庫

2024-04-03 09:27:49

后端開發(fā)數(shù)據(jù)庫內(nèi)核

2019-04-04 09:08:41

2009-12-16 11:11:44

HTML 5

2011-09-02 14:59:15

2024-03-01 20:55:40

Pytorch張量Tensor

2025-01-20 08:00:00

圖像增強深度學(xué)習(xí)AI

2009-12-07 09:39:04

Linux設(shè)備驅(qū)動硬件通信

2009-10-21 17:02:51

綜合布線施工經(jīng)驗

2010-03-15 15:45:50

2013-01-09 10:34:13

OpenStackKVM

2023-01-03 17:31:52

2024-12-31 07:00:00

2009-12-16 15:59:13

Linux設(shè)備文件管理

2021-04-27 08:31:10

前端應(yīng)用場景

2021-12-29 09:00:36

Go文件syscall

2024-07-26 10:35:00

點贊
收藏

51CTO技術(shù)棧公眾號

91精品久久久久久久久久久久| 久久久999免费视频| 国产一区二区三区在线观看| 希岛爱理av一区二区三区| 日韩一区二区三区四区| 黄网站欧美内射| 国产小视频在线播放| 狠狠色丁香久久婷婷综合丁香| 欧美激情免费看| 一级黄色片大全| 99精品视频在线免费播放| 午夜精品一区二区三区电影天堂 | 日韩欧美另类中文字幕| 欧美日韩国产一区二区| 一个色的综合| 色偷偷在线观看| 老司机精品视频一区二区三区| 久久久久久久爱| 正在播放国产对白害羞| 另类图片第一页| 欧美久久一区二区| 欧美日韩在线中文| 欧美寡妇性猛交xxx免费| 久久久国产一区二区三区四区小说| 亚洲影院色在线观看免费| 亚洲 欧美 中文字幕| 亚洲网站视频| 久久视频在线视频| 欧美日韩高清丝袜| 久久动漫网址| 日韩手机在线导航| 午夜精品中文字幕| 日韩免费小视频| 亚洲二区在线视频| 久久观看最新视频| av影片免费在线观看| 91论坛在线播放| 国产精品对白刺激久久久| 国产精品久久婷婷| 日本va欧美va精品| 国产精品成人久久久久| 日韩精品国产一区二区| 欧美日韩免费| 欧美日本中文字幕| 国产av 一区二区三区| 不卡在线一区| 在线亚洲午夜片av大片| 在线观看日本中文字幕| 欧美激情在线精品一区二区三区| 亚洲电影天堂av| 亚洲熟妇一区二区| 日韩在线亚洲| 精品粉嫩aⅴ一区二区三区四区| 午夜免费视频网站| 日韩08精品| 日韩一区二区在线免费观看| 天堂在线一区二区三区| 亚州欧美在线| 欧美一区二区三区精品| 午夜激情影院在线观看| 精品久久免费| 精品国产一区久久| 亚洲无人区码一码二码三码| 国产成人精品福利| 亚洲精品一区在线观看| 成人手机在线免费视频| 香蕉久久99| 亚洲天堂av综合网| 麻豆视频免费在线播放| 一区二区蜜桃| 97在线视频一区| 无码人妻黑人中文字幕| 奇米精品一区二区三区在线观看| 国产精品嫩草视频| 国产精品毛片久久久久久久av| 久久精品国产亚洲av麻豆| 亚洲aⅴ乱码精品成人区| a级精品国产片在线观看| 精品伦精品一区二区三区视频| 日本激情视频网站| 久久―日本道色综合久久| 日本精品国语自产拍在线观看| 91社区在线高清| 亚洲精品写真福利| 免费在线观看视频a| 日本免费一区二区三区四区| 欧美三级欧美一级| 污免费在线观看| 麻豆成人入口| 一本色道久久综合亚洲精品小说 | 在线视频 91| 国产精品伊人色| 国产一区二区三区四区hd | 久久亚洲国产精品成人av秋霞| 日韩一级片大全| 激情视频一区| 国产精品高潮在线| 99视频国产精品免费观看a| www.66久久| 天天综合中文字幕| 欧美aa免费在线| 欧美精品自拍偷拍| 国产乱了高清露脸对白| 日本电影一区二区| 国模精品视频一区二区| 国产精品露脸视频| 不卡在线观看av| 一区二区三区四区免费视频| 韩国成人二区| 555www色欧美视频| 免费人成又黄又爽又色| 欧美色图首页| 国产剧情日韩欧美| 五十路在线视频| 亚洲人精品午夜| av在线无限看| 精品久久97| 另类视频在线观看| 波多野结衣在线观看视频| 粉嫩在线一区二区三区视频| 亚洲一区二区在| 成人欧美大片| 亚洲国产欧美日韩精品| 黄色一级片在线免费观看| 秋霞午夜鲁丝一区二区老狼| 久久精品日产第一区二区三区乱码| 精品视频在线一区二区| 欧美伊人精品成人久久综合97| 国产原创剧情av| 亚洲精品电影| 国产日韩在线亚洲字幕中文| 男女视频在线观看| 偷拍一区二区三区| 男男受被啪到高潮自述| 婷婷亚洲图片| 国产日产欧美精品| yw193.com尤物在线| 欧美性xxxxxxxxx| 这里只有精品在线观看视频| 欧美精品自拍| 亚洲一区二区久久久久久久| 日本激情在线观看| 欧美偷拍一区二区| 五月天精品视频| 老司机一区二区三区| 精品乱子伦一区二区三区| av资源网在线播放| 精品人在线二区三区| 九九久久免费视频| 成熟亚洲日本毛茸茸凸凹| 男人天堂手机在线视频| 亚洲网一区二区三区| 久久91亚洲精品中文字幕| 国产裸体无遮挡| 亚洲天堂久久久久久久| www.污网站| 亚洲色图国产| 99影视tv| √天堂8资源中文在线| 精品sm捆绑视频| 日本一本高清视频| 91麻豆国产精品久久| 无人在线观看的免费高清视频| 狠狠综合久久av一区二区蜜桃| 国产精品极品尤物在线观看| 五月天婷婷在线视频| 欧美电影影音先锋| 免费一级特黄特色大片| 91热门视频在线观看| 亚洲成人av免费看| 国产精品国产三级国产在线观看| 91视频最新| 不卡av免费观看| 日韩精品免费一线在线观看| 丰满人妻老熟妇伦人精品| 国产欧美精品一区| 午夜大片在线观看| 99国产精品99久久久久久粉嫩| 九九久久99| 8av国产精品爽爽ⅴa在线观看| 久久精品最新地址| 黄色aaa毛片| 在线亚洲欧美专区二区| 青花影视在线观看免费高清| 成人毛片老司机大片| 日韩avxxx| 国产精品久久久久蜜臀| av一区二区三区在线观看| 性欧美18~19sex高清播放| 色老头一区二区三区在线观看| 精品人妻无码一区二区色欲产成人 | 亚洲国产午夜| 日本一区二区三区四区高清视频| 天堂综合在线播放| 91国产一区在线| 欧美三级黄网| 日韩激情第一页| 国产精品一区二区黑人巨大| 精品欧美国产一区二区三区| 波多野结衣久久久久| 成人免费视频app| 污污的网站18| 亚洲乱码视频| 手机成人av在线| 亚洲国产国产| 99在线视频免费观看| 日韩毛片在线| 国内精品美女av在线播放| 一本一道波多野毛片中文在线| 亚洲第一二三四五区| 91禁在线观看| 色婷婷狠狠综合| 懂色av.com| 亚洲色图丝袜美腿| av女人的天堂| 99天天综合性| 男生和女生一起差差差视频| 久久精品动漫| 97在线国产视频| 女同性一区二区三区人了人一| 日韩欧美视频一区二区三区四区 | 日韩精品高清不卡| 国产在线播放观看| 欧美三级免费| 最新av网址在线观看| 999成人网| 四虎影院一区二区三区| 午夜欧洲一区| 久久99久久精品国产| 136福利精品导航| 成人午夜激情网| 国产精品久久久久久妇女| 国产成人av网址| 小草在线视频免费播放| 97久久精品在线| av影片在线| 欧美激情乱人伦一区| 91在线中文| 欧美老少做受xxxx高潮| sm国产在线调教视频| 久久在精品线影院精品国产| 免费看美女视频在线网站| 在线精品播放av| 成年在线观看免费人视频| 亚洲视频在线观看| 精品欧美不卡一区二区在线观看 | 麻豆传媒视频在线| 色哟哟网站入口亚洲精品| 国产三级在线| 中文欧美日本在线资源| 欧美激情二区| 久久久av电影| 日本在线观看大片免费视频| 欧美日本亚洲视频| www中文字幕在线观看| 久久久久免费视频| av成人 com a| 91大神在线播放精品| 中文字幕在线看片| 日韩美女av在线免费观看| 日本综合视频| 成人精品一区二区三区电影免费 | 久久福利精品| 成人性做爰aaa片免费看不忠| 日本怡春院一区二区| 五月天av在线播放| 国产东北露脸精品视频| www.17c.com喷水少妇| 2022国产精品视频| 国产三级短视频| 亚洲美女一区二区三区| 国产一级片网址| 欧美日韩中文在线| 伊人久久成人网| 日韩精品一区二区三区视频在线观看| 天堂av一区二区三区| 亚洲欧美日韩另类| 日本中文字幕在线观看| 欧美国产日韩一区| 免费观看欧美大片| 国产欧美日韩中文| 91精品国产自产精品男人的天堂 | 久久国产影院| 日本阿v视频在线观看| 久久精品日韩欧美| 日韩av一卡二卡三卡| 99久久精品免费看国产 | 亚洲卡一卡二卡三| 亚洲欧美日本精品| 日本h片在线| 国产精品电影观看| 岛国成人av| 一区二区三视频| 亚洲深夜激情| 最好看的中文字幕| 国产日韩高清在线| 日本一级黄色录像| 欧美日韩1区2区| 五十路在线观看| www.日韩av.com| 超碰aⅴ人人做人人爽欧美| 亚洲一区二区三区乱码aⅴ| 蜜桃国内精品久久久久软件9| 久久久成人精品一区二区三区| 久久狠狠婷婷| 日韩高清一二三区| 欧美激情在线看| 国产免费观看av| 欧美成人艳星乳罩| 免费在线看黄色| 日韩美女中文字幕| 精品福利一区| 欧美这里只有精品| 久久精品久久99精品久久| 日本aaa视频| 亚洲永久免费av| 91theporn国产在线观看| 亚洲欧美制服丝袜| 国产一线二线在线观看| 91探花福利精品国产自产在线 | 亚洲新声在线观看| gogo高清在线播放免费| 91在线网站视频| 99久久婷婷这里只有精品| 欧美xxxxx在线视频| 99国内精品久久| 日韩免费视频网站| 日韩免费视频线观看| 永久免费网站在线| 成人福利网站在线观看| 久久神马影院| 国产一区视频免费观看| xfplay精品久久| www.日本精品| 亚洲国产精彩中文乱码av在线播放| 在线免费av导航| 亚洲a在线观看| 亚洲高清影视| 青娱乐精品在线| 一区二区三区中文字幕| av中文字幕播放| 久久成人亚洲精品| 日韩免费成人| 青青青在线观看视频| 国产麻豆精品在线观看| 18岁成人毛片| 日韩欧美在线观看一区二区三区| 91小视频xxxx网站在线| 91精品在线观| 综合天天久久| 在线成人精品视频| 亚洲国产精品一区二区久久恐怖片| 国产视频在线观看视频| 久久999免费视频| 97久久综合区小说区图片区| 亚洲精品无码国产| 91视频在线看| 欧美一级淫片免费视频黄| 中文字幕亚洲一区二区三区五十路 | 依依成人综合视频| 国 产 黄 色 大 片| 97在线精品国自产拍中文| 神马久久影院| 超碰在线97免费| 亚洲欧美国产三级| 日韩中文字幕综合| 欧美在线一级视频| 日韩理论电影| 制服.丝袜.亚洲.中文.综合懂| 黄色一区二区在线观看| porn视频在线观看| 亚洲伊人一本大道中文字幕| 激情欧美亚洲| 中文字幕欧美激情极品| 欧美一区二区三区免费| 永久免费毛片在线播放| 亚洲国产精品一区在线观看不卡| 国产麻豆视频精品| av中文在线播放| 正在播放亚洲1区| 高潮久久久久久久久久久久久久| 久久久久久久久久久久久久国产| 国产精品色婷婷| 成人毛片在线免费观看| 国产成人亚洲综合91精品| 中文在线日韩| 中文字幕丰满乱子伦无码专区| 欧美三级三级三级爽爽爽| 日本理论片午伦夜理片在线观看| 欧美日韩免费观看一区| 国产精品影音先锋| 精品一区二区无码| 久久久久国产精品一区| 精品99在线| www.黄色网| 欧美色精品天天在线观看视频| 丁香花在线观看完整版电影| 性欧美大战久久久久久久免费观看 | 国产成人一区二区| 一区三区视频|