Cách tạo huy hiệu ứng dụng

Huy hiệu được dùng để truyền tải thông tin không khẩn cấp cho người dùng. Ví dụ: chúng được dùng để cho biết trạng thái của một ứng dụng hoặc số lượng mục chưa đọc. Cách tạo huy hiệu ứng dụng theo kiểu truyền thống là thêm một số vào biểu tượng trang web. Trên các trình duyệt hiện đại, sau khi cài đặt một ứng dụng, sẽ có một cách thức tích hợp để thêm huy hiệu vào biểu tượng ứng dụng trong thanh tác vụ của hệ điều hành.

Cách làm hiện đại

Sử dụng phương thức navigator.setAppBadge()

Phương thức navigator.setAppBadge() đặt một huy hiệu trên biểu tượng được liên kết với ứng dụng cần cài đặt. Phương thức này có một đối số duy nhất không bắt buộc, đó là một số nguyên sẽ được dùng làm giá trị của huy hiệu. Khi bạn đặt số này thành 0, huy hiệu ứng dụng sẽ bị xoá. Nếu không cung cấp đối số, bạn sẽ nhận được một huy hiệu chung, thường hiển thị dưới dạng một dấu chấm có màu.

Biểu tượng ứng dụng cho thấy biểu tượng thực tế có số 3 là giá trị huy hiệu.

Browser Support

  • Chrome: 81.
  • Edge: 81.
  • Firefox: not supported.
  • Safari: 17.

Source

Cách cổ điển

Thêm số vào biểu tượng trang web

Nếu chưa cài đặt ứng dụng, bạn có thể thêm một số vào biểu tượng trang web. Có nhiều cách để làm việc này, chẳng hạn như bằng cách vẽ biểu tượng trang web một cách linh hoạt vào một canvas có thêm thông tin về huy hiệu và hiển thị biểu tượng đó dưới dạng URL Blob, hoặc tạo một hình ảnh SVG có thông tin về huy hiệu dưới dạng URL dữ liệu.

Favicon cho thấy biểu tượng thực tế với số 5 là giá trị huy hiệu.

Cải tiến tăng dần

Đoạn mã dưới đây sử dụng một phần tử tuỳ chỉnh <favicon-badge></favicon-badge> cho phép nhà phát triển khai báo đặt huy hiệu trên biểu tượng trang web được chỉ định thông qua thuộc tính src bằng cách truyền một số nguyên vào thuộc tính badge. Khi người dùng cài đặt ứng dụng, huy hiệu sẽ được "nâng cấp" thành huy hiệu hệ điều hành gốc.

import 'https://unpkg.com/favicon-badge@2.0.0/dist/FavIconBadge.js';

// DOM references.
const favicon = document.querySelector('favicon-badge');
const installButton = document.querySelector('button');

// Feature detection.
const supportsAppBadge = 'setAppBadge' in navigator;

let setAppBadge;

// For the demo simply set the badge between [0, 9].
let i = 0;
const getAppBadgeValue = () => {
  if (i > 9) {
    i = 0;
  }
  return i++;
};

// Set the badge on the favicon.
const setAppBadgeFavicon = (value) => {
  favicon.badge = value;
};

// Set the native operating system badge.
const setAppBadgeNative = (value) => {
  navigator.setAppBadge(value);
}

// If the app is installed and the Badging API is supported,
// set the badge on the native operating system. Else, fall
// back to the favicon.
if (
  matchMedia('(display-mode: standalone)').matches &&
  supportsAppBadge
) {
  setAppBadge = setAppBadgeNative;
} else {
  setAppBadge = setAppBadgeFavicon;
}

// Set a new badge every second.
setInterval(() => {
  setAppBadge(getAppBadgeValue());
}, 1000);

// If installation is supported…
if ('BeforeInstallPromptEvent' in window) {
  let installEvent = null;
  const onInstall = () => {
    // After installation, "upgrade" to the native operating system badge.
    installButton.disabled = true;
    installEvent = null;
    if (supportsAppBadge) {
      favicon.badge = false;
      setAppBadge = setAppBadgeNative;
    }
  };

  // …listen for the `beforeinstallprompt` event.
  window.addEventListener('beforeinstallprompt', (event) => {
    event.preventDefault();
    installEvent = event;
    installButton.disabled = false;
  });

  // Deal with installation.
  installButton.addEventListener('click', async () => {
    if (!installEvent) {
      return;
    }
    installEvent.prompt();
    const result = await installEvent.userChoice;
    if (result.outcome === 'accepted') {
      onInstall();
    }
  });

  // Listen for the `appinstalled` in case the user installs the app manually.
  window.addEventListener('appinstalled', (event) => {
    onInstall();
  });
}

