You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JS生成特定Google Font的全样式有效加载URL?

优化Google Fonts CSS链接生成函数的问题

我正在开发一款图像编辑器,需要在用户选择字体时加载该字体家族的所有可用样式(italic、normal)和字重(如400–800)。目前通过fontsource API获取字体数据,尝试生成Google CSS链接,示例链接如下:

https://fonts.googleapis.com/css2?family=Open%20Sans:ital,wght@0,300..800;1,300..800

但编写的函数有时会生成无效链接,且不确定是否覆盖所有样式/字重。以下是API返回的示例数据:

{
 "id": "open-sans",
 "family": "Open Sans",
 "subsets": [
  "cyrillic",
  "cyrillic-ext",
  "greek",
  "greek-ext",
  "hebrew",
  "latin",
  "latin-ext",
  "vietnamese"
 ],
 "weights": [
  300,
  400,
  500,
  600,
  700,
  800
 ],
 "styles": [
  "italic",
  "normal"
 ],
 "defSubset": "latin",
 "variable": true,
 "lastModified": "2022-09-22",
 "category": "sans-serif",
 "license": "OFL-1.1",
 "type": "google"
}

我的当前代码如下,请问是否有更优解决方案?谢谢

function generateGoogleFontURL(font) {
  const formattedFontFamily = font.family.replace(/\s+/g, "+")
  if (font.weights.length == 0) {
    return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}`]
  }
  if (!font.variable) {
      if (font.styles.includes("italic")) {
        return font.weights.map(x => `https://fonts.googleapis.com/css2?family=${formattedFontFamily}:ital,wght@0,${x};1,${x}`)
      }
      return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:wght@${font.weights.join(';')}`]
  }
  if (font.weights.length > 1) {
    const minWeight = font.weights[0]
    const maxWeight = font.weights[font.weights.length - 1]
    if (font.styles.includes("italic")) {
        return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:ital,wght@0,${minWeight}..${maxWeight};1,${minWeight}..${maxWeight}`]
    }
    else {
      return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:wght@${minWeight}..${maxWeight}`]
    }
  }    
  if (font.styles.includes("italic")) {
      return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:ital,wght@0,${font.weights[0]};1,${font.weights[0]}`]
  }
  return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:wght@${font.weights[0]}`]
}

优化方案

问题分析

原代码存在几个核心问题:

  • 第一行replace方法缺少闭合括号,存在语法错误
  • 非可变字体场景下,为每个字重生成单独链接,会触发过多HTTP请求,影响加载性能
  • 未处理weights数组无序的情况,直接取首尾元素可能生成错误的权重范围
  • 样式判断逻辑重复,边界场景覆盖不足

优化后的代码

function generateGoogleFontURL(font) {
  // 安全格式化字体名称,兼容特殊字符
  const formattedFontFamily = encodeURIComponent(font.family);
  // 处理无权重数据的边界情况
  if (!font.weights || font.weights.length === 0) {
    return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}`];
  }

  // 对权重数组排序,确保范围计算准确
  const sortedWeights = [...font.weights].sort((a, b) => a - b);
  const hasItalic = font.styles?.includes("italic");
  const hasNormal = !font.styles || font.styles.includes("normal");
  let paramSegments = [];

  if (font.variable) {
    // 可变字体使用范围语法
    const weightRange = `${sortedWeights[0]}..${sortedWeights.at(-1)}`;
    if (hasNormal) paramSegments.push(`0,${weightRange}`);
    if (hasItalic) paramSegments.push(`1,${weightRange}`);
  } else {
    // 非可变字体合并权重,减少请求数量
    const weightStr = sortedWeights.join(';');
    if (hasNormal) paramSegments.push(`0,${weightStr}`);
    if (hasItalic) paramSegments.push(`1,${weightStr}`);
  }

  // 拼接最终URL
  let baseUrl = `https://fonts.googleapis.com/css2?family=${formattedFontFamily}`;
  if (paramSegments.length > 0) {
    baseUrl += `:ital,wght@${paramSegments.join(';')}`;
  }

  return [baseUrl];
}

优化点说明

  • 用encodeURIComponent替代简单的空格替换,更安全处理字体名称中的特殊字符(如符号、非英文字符)
  • 对权重数组排序,避免API返回无序数据导致的范围错误
  • 合并非可变字体的样式请求,减少HTTP链接数量,提升加载性能
  • 清晰拆分样式判断逻辑,覆盖仅含normal、仅含italic等边界场景
  • 修复原代码的语法错误,增加对styles字段可能不存在的兼容处理

内容的提问来源于stack exchange,提问作者StupidDoofus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 20:24:57