學會這些 Web API 使你的開發效率翻倍

九旬發表於2023-04-10

隨著瀏覽器的日益壯大,瀏覽器自帶的功能也隨著增多,在 Web 開發過程中,我們經常會使用一些 Web API 增加我們的開發效率。

本篇文章主要選取了一些有趣且有用的 Web API 進行介紹,並且 API 可以線上執行預覽。

Clipboard API(剪下板)

剪下板 API 快速將內容複製到剪下板上,下面是一鍵複製的方法:

const onClipText = (text) => {
    handleCopyValue(text)
        .then(() => {
            alert("複製成功");
        })
        .catch(() => {
            alert("自動複製失敗,請手動複製");
        });
};

const handleCopyValue = (text) => {
    //瀏覽器禁用了非安全域的 navigator.clipboard 物件
    //線上上環境會報錯 TypeError: Cannot read properties of undefined (reading 'writeText')
    if (!navigator.clipboard && window.isSecureContext) {
        return navigator.clipboard.writeText(text);
    } else {
        // 判斷是否支援複製
        if (!document.execCommand("copy")) return Promise.reject();
        // 建立標籤,並隱藏
        const textArea = document.createElement("textarea");
        textArea.style.position = "fixed";
        textArea.style.top = textArea.style.left = "-100vh";
        textArea.style.opacity = "0";
        textArea.value = text;
        document.body.appendChild(textArea);
        // 聚焦、複製
        textArea.focus();
        textArea.select();
        return new Promise((resolve, reject) => {
            // 不知為何,必須寫這個三目,不然copy不上
            document.execCommand("copy") ? resolve() : reject();
            textArea.remove();
        });
    }
};

執行onClipText方法,即可將想複製內容,複製到使用者的剪下板上。

Fullscreen API(進入/退出全屏)

Fullscreen API 用於在 Web 應用程式中開啟全屏模式,使用它就可以在全屏模式下檢視頁面/元素。在安卓手機中,它會溢位瀏覽器視窗和安卓頂部的狀態列(顯示網路狀態、電池狀態等的地方)。

下面是一個 Fullscreen API 的例子:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Fullscreen API Example</title>
  </head>
  <body>
    <div id="booktext">
       <h1>正能量先鋒</h1>
        <p>在今天這個快節奏、競爭激烈的時代裡,我們時常會面臨一些挑戰和困難,有時甚至會讓我們感到絕望和沮喪。但我們應該時刻銘記,每一個困難背後都有無限的機會和可能。</p>
       <button onclick="toggleFullscreen()">進入/退出沉浸式閱讀</button>
    </div>
    
    <script>
      var bookText = document.getElementById('booktext');
      
      function toggleFullscreen() {
        if (document.fullscreenElement) {
          document.exitFullscreen();
        } else {
          bookText.requestFullscreen().catch(err => {
            console.log(`Error attempting to enable full-screen mode: ${err.message} (${err.name})`);
          });
        }
      }
    </script>
  </body>
</html>

上面的例子展示瞭如何透過 Fullscreen API 實現一個影片全屏播放的功能。

在 HTML 中,我們定義了一個影片播放器,使用 controls 屬性新增了播放器的控制欄。同時,我們也定義了一個按鈕,點選該按鈕可以全屏播放影片。

在 JavaScript 中,我們首先透過 getElementById 獲取到影片容器,然後透過 querySelector 獲取到影片元素本身。接著,定義了一個 toggleFullscreen 函式來監聽按鈕的點選事件,並根據當前全屏狀態呼叫 requestFullscreenexitFullscreen 來切換全屏狀態。

需要注意的是,requestFullscreen 方法可能會被瀏覽器阻止,例如因為使用者未授權。因此在實際使用中,我們需要使用 catch 方法來捕獲 requestFullscreen 方法的呼叫錯誤資訊。

Online State API(網路狀態)

就是獲取當前的網路狀態,同時也有對應的事件去響應網路狀態的變化。

window.addEventListener("online", onlineHandler); // 聯網時
window.addEventListener("offline", offlineHandler); // 斷網時

比如很常見的一個需求,斷網時提示,網路恢復時重新整理。

實現斷網重連:

const onlineHandler = () => {
    window.location.reload();
};
const offlineHandler = () => {
    alert("網路異常,請檢查您的網路");
};
window.addEventListener("online", onlineHandler);
window.addEventListener("offline", offlineHandler);

這樣就可以監聽使用者的網路狀態,如網路連結、斷開時可以對使用者進行提示以及做相應的邏輯處理。

