| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- // Favicon 工具函数
- /** 使用 URL 更新 favicon(如恢复默认) */
- export function updateFavicon(url: string) {
- const link = document.querySelector("link[rel*='icon']") as HTMLLinkElement;
- if (link) {
- link.href = url;
- } else {
- const newLink = document.createElement("link");
- newLink.rel = "icon";
- newLink.href = url;
- document.head.appendChild(newLink);
- }
- }
- /** 移除动态 favicon,恢复为默认(需页面存在 link[rel=icon] 指向默认图标) */
- export function removeFavicon() {
- const link = document.querySelector("link[rel*='icon']") as HTMLLinkElement;
- if (link) {
- link.remove();
- }
- }
- const DEFAULT_FAVICON = "/favicon.ico";
- /** 用 Canvas 绘制红底白字数字徽章,并设为 favicon(未读数 > 0 时使用) */
- export function updateFaviconWithBadge(count: number) {
- if (count <= 0) {
- updateFavicon(DEFAULT_FAVICON);
- return;
- }
- const size = 64;
- const canvas = document.createElement("canvas");
- canvas.width = size;
- canvas.height = size;
- const ctx = canvas.getContext("2d");
- if (!ctx) return;
- const text = count > 99 ? "99+" : String(count);
- const fontSize = text.length >= 2 ? 16 : 18;
- const radius = text.length >= 2 ? 14 : 12;
- const cx = size - radius - 4;
- const cy = radius + 4;
- ctx.clearRect(0, 0, size, size);
- ctx.beginPath();
- ctx.arc(cx, cy, radius, 0, Math.PI * 2);
- ctx.fillStyle = "#dc2626";
- ctx.fill();
- ctx.strokeStyle = "#fff";
- ctx.lineWidth = 2;
- ctx.stroke();
- ctx.fillStyle = "#fff";
- ctx.font = `bold ${fontSize}px system-ui, sans-serif`;
- ctx.textAlign = "center";
- ctx.textBaseline = "middle";
- ctx.fillText(text, cx, cy);
- const dataUrl = canvas.toDataURL("image/png");
- updateFavicon(dataUrl);
- }
- export { DEFAULT_FAVICON };
|