fix: fc-icon 改用 SVG 矢量图 + image 渲染,彻底解决微信 text 自定义字体不显示导致图标变字符

- 微信小程序 <text> 对 @font-face 自定义字体支持不可靠(开发者工具/真机均可能不渲染),图标回退成字符
- 改用 <image> 渲染 Lucide SVG 矢量图(data:image/svg+xml),彻底绕开字体加载限制,矢量/可上色
- 新增 utils/icon-svg.js(49 图标内层 SVG,stroke/fill 用 __C__ 占位),fc-icon 按 color 动态拼色
- 内置设计 token→色值映射,调用方传 var(--xxx) 自动解析为具体色值
- 移除 app.wxss 中已无用的 @font-face(字体方案废弃)
This commit is contained in:
2026-07-22 23:09:56 +08:00
parent 6b24be67ad
commit c98758e61b
5 changed files with 44 additions and 26 deletions

View File

@@ -1,23 +1,54 @@
const iconMap = require('../../utils/icon-map');
const iconSvg = require('../../utils/icon-svg');
// 设计 token 色值映射:调用方常传 var(--xxx),但 SVG data URI 内无法解析 CSS 变量,需转成具体色值
const CSS_VARS = {
'--accent': '#B6F24E',
'--accent-hover': '#C7F56E',
'--accent-active': '#9EDB3A',
'--text': '#ECF1EF',
'--text-2': '#9BA7A1',
'--text-3': '#6B7670',
'--danger': '#FF5C5C',
'--success': '#2BD9A6',
'--warn': '#F2B53D',
'--info': '#4FA8FF',
};
function resolveColor(c) {
if (!c) return '#ECF1EF';
const m = /^var\((--[\w-]+)\)$/.exec(String(c).trim());
if (m) return CSS_VARS[m[1]] || '#ECF1EF';
return c; // 已是具体色值hex
}
// 用 <image> 渲染 Lucide SVG 矢量图(微信小程序 <text> 自定义字体不可靠,改用此方案 100% 稳定)
Component({
properties: {
// Lucide 图标名,如 search / dumbbell / heart
name: { type: String, value: '' },
// 字号rpx
// 字号rpx,同时作为图标宽高
size: { type: Number, value: 20 },
// 颜色默认跟随当前文字色currentColor 在 iconfont 下用具体色
// 颜色:可传具体 hex或 var(--xxx)(自动解析为对应 token 色值
color: { type: String, value: '' },
},
data: { glyph: '' },
data: { src: '' },
observers: {
name(n) {
this.setData({ glyph: (iconMap[n] || '') });
},
name(n) { this._build(n, this.data.color); },
color(c) { this._build(this.data.name, c); },
},
lifetimes: {
attached() {
this.setData({ glyph: (iconMap[this.data.name] || '') });
attached() { this._build(this.data.name, this.data.color); },
},
methods: {
_build(name, color) {
const inner = iconSvg[name];
if (!inner) { this.setData({ src: '' }); return; }
const stroke = resolveColor(color);
const body = inner.replace(/__C__/g, stroke);
const svg =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" ' +
'stroke="' + stroke + '" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
body + '</svg>';
this.setData({ src: 'data:image/svg+xml,' + encodeURIComponent(svg) });
},
},
});

View File

@@ -1 +1 @@
<text class="fc-icon" style="font-size:{{size}}rpx;{{color ? 'color:' + color + ';' : ''}}">{{glyph}}</text>
<image wx:if="{{src}}" src="{{src}}" mode="aspectFit" class="fc-icon" style="width:{{size}}rpx;height:{{size}}rpx;" />

View File

@@ -1,10 +1,4 @@
.fc-icon {
font-family: "fc-icon";
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
display: inline-block;
vertical-align: middle;
}