Page Visibility API(頁面顯示)

我們可以用document.visibitilityState來監聽網頁可見度,是否解除安裝..

在手機和電腦上都會現這種情況,比如頁面中有一個影片正在播放,然後在切換tab頁後給影片暫停播放,或者有個定時器輪詢,在頁面不顯示的狀態下停止無意義的輪詢等等。

比如一個影片的例子來展示:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Fullscreen API Example</title>
  </head>
  <body>
 <video id="vs" src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm" controls>
 </video>
<script>
const video = document.getElementById('vs')

window.addEventListener('visibilitychange',() => {
    // 透過這個方法來獲取當前標籤頁在瀏覽器中的啟用狀態。
    switch(document.visibilityState){
        case'prerender': // 網頁預渲染 但內容不可見
        case'hidden':    // 內容不可見 處於後臺狀態,最小化,或者鎖屏狀態
        video.puase()
        case'visible':   // 內容可見
        video.play()
        case'unloaded':  // 文件被解除安裝
        video.destory()
    }
});
</script>
</body>
</html>

這個API的用處就是用來響應我們網頁的狀態,如果這個標籤頁顯示則影片就開始播放,隱藏就暫停,關閉就解除安裝。

Screen Orientation API(頁面方向)

我們可以透過以下程式碼來演示如何使用Screen Orientation API來控制頁面的方向:

// 獲取螢幕方向物件
const orientation = screen.orientation;

// 監聽螢幕方向變化事件
orientation.addEventListener('change', () => {
  console.log(`螢幕方向變為:${orientation.type}`);
});

// 鎖定螢幕方向為橫屏
orientation.lock('landscape').then(() => {
  console.log('螢幕方向已鎖定為橫屏');
}).catch((err) => {
  console.log(`鎖定螢幕方向失敗:${err}`);
});

// 解鎖螢幕方向
orientation.unlock();

在這段程式碼中,我們首先透過screen.orientation獲取了螢幕方向物件,並透過addEventListener方法監聽了螢幕方向變化事件。然後,我們使用lock方法將螢幕方向鎖定為橫屏,並在鎖定成功後列印了一條訊息。最後,我們使用unlock方法解鎖了螢幕方向。

需要注意的是,lock方法可能會在某些裝置上無法生效,因此我們需要在實際使用中進行相容性測試。

Battery API(電池資訊)

以下是一個使用 Battery API 的簡單示例:

<!DOCTYPE html>
<html>
<head>
    <title>Web Battery API Example</title>
</head>
<body>
    <h1>Web Battery API Example</h1>
    <div id="battery-status">
        <p>當前電量: <span id="battery-level"></span></p>
        <p>電池狀態: <span id="battery-status"></span></p>
    </div>

    <script>
        // 獲取電池資訊
        navigator.getBattery().then(function(battery) {
            // 更新電量資訊
            updateBatteryStatus(battery);

            // 監聽電池資訊變化
            battery.addEventListener('levelchange', function() {
                updateBatteryStatus(battery);
            });

            battery.addEventListener('chargingchange', function() {
                updateBatteryStatus(battery);
            });
        });

        // 更新電量資訊
        function updateBatteryStatus(battery) {
            document.querySelector('#battery-level').textContent = battery.level * 100 + '%';
            document.querySelector('#battery-status').textContent = battery.charging ? '正在充電' : '未充電';
        }
    </script>
</body>
</html>

這個例子展示瞭如何使用Web Battery API來獲取電池的狀態資訊,並在頁面上顯示當前電量和電池狀態。

在這個例子中,我們使用了navigator.getBattery()方法來獲取電池資訊,並使用battery.addEventListener()方法來監聽電池資訊變化。最後,我們使用updateBatteryStatus()函式來更新電量資訊並在頁面上顯示。

Web Share API(分享)

以下是一個簡單的Web Share API例子:

// 獲取分享按鈕元素
const shareButton = document.querySelector('#share-button');

// 新增點選事件監聽器
shareButton.addEventListener('click', async () => {
  try {
    // 檢查瀏覽器是否支援Web Share API
    if (navigator.share) {
      // 呼叫Web Share API分享
      await navigator.share({
        title: '分享標題',
        text: '分享描述',
        url: '分享連結'
      });
    } else {
      // 如果不支援,顯示提示資訊
      alert('該瀏覽器不支援Web Share API');
    }
  } catch (error) {
    // 處理異常情況
    console.error('分享失敗:', error);
  }
});

