jsx/tsx使用cssModule和typescript-plugin-css-modules
目录1,前言 2,效果图3,如何使用 3.1,安装 3.2,配置4,示例 5,插件错误处理 5.1,错误触发原因 5.2,解决办法1,前言 在vite/webpack搭建的项目中,不管是vue还是re
顺晟科技
2022-09-15 14:54:42
118
欢迎关注我的公众号:前端侦探
之前做了一个 Chrome 插件,可以根据地址的不同生成不同的图标,这样可以很方便的区分不同的开发环境,效果如下
主要实现过程其实不复杂,首先获取网站 favicon,然后给 favicon 添加标识,重新绘制生成就行了
其中,这里的图标就是通过 SVG 生成的,下面看看具体实现吧。
想知道获取方式,可以先了解设置方式。
一般有两种方式可以设置网站的 favicon
。
第一种,通过 link
标签设置(需要rel="icon"
属性)
<link rel="icon" href="xxx.png">
第二种,直接在网站根目录放一张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 基础知识就足够了。具体实现如下
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;
由于存在/favicon.ico
没有设置的情况,所以需要在 img 加载失败的时候给一张默认图
img.onerror = () => {
resolve("默认图base64");
}
这样就能获取到 favicon 的图像信息了
在上面的基础上,其实可以继续通过 canvas 进行绘制,再绘制一个标签也不是难事。不过这里可以采用 SVG 的方式来进行绘制,有以下一些优点
成本更低,比 canvas 更易理解灵活性高,可以通过 CSS 进行一些样式控制首先,我们可以在 HTML 中自由的、像正常网页开发一样,绘制这样一个布局,相信没有什么难度
<body>
<strong>local</strong>
<img src='xxx.png'>
</body>
由于宽度有限,所以需要强制文本换行,超出隐藏,关键样式如下
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 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')
这里需要注意几点
img 标签在 svg 中需要写成<img></img>
闭合形态,不然会被认为结构错误img 只能使用内联图片,比如 base64,这也是为何绘制原始 favicon 的原因如果使用内联 svg,需要对 svg 进行转义字符串中的单双引号问题也需要注意一下然后,将生成的 SVG 直接设置为 favicon
link.href= favicon;
这样就能正常的渲染了~
完整实现可以参考项目:https://github.com/XboxYan/auto-dev-favicon-chrome-plugin
首先是兼容性。
目前只有 Chrome 和 Firefox 是支持的,为了兼容其他浏览器,可以用一个 .ico
来兜底
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
另外,在 Chrome 上还有一个限制(不知道是不是Chrome 更新后的限制),当 favicon 使用 svg 格式图片时,此时的 svg 会处于一种secure-static-mode,在这种模式下,所有动画都不会执行,会处于第一帧,比如下面这个例子
<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>
很简单的一个背景颜色动画。在 Firefox 上是用作 favicon 是有动画的
但是,Chrome 上却不行,只有禁止的第一帧
所以之前想实现标识文本滚动的效果可以就此打住了
19
2022-10
19
2022-10
25
2022-09
15
2022-09
15
2022-09
14
2022-09