Welcome to my public account: front-end detective
I made a Chrome plug-in before, which can generate different icons according to different addresses, which can easily distinguish different development environments. The effect is as follows
The main implementation process is actually not complicated. First, get the website favicon, then add a logo to the favicon, and redraw the generation.
Among them, the icons here are generated by SVG, let's take a look at the specific implementation.
1. How to get favicon
If you want to know how to get it, you can first understand how to set it up.
There are generally two ways to set the website favicon
.
The first one is set by the link
tag (requires rel="icon"
attribute)
<link rel="icon" href="xxx.png">
The second is to put a favicon.ico
directly in the root directory of the website (must be this name, the browser defaults), nothing in html needs to be set
- 网站目录
index.html
favicon.ico
If none of the above are set, you will most likely see the following errors
Knowing these, the acquisition is simple, first get it through link
, as long as rel
include icon
const link = document.querySelector('link[rel~="icon"]');
If you can't find it, you can request /favicon.ico
, and add a 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
}
}
Obtained in this way link
is guaranteed to exist, and then draws
2. Drawing using canvas
Since the image needs to be composited, the original image needs to be drawn first. When it comes to image drawing, you can think of canvas drawing, and only a little canvas basic knowledge is enough. The specific implementation is as follows
const canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => {
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
let dataURL = canvas.toDataURL("image/png");
resolve(dataURL);
canvas = null;
};
img.src = url;
Since there is a situation where /favicon.ico
is not set, it is necessary to give a default image when img fails to load
img.onerror = () => {
resolve("默认图base64");
}
In this way, the image information of the favicon can be obtained.
3. Use SVG for image synthesis
On the basis of the above, in fact, you can continue to draw through canvas, and it is not difficult to draw a label. However, SVG can be used to draw here, which has the following advantages
- Lower cost and easier to understand than canvas
- High flexibility, some style control through CSS
First of all, we can draw such a layout freely in HTML, just like normal web development, I believe there is no difficulty
<body>
<strong>local</strong>
<img src='xxx.png'>
</body>
Due to the limited width, it is necessary to force the text to wrap, beyond the hidden, the key styles are as follows
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;
}
Next, put this piece of html into the foreignObject
tag. For the role of foreignObject , you can refer to this article by Mr. Zhang Xinxu, SVG introduction and screenshots, and other applications . Here, you can simply understand that it is HTML tags can be included, and SVG itself is also a kind of image, which achieves the purpose of synthesizing images
The specific implementation is as follows
const link = getLink();
const icon = await img2Base64(link.href);
const favicon = `data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32"><foreignObject x="0" y="0" width="100%" height="100%"><body xmlns="http://www.w3.org/1999/xhtml">
<style>
html,body{
height: 100%;
margin: 0;
text-align: center;
}
img{
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>
<img src='${icon}'></img>
</body></foreignObject></svg>`.replace(/\n/g, '').replace(/\t/g, '').replace(/#/g, '%23')
A few things to note here
- The img tag needs to be written as
<img></img>
closed form in svg, otherwise it will be considered as a structural error - img can only use inline images, such as base64, which is why the original favicon is drawn
- If you use inline svg, you need to escape the svg
- The problem of single and double quotation marks in strings also needs to be paid attention to
Then, set the resulting SVG directly as a favicon
link.href= favicon;
This will render it normally~
The complete implementation can refer to the project: https://github.com/XboxYan/auto-dev-favicon-chrome-plugin
4. Some limitations
The first is compatibility.
Currently only Chrome and Firefox are supported. In order to be compatible with other browsers, you can use one .ico
to get the bottom line
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
In addition, there is a limitation on Chrome (I don't know if it is a limitation after Chrome's update), when the favicon uses svg format images, the svg at this time will be in a secure-static-mode , in this mode, all The animation will not be executed, it will be in the first frame, such as the following example
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<foreignObject width="100%" height="100%">
<body xmlns="http://www.w3.org/1999/xhtml">
<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>
</body>
</foreignObject>
</svg>
A very simple background color animation. On Firefox is used as a favicon is animated
However, it doesn't work on Chrome, only the first frame is forbidden
So before I want to achieve the effect of scrolling the logo text, I can stop here 😭
Similar to media queries, I saw such an implementation on the Internet before, and the dark mode is directly implemented in SVG
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
path {
fill: #fff;
}
rect {
fill: #B09AFE;
}
@media (prefers-color-scheme: dark) {
path {
fill: #B09AFE;
}
rect {
fill: #fff;
}
}
</style>
<rect width="128" height="128" rx="64" fill="#B09AFE"/>
<path d="M32.375 37.5714H22C22 58.004 38.2596 74.5714 58.3125 74.5714V98.3571C58.3125 99.8107 59.4797 101 60.9062 101H66.0937C67.5203 101 68.6875 99.8107 68.6875 98.3571V74.5714C68.6875 54.1388 52.4279 37.5714 32.375 37.5714ZM94.625 27C80.9754 27 69.109 34.6808 62.9002 46.0286C67.3906 51.017 70.7139 57.079 72.4646 63.8018C90.7344 61.8692 105 46.1442 105 27H94.625Z" fill="white"/>
</svg>
But it's the same problem, only works under Firefox, Chrome is static
In general, SVG provides infinite possibilities for drawing, not just the case in this article. Anyone who thinks canvas is too complicated can consider this solution
Finally, if you think it's good and helpful to you, please like, bookmark, and forward ❤❤❤
Welcome to my public account: front-end detective
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。