這個例子假設頁面中有一個id為share-button的分享按鈕元素。當使用者點選該按鈕時,程式碼會檢查瀏覽器是否支援Web Share API,如果支援則呼叫該API進行分享,否則顯示一個提示資訊。

navigator.share方法中,我們可以傳遞一個包含titletexturl等屬性的物件,用於指定分享內容的標題、描述和連結。如果使用者選擇分享,系統會彈出一個分享對話方塊,讓使用者選擇分享方式(例如透過社交媒體、電子郵件等方式分享)。

如果使用者取消分享,則navigator.share方法會返回一個Promise物件,其狀態為rejected。我們可以透過捕獲該Promise物件的異常來處理分享失敗的情況。

ImageCapture API(圖片抓取)

以下提供一個基本的Web ImageCapture API示例,如下所示:

HTML程式碼:

<!DOCTYPE html>
<html>
  <head>
    <title>Web ImageCapture API Demo</title>
  </head>
  <body>
    <h1>Web ImageCapture API Demo</h1>
    <video id="video" width="640" height="480" autoplay></video>
    <br>
    <button id="capture-btn">Capture Image</button>
    <br>
    <canvas id="canvas" width="640" height="480"></canvas>
    <br>
    <img id="captured-img">
  </body>
</html>

JavaScript程式碼:

// 獲取影片和按鈕元素
const video = document.getElementById('video');
const captureBtn = document.getElementById('capture-btn');

// 獲取畫布和影像元素
const canvas = document.getElementById('canvas');
const img = document.getElementById('captured-img');

// 獲取影片流
navigator.mediaDevices.getUserMedia({ video: true })
  .then(stream => {
    video.srcObject = stream;
    video.play();
  })
  .catch(error => {
    console.log(error);
  });

// 設定ImageCapture
let imageCapture;
const track = video.srcObject.getVideoTracks()[0];
imageCapture = new ImageCapture(track);

// 新增事件監聽器
captureBtn.addEventListener('click', () => {
  // 拍照
  imageCapture.takePhoto()
    .then(blob => {
      // 將照片顯示在畫布上
      const url = URL.createObjectURL(blob);
      canvas.getContext('2d').drawImage(img, 0, 0);
      
      // 將照片顯示在影像元素中
      img.src = url;
    })
    .catch(error => {
      console.log(error);
    });
});

這個示例將顯示一個影片元素和一個“Capture Image”按鈕。當使用者點選按鈕時,它將使用ImageCapture API拍攝照片,並在畫布和影像元素中顯示照片。

請注意,此示例僅適用於支援MediaStreamTrack和ImageCapture API的瀏覽器。

Selection API(文字選區)

下面是一個Web Selection API的例子,如下所示:

HTML程式碼:

<!DOCTYPE html>
<html>
<head>
    <title>Web Selection API Example</title>
    <style>
        .highlight {
            background-color: yellow;
        }
    </style>
</head>
<body>
    <h1>Web Selection API Example</h1>
    <p>Select text in the paragraph below to see the API in action.</p>
    <p id="demo">The Web Selection API allows you to retrieve and manipulate text selections made by the user.</p>
</body>
</html>

JavaScript程式碼(web-selection-api.js):

// 獲取文字節點
const demoEl = document.getElementById('demo');

// 監聽文字節點的選擇事件
demoEl.addEventListener('mouseup', handleSelection);

// 處理選擇事件
function handleSelection() {
    // 獲取使用者選擇的文字
    const selection = window.getSelection();
    const selectedText = selection.toString();
    // 如果選擇的文字不為空
    if (selectedText) {
        // 建立一個新的高亮節點
        const highlightEl = document.createElement('span');
        highlightEl.classList.add('highlight');

        // 將高亮節點插入到選擇範圍中
        const range = selection.getRangeAt(0);
        range.surroundContents(highlightEl);

        // 取消選擇
        selection.removeAllRanges();
    }
}

這個例子演示瞭如何使用Web Selection API來獲取使用者選擇的文字,並將其高亮顯示。

當使用者在頁面上選擇文字時,會觸發mouseup事件,然後呼叫handleSelection函式來處理選擇事件。

handleSelection函式中,我們首先使用window.getSelection()方法獲取使用者選擇的文字,然後檢查是否選擇了文字。

如果選擇了文字,我們建立一個新的span元素,並將其新增到選擇範圍中,然後使用removeAllRanges()方法取消選擇。最後,我們使用CSS樣式將高亮顯示的文字突出顯示。

