web-font/public/webfont-sdk.js
崮生(子虚) 9da270733d v1.2.0: 增量字体加载 SDK,优化预览体验
- 新增 webfont-sdk.js,支持按需增量加载字体片段,无闪烁
- 预览使用 SDK 增量加载,输入时不再重新加载已有字体
- SDK 根据元素类型(input/textarea vs 其他)正确获取文本
- SDK 支持重复调用同一选择器时自动清理旧状态
- 页面说明区分基础用法和进阶用法,提供 SDK 下载链接
- URL 改为完整域名(location.origin),方便用户直接复制使用
- 预览文本框字体大小调至 32px
- API Key 输入框改为 text 类型消除密码警告
- SEO 优化:添加 description meta,优化 title

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 20:48:23 +08:00

104 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* WebFont SDK — 按需增量加载字体片段,无闪烁
* 用法WebFont.loadFont({ fontName, selector, baseUrl, family })
*/
var WebFont = (function () {
/** 按 selector 索引的活跃任务,重复调用同一选择器时自动清理旧任务 */
var tasks = {};
/**
* @param {Object} options
* @param {string} options.fontName - 字体文件名(如 "思源黑体.ttf"
* @param {string} options.selector - CSS 选择器(如 ".title"
* @param {string} [options.baseUrl] - API 基础地址,默认当前域名
* @param {string} [options.family] - font-family 名称,默认 fontName 去掉扩展名
*/
function loadFont(options) {
var selector = options.selector;
var fontName = options.fontName;
var baseUrl = options.baseUrl || location.origin;
var family = options.family || fontName.replace(/\.[^.]+$/, "");
/** 清理同一选择器的旧任务 */
if (tasks[selector]) {
clearInterval(tasks[selector].timer);
/** 移除旧任务注入的 style 标签 */
var oldStyles = tasks[selector].styles;
for (var s = 0; s < oldStyles.length; s++) {
oldStyles[s].remove();
}
}
var loadedChars = {};
var injectedStyles = [];
var applied = false;
/** 获取元素的文本内容 */
function getText(el) {
var tag = el.tagName;
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") {
return el.value || "";
}
return el.textContent || "";
}
function collectChars() {
var charSet = {};
var elements = document.querySelectorAll(selector);
for (var i = 0; i < elements.length; i++) {
var text = getText(elements[i]);
for (var j = 0; j < text.length; j++) {
charSet[text[j]] = true;
}
}
return charSet;
}
function loadNewChars() {
var current = collectChars();
var newChars = [];
for (var c in current) {
if (!loadedChars[c]) {
newChars.push(c);
}
}
if (newChars.length === 0) return;
for (var k = 0; k < newChars.length; k++) {
loadedChars[newChars[k]] = true;
}
var text = newChars.join("");
var url = baseUrl + "/api?font=" + encodeURIComponent(fontName) + "&text=" + encodeURIComponent(text);
var unicodeRanges = newChars
.map(function (c) { return "U+" + c.codePointAt(0).toString(16).padStart(4, "0"); })
.join(", ");
var style = document.createElement("style");
style.textContent =
'@font-face {\n' +
' font-family: "' + family + '";\n' +
' src: url("' + url + '") format("truetype");\n' +
' unicode-range: ' + unicodeRanges + ';\n' +
'}\n';
document.head.appendChild(style);
injectedStyles.push(style);
if (!applied) {
applied = true;
var elements = document.querySelectorAll(selector);
for (var i = 0; i < elements.length; i++) {
elements[i].style.fontFamily = '"' + family + '", sans-serif';
}
}
}
loadNewChars();
var timer = setInterval(loadNewChars, 1000);
tasks[selector] = { timer: timer, styles: injectedStyles };
}
return { loadFont: loadFont };
})();