Tài liệu đọc thêm

Bản minh hoạ

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="manifest" href="manifest.json" />
    <title>How to create an app badge</title>
    <link rel="stylesheet" href="style.css" />
    <!-- TODO: Devsite - Removed inline handlers -->
    <!-- <script>
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', async () => {
          const registration = await navigator.serviceWorker.register(
            'sw.js',
          );
          console.log(
            'Service worker registered for scope',
            registration.scope,
          );
        });
      }
    </script>
    <script src="script.js" type="module"></script> -->
  </head>
  <body>
    <h1>How to create an app badge</h1>
    <ol>
      <li>
        Watch the favicon. You should see a counter that updates each second
        integrated into the favicon.
        <img
          src="../favicon.png"
          style="width: 250px; height: auto"
          width="528"
          height="74"
          alt="Favicon with counter."
        />
      </li>
      <li>
        Install the app by clicking the button below. After the installation,
        the button is disabled.
        <p>
          <button disabled type="button">Install</button>
        </p>
      </li>
      <li>
        Watch the app icon in your operating system's task bar. You should see a
        counter that updates each second as an app badge.
        <img
          src="../app-badge.png"
          style="width: 80px; height: auto"
          width="282"
          height="388"
          alt="App badge with counter."
        />
      </li>
    </ol>
    <favicon-badge src="../favicon.svg" textColor="#fff" badge="" />
  </body>
</html>

CSS


        html {
  box-sizing: border-box;
  font-family: system-ui, sans-serif;
  color-scheme: dark light;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body {
  margin: 1rem;
}

img {
  height: auto;
  max-width: 100%;
  display: block;
}
        

JS


        import 'https://unpkg.com/favicon-badge@2.0.0/dist/FavIconBadge.js';

// The `` custom element.
const favicon = document.querySelector('favicon-badge');
// The install button.
const installButton = document.querySelector('button');

// Feature detection.
const supportsAppBadge = 'setAppBadge' in navigator;

// This function will either set the favicon or the native
// app badge. The implementation is dynamically changed at runtime.
let setAppBadge;

// Variable for the counter.
let i = 0;

// Returns a value between 0 and 9.
const getAppBadgeValue = () => {
  if (i > 9) {
    i = 0;
  }
  return i++;
};

// Function to set a favicon badge.
const setAppBadgeFavicon = (value) => {
  favicon.badge = value;
};

// Function to set a native app badge.
const setAppBadgeNative = (value) => {
  navigator.setAppBadge(value);
}

// If the app is installed and native app badges are supported,
// use the native app badge.
if (
  matchMedia('(display-mode: standalone)').matches &&
  supportsAppBadge
) {
  setAppBadge = setAppBadgeNative;
// In all other cases (i.e., if the app is not installed or native
//  app badges are not supported), use the favicon badge.
} else {
  setAppBadge = setAppBadgeFavicon;
}

// Update the badge every second.
setInterval(() => {
  setAppBadge(getAppBadgeValue());
}, 1000);

// Only relevant for browsers that support installation.
if ('BeforeInstallPromptEvent' in window) {
  // Variable to stash the `BeforeInstallPromptEvent`.
  let installEvent = null;

  // Function that will be run when the app is installed.
  const onInstall = () => {
    // Disable the install button.
    installButton.disabled = true;
    // No longer needed.
    installEvent = null;

    if (supportsAppBadge) {
      // Remove the favicon badge.
      favicon.badge = false;
      // Switch the implementation so it uses the native
      // app badge.
      setAppBadge = setAppBadgeNative;
    }
  };

  window.addEventListener('beforeinstallprompt', (event) => {
    // Do not show the install prompt quite yet.
    event.preventDefault();
    // Stash the `BeforeInstallPromptEvent` for later.
    installEvent = event;
    // Enable the install button.
    installButton.disabled = false;
  });

  installButton.addEventListener('click', async () => {
    // If there is no stashed `BeforeInstallPromptEvent`, return.
    if (!installEvent) {
      return;
    }
    // Use the stashed `BeforeInstallPromptEvent` to prompt the user.
    installEvent.prompt();
    const result = await installEvent.userChoice;
    // If the user installs the app, run `onInstall()`.
    if (result.outcome === 'accepted') {
      onInstall();
    }
  });

  // The user can decide to ignore the install button
  // and just use the browser prompt directly. In this case
  // likewise run `onInstall()`.
  window.addEventListener('appinstalled', (event) => {
    onInstall();
  });
}