Performance API(效能檢測)

以下是一個使用 Web Performance API 的例子:

// 測量頁面載入時間
const startTime = window.performance.now();

window.addEventListener('load', () => {
  const loadTime = window.performance.now() - startTime;
  console.log(`頁面載入時間為:${loadTime} 毫秒`);
});

// 測量網路時間
const resourceUrl = 'https://example.com/resource';

fetch(resourceUrl)
  .then(response => {
    const fetchTime = window.performance.now() - startTime;
    console.log(`請求時間為:${fetchTime} 毫秒`);

    // 獲取網路時間資訊
    const entry = performance.getEntriesByName(resourceUrl)[0];
    const start = entry.fetchStart;
    const end = entry.responseEnd;

    console.log(`DNS 查詢時間為:${entry.domainLookupEnd - entry.domainLookupStart} 毫秒`);
    console.log(`TCP 握手時間為:${entry.connectEnd - entry.connectStart} 毫秒`);
    console.log(`TLS 握手時間為:${entry.secureConnectionStart ? entry.connectEnd - entry.secureConnectionStart : 'N/A'} 毫秒`);
    console.log(`請求時間為:${entry.responseStart - entry.requestStart} 毫秒`);
    console.log(`響應時間為:${entry.responseEnd - entry.responseStart} 毫秒`);
    console.log(`傳輸大小為:${entry.transferSize} 位元組`);
  });

在這個例子中,我們使用了 Web Performance API 提供的 performance 物件來測量頁面載入時間和使用 fetch() 方法獲取資源的網路時間。我們還使用了 getEntriesByName() 方法來檢索資源的網路時間資訊。

Geolocation API(獲取位置)

以下是一個使用 Geolocation API 獲取使用者當前位置資訊的示例程式碼:

// 檢查瀏覽器是否支援 Geolocation API
if ('geolocation' in navigator) {
  // 獲取使用者當前位置資訊
  navigator.geolocation.getCurrentPosition(
    (position) => {
      const { latitude, longitude } = position.coords;
      console.log(`您的緯度為:${latitude},經度為:${longitude}`);
    },
    (error) => {
      switch (error.code) {
        case error.PERMISSION_DENIED:
          console.log('使用者拒絕了位置請求');
          break;
        case error.POSITION_UNAVAILABLE:
          console.log('無法獲取位置資訊');
          break;
        case error.TIMEOUT:
          console.log('請求超時');
          break;
        default:
          console.log('發生未知錯誤');
      }
    }
  );
} else {
  console.log('您的瀏覽器不支援 Geolocation API');
}

在這個例子中,我們首先檢查瀏覽器是否支援 Geolocation API

如果支援,則呼叫 navigator.geolocation.getCurrentPosition() 方法獲取使用者當前位置資訊。該方法接受兩個回撥函式作為引數:一個成功的回撥函式和一個失敗的回撥函式。

如果獲取位置資訊成功,則成功的回撥函式將被呼叫,並傳遞包含位置資訊的物件作為引數。否則將呼叫失敗的回撥函式,並傳遞一個描述錯誤的物件作為引數。

Broadcast Channel API(跨頁面通訊)

下面是一個使用 Broadcast Channel API 實現簡單的跨視窗通訊的例子:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Broadcast Channel API Example</title>
  </head>
  <body>
    <div id="message"></div>
    <input type="text" id="input-message">
    <button onclick="sendMessage()">Send Message</button>

    <script>
      const channel = new BroadcastChannel('my-channel'); // 建立一個廣播通道物件

      function sendMessage() {
        const inputMessage = document.getElementById('input-message');
        const message = inputMessage.value;
        channel.postMessage(message); // 將訊息傳送到廣播通道中
        inputMessage.value = ''; // 清空輸入框內容
      }

      channel.onmessage = (event) => {
        const message = event.data;
        const messageDiv = document.getElementById('message');
        messageDiv.innerHTML = message;
      }
    </script>
  </body>
</html>

上面的例子展示瞭如何使用 Broadcast Channel API 實現在兩個視窗之間進行文字訊息的雙向通訊。

在 HTML 中,我們定義了一個輸入框和一個按鈕,用於輸入和傳送訊息。我們還定義了一個 div 元素,用於展示接收到的訊息。

在 JavaScript 中,我們建立了一個名為 my-channel 的廣播通道物件,並定義了一個 sendMessage 函式,該函式將輸入框中的文字訊息傳送到廣播通道中。

