首頁  >  文章  >  web前端  >  詳解用SVG為 favicon 新增標識

詳解用SVG為 favicon 新增標識

青灯夜游
青灯夜游轉載
2022-09-07 10:30:161769瀏覽

怎麼使用SVG為 favicon 新增標識?以下這篇文章為大家介紹一下使用 SVG 產生帶有標識的 favicon的方法,希望對大家有幫助!

之前做了一個Chrome 插件,可以根據地址的不同生成不同的圖標,這樣可以很方便的區分不同的開發環境,效果如下

主要實作過程其實不複雜,先取得網站favicon,然後給favicon 加入標識,重新繪製生成就行了

##其中,這裡的圖示就是透過SVG 產生的,下面來看看具體實現吧。 【推薦學習:

css影片教學

一、favicon 的取得方式

想知道取得方式,可以先了解設定方式。

一般有兩種方式可以設定網站的

favicon

第一種,透過

link 標籤設定(需要rel="icon"屬性)

<link>
第二種,直接在

網站根目錄放一張favicon.ico(必須是這個名稱,瀏覽器預設的),html 中什麼也不用設定

- 网站目录
    index.html
    favicon.ico
如果以上都沒有設置,那麼大機率會看到以下錯誤

了解這些,獲取就簡單了,先透過

link獲取,只要rel#包含icon就行了

const link = document.querySelector('link[rel~="icon"]');
如果找不到,可以請求

/favicon.ico,這裡直接加入一個link

function getLink(){
    const link = document.querySelector('link[rel~="icon"]');
    if (link) {
        return link
    } else {
        const link = document.createElement('link');
        link.rel = "icon";
        link.href = "/favicon.ico"
        document.head.append(link);
        return link
    }
}
這樣取得的

link就保證存在了,然後就是繪製

二、利用canvas 來繪製##因為需要合成影像,所以需要先繪製原有影像。提到影像繪製,可以想到 canvas 繪製,只需要一點點 canvas 基礎知識就足夠了。具體實作如下

const canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
詳解用SVG為 favicon 新增標識 = new Image();
詳解用SVG為 favicon 新增標識.crossOrigin = 'anonymous';
詳解用SVG為 favicon 新增標識.onload = () => {
    canvas.height = 詳解用SVG為 favicon 新增標識.height;
    canvas.width = 詳解用SVG為 favicon 新增標識.width;
    ctx.drawImage(詳解用SVG為 favicon 新增標識, 0, 0, canvas.width, canvas.height);
    let dataURL = canvas.toDataURL("image/png");
    resolve(dataURL);
    canvas = null;
};
詳解用SVG為 favicon 新增標識.src = url;

由於存在

/favicon.ico

沒有設定的情況,所以需要在詳解用SVG為 favicon 新增標識 載入失敗的時候給一張預設圖<pre class="brush:php;toolbar:false">詳解用SVG為 favicon 新增標識.onerror = () =&gt; {     resolve(&quot;默认图base64&quot;); }</pre>這樣就能取得到favicon 的圖像資訊了

三、利用SVG 進行圖片合成

在上面的基礎上,其實可以繼續透過canvas 進行繪製,再繪製一個標籤也不是難事。不過這裡可以採用SVG 的方式來進行繪製,有以下一些優點

    成本更低,比canvas 更易理解
  • ##彈性高,可以透過CSS 進行一些樣式控制
  • 首先,我們可以在HTML 中自由的、像正常網頁開發一樣,繪製這樣一個佈局,相信沒有什麼難度

#
  <strong>local</strong>
  

由於寬度有限,所以需要強製文字換行,超出隱藏,關鍵樣式如下

strong{
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  text-transform: uppercase;
  background-color: orange;
  color: #fff;
  padding: 0px 2px;
  border-radius: 2px;
  font-size: 12px;
  box-sizing: border-box;
  max-width: 100%;
  width: max-content;
  height: 16px;
  line-height: 16px;
  word-break: break-all;
  overflow: hidden;
}
接著,將這一段html 放入

