iT邦幫忙

2025 iThome 鐵人賽

DAY 13
4
Modern Web

從 Canvas 到各式各樣的 Web API 之旅系列 第 13

Day 13 - Web Share API 用原生分享面板把網頁變得像 App

  • 分享至 

  • xImage
  •  

Day 13 - Web Share API 用原生分享面板把網頁變得像 App

把網頁變得像手機 App 的關鍵一步,就是呼叫系統「原生分享面板」! 📤 🔗
這篇會帶你用 Web Share 分享連結、檔案、Canvas 截圖,行動裝置支援最好,桌機則是逐年進步!


Web Share API(原生分享面板)

  • navigator.share(data):呼叫系統原生分享面板。data 可帶 titletexturlfiles
  • navigator.canShare({ files }):檢查是否支援分享檔案(含大小/型別等條件)。

1) 分享連結/文字

連結/文字分享只需檢查 navigator.share 是否存在;不要navigator.canShare 來判斷這種情況。

分享連結:文字

<button id="btnShare">Share</button>

<script>
  document.getElementById('btnShare').addEventListener('click', async () => {
    if (!navigator.share) {
        alert('此裝置/瀏覽器不支援 Web Share');
        return;
    }
      
    try {
      await navigator.share({
        title: document.title,
        text: '看看這頁',
        url: location.href
      });
    } catch (e) {
        /* 使用者取消不算錯 */
    }
  });
</script>

2) 分享檔案

檔案分享在平台/瀏覽器上限制較多(容量、型別、來源),所以先用 navigator.canShare({ files }) 檢查。

分享檔案

<input type="file" id="fileInput" multiple />
<button id="btnShareFiles">Share selected files</button>

<script>
  const picker = document.getElementById('fileInput');
    
  document.getElementById('btnShareFiles').addEventListener('click', async () => {
    const files = Array.from(picker.files || []);
      
    if (!files.length) return alert('請先選檔');

    if (navigator.canShare && navigator.canShare({ files })) {
      try {
          await navigator.share({ files, title: '檔案分享' });
      }
      catch (e) {
          /* 使用者取消 */
      }
    } else {
      alert('此裝置/瀏覽器暫不支援分享檔案');
    }
  });
</script>

3) 分享 Canvas 截圖(Canvas → PNG 檔案)

分享 Canvas 截圖

<canvas id="cv" width="160" height="90"></canvas>
<button id="btnShareCanvas">Share Canvas</button>

<script>
  const cv = document.getElementById('cv');
  const ctx = cv.getContext('2d');
  ctx.fillStyle = '#09f';
  ctx.fillRect(0,0,160,90); // 畫點東西

  document.getElementById('btnShareCanvas').addEventListener('click', async () => {
    const blob = await new Promise(r => cv.toBlob(r, 'image/png'));
    const file = new File([blob], 'screenshot.png', { type: 'image/png' });

    if (navigator.canShare && navigator.canShare({ files: [file] })) {
      try {
          await navigator.share({ files: [file], title: 'Canvas Screenshot' });
      }
      catch (e) {
          /* 使用者取消 */
      }
    } else {
      // Fallback:下載檔案
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = 'screenshot.png';
      a.click();
      URL.revokeObjectURL(a.href);
    }
  });
</script>

4) Fallback:不支援 share 時(複製連結為主)

<button id="btnShareFallback">Share (with fallback)</button>
<script>
  const fallbackShare = async () => {
    const url = location.href;
    try {
        await navigator.clipboard.writeText(url);
        alert('已複製連結');
    }
    catch {
        prompt('請手動複製以下連結', url);
    }
  };

  document.getElementById('btnShareFallback').addEventListener('click', async () => {
    if (navigator.share) {
      try {
          await navigator.share({ title: document.title, url: location.href });
          return;
      }
      catch (e) {
          /* 取消則走 fallback */
      }
    }
    await fallbackShare();
  });
</script>

注意事項(與前兩節一致的心法)

  • HTTPS / localhost 幾乎是必須;很多瀏覽器會在非安全環境中關閉功能。
  • 使用者手勢(click/tap)為必要條件;不要在載入時自動呼叫 share()
  • 行動裝置支援最佳;桌機支援逐年提升,但仍有差異。
  • 分享檔案前要先 navigator.canShare({ files });不支援就走 Copy Link / 下載 的替代路徑。
  • 與 Clipboard 節點配合:不支援 share → 複製連結 是最普適的退路。

範例 Demo

上面用簡單程式碼示範了「分享連結、檔案、Canvas 截圖」的基本流程。
想直接體驗完整互動,請看這個線上範例(本文截圖也來自這裡):

Web Share


👉 歡迎追蹤這個系列,我會從 Canvas 開始,一步步帶你認識更多 Web API 🎯


上一篇
Day 12 - 用 Fullscreen API、Clipboard API 打造沉浸展示與一鍵複製
下一篇
Day 14 - 用 Screen Orientation、Wake Lock、Vibration API 讓網頁控制螢幕方向、保持常亮與震動
系列文
從 Canvas 到各式各樣的 Web API 之旅15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言