同時,我們在 channel 物件上透過 onmessage 方法監聽廣播通道上的訊息,一旦有訊息傳送到該通道,就會觸發該方法,在該方法中將接收到的訊息展示在 div 元素中。

需要注意的是,廣播通道的名字需要保持一致,才能實現不同視窗之間的通訊。

Vibration API(裝置振動)

以下是一個簡單的Web Vibration API例子:

<!DOCTYPE html>
<html>
<head>
    <title>Web Vibration API Example</title>
</head>
<body>
    <h1>Web Vibration API Example</h1>
    <button onclick="vibrate()">Vibrate</button>
    <script>
        function vibrate() {
            if ("vibrate" in navigator) {
                navigator.vibrate(1000); // 1秒鐘的震動
            } else {
                alert("Vibration API not supported in this browser.");
            }
        }
    </script>
</body>
</html>

這個例子中,當使用者點選"Vibrate"按鈕時,瀏覽器會嘗試透過Web Vibration API來觸發裝置的震動功能。

如果裝置支援Web Vibration API,則會進行1秒鐘的震動,否則會彈出一個警告框提示使用者該功能不被支援。

Srceen Capture API(影片截圖)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Web Screen Capture API Example</title>
</head>
<body>
    <h1>Web Screen Capture API Example</h1>

    <button id="start-capture">Start Capture</button>
    <button id="stop-capture">Stop Capture</button>

    <canvas id="canvas" width="640" height="480"></canvas>

    <script>
        // 獲取DOM元素
        const startCaptureBtn = document.getElementById('start-capture');
        const stopCaptureBtn = document.getElementById('stop-capture');
        const canvas = document.getElementById('canvas');

        // 獲取媒體流(螢幕共享)並將其渲染到canvas中
        async function startCapture() {
            try {
                const mediaStream = await navigator.mediaDevices.getDisplayMedia();
                const context = canvas.getContext('2d');
                context.drawImage(video, 0, 0, canvas.width, canvas.height);
            } catch(err) {
                console.error("Error: " + err);
            }
        }

        // 停止捕獲並停止媒體流
        function stopCapture() {
            const tracks = mediaStream.getTracks();
            tracks.forEach(track => track.stop());
        }

        // 註冊按鈕單擊事件
        startCaptureBtn.addEventListener('click', startCapture);
        stopCaptureBtn.addEventListener('click', stopCapture);
    </script>
</body>
</html>

這個例子中,頁面上有兩個按鈕,一個用於開始捕獲螢幕,另一個用於停止捕獲。捕獲的內容被呈現在一個畫布上。

startCapture() 函式中,我們使用 navigator.mediaDevices.getDisplayMedia() 方法獲取螢幕共享的媒體流,並將其渲染到canvas上。在 stopCapture() 函式中,我們停止所有媒體流的所有軌道,以結束捕獲過程。

Intersection Observer API(元素監聽)

以下是一個示例,演示瞭如何使用 Intersection Observer API 在元素進入視口時進行檢測:

<!DOCTYPE html>
<html>
  <head>
    <title>Intersection Observer Example</title>
    <style>
      .box {
        width: 100px;
        height: 100px;
        background-color: green;
        margin-bottom: 50px;
      }
      .visible {
        background-color: red;
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>

    <script>
      const boxes = document.querySelectorAll('.box');

      const options = {
        rootMargin: '0px',
        threshold: 0.5
      };

      const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            entry.target.classList.add('visible');
          } else {
            entry.target.classList.remove('visible');
          }
        });
      }, options);

      boxes.forEach(box => {
        observer.observe(box);
      });
    </script>
  </body>
</html>

在這個示例中,我們首先選擇所有具有“box”類的元素。然後,我們建立一個帶有0畫素的rootMargin和0.5的閾值的IntersectionObserver例項。這意味著當元素的50%位於視口內時,它將被視為可見。

然後,我們迴圈遍歷每個盒子元素,並在我們的觀察者例項上呼叫observe方法,將盒子元素作為引數傳遞。

最後,在IntersectionObserver例項的回撥函式中,我們檢查每個條目是否與視口相交。如果是,則將“visible”類新增到條目的目標元素中,否則將其刪除。

參考

  1. web-api-examples
  2. MDN-Web APIs
  3. 12 Rarely Used JavaScript Web APIs that Will Boost Your Website to THE MOON
  4. 7 JavaScript Web APIs to build Futuristic Websites you didn't know
  5. 你(可能)不知道的 web api

最後附上我的部落格地址————九旬的部落格,歡迎?Star?。

相關文章