foreignObject

#標籤中,關於 foreignObject 的作用,有興趣的可以參考張鑫旭老師的這篇文章SVG 簡介與截圖等應用,在這裡,你可以簡單理解為是可以包含HTML 的標籤,而SVG 本身也是一種圖片,這樣就達到了合成圖像的目的

具體實作如下

const link = getLink();
const icon = await 詳解用SVG為 favicon 新增標識2Base64(link.href);
const favicon = `data:image/svg+xml;charset=utf-8,<svg><foreignobject>
  <style>
    html,body{
      height: 100%;
      margin: 0;
      text-align: center;
    }
    詳解用SVG為 favicon 新增標識{
      display: block;
      width: 100%;
      height: 100%;
      object-fit: contain;
    }
    strong{
      position: absolute;
      bottom: 0;
      left: 50%;
      transform: translateX(-50%);
      text-transform: uppercase;
      background-color: ${color};
      color: #fff;
      padding: 0px 2px;
      border-radius: 2px;
      font-size: 12px;
      box-sizing: border-box;
      max-width: 100%;
      width: max-content;
      height: 16px;
      line-height: 16px;
      word-break: break-all;
      overflow: hidden;
    }
  </style>
  <strong>local</strong>
  詳解用SVG為 favicon 新增標識>
  </foreignobject></svg>`.replace(/\n/g, '').replace(/\t/g, '').replace(/#/g, '%23')
這裡需要注意幾點

##詳解用SVG為 favicon 新增標識 標籤在svg 中需要寫成

詳解用SVG為 favicon 新增標識>
    閉合形態,不然會被認為結構錯誤
  • 詳解用SVG為 favicon 新增標識 只能使用內聯圖片,例如base64,這也是為何繪製原始favicon 的原因

  • 如果使用內聯svg,需要對svg 進行轉義

  • 字串中的單雙引號問題也需要注意一下

  • 然後,將產生的SVG 直接設定為favicon

    link.href= favicon;

這樣就能正常的渲染了~

完整實作可以參考項目:https://github.com/XboxYan/auto-dev-favicon-chrome-plugin

四、一些局限性

首先是兼容性。

目前只有 Chrome 和 Firefox 是支持的,为了兼容其他浏览器,可以用一个 .ico来兜底

<link>
<link>

另外,在 Chrome 上还有一个限制(不知道是不是Chrome 更新后的限制),当 favicon 使用 svg 格式图片时,此时的 svg 会处于一种secure-static-mode,在这种模式下,所有动画都不会执行,会处于第一帧,比如下面这个例子

<svg>
  <foreignobject>
      
        <style>
        html,body{
            margin: 0;
            height: 100%
        }
        div{
            height: 100%;
            background: pink;
            animation: hue 3s infinite;
        }
        @keyframes hue {
            to {
                filter: hue-rotate(360deg)
            }
        }
        </style>
        <div></div>
      
    </foreignobject>
</svg>

很简单的一个背景颜色动画。在 Firefox 上是用作 favicon 是有动画的

但是,Chrome 上却不行,只有禁止的第一帧

所以之前想实现标识文本滚动的效果可以就此打住了

比较类似的还有媒体查询,之前在网上看到有这样的实现,直接在 SVG 中实现黑暗模式

<svg>
    <style>
        path {
            fill: #fff;
        }
        rect {
            fill: #B09AFE;
        }
        @media (prefers-color-scheme: dark) {
            path {
                fill: #B09AFE;
            }
            rect {
                fill: #fff;
            }
        }
    </style>
    <rect></rect>
    <path></path>
</svg>

但是也是同样的问题,只有 Firefox 下可行,Chrome是静止不动的

总的来说,SVG 在绘制方面提供了无限可能,不仅仅是本文中的案例,觉得 canvas 过于复杂的都可以考虑这一方案

(学习视频分享:web前端

以上是詳解用SVG為 favicon 新增標識的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除