【问题标题】:Firefox returning empty string for font when using getComputedStyleFirefox 在使用 getComputedStyle 时为字体返回空字符串
【发布时间】:2018-11-07 12:02:14
【问题描述】:

我编写了一个实用函数来获取字符串的像素宽度。我希望该函数可以选择使用在特定元素上设置的字体,因此无论该元素的样式如何,我都会自动使用该字体进行测量。

问题是 Firefox 不想告诉我元素正在使用什么字体。以下代码适用于其他浏览器:

export function getTextWidth(items: string | string[], font: string | HTMLElement, fallbackFont?: string): number {
  const canvas = ((getTextWidth as any).canvas as HTMLCanvasElement ||
                  ((getTextWidth as any).canvas = document.createElement('canvas') as HTMLCanvasElement));
  const context = canvas.getContext('2d');
  let maxWidth = 0;

  if (typeof font === 'string')
    context.font = (font ? font : 'normal 12px sans-serif');
  else if (typeof font === 'object') {
    const elementFont = window.getComputedStyle(font).getPropertyValue('font');

    if (elementFont)
      context.font = elementFont;
    else if (fallbackFont)
      context.font = fallbackFont;
    else
      context.font = 'normal 12px sans-serif';
  }

  if (!Array.isArray(items))
    items = [items];

  for (const item of items) {
    const width = context.measureText(item).width;
    maxWidth = Math.max(maxWidth, width);
  }

  return maxWidth;
}

问题是 window.getComputedStyle(font).getPropertyValue('font') 在 Firefox 上返回一个空字符串,所以我无法将 context 设置为匹配的字体,以便 measureText 正常工作。

我在函数fallbackFont 中添加了可选参数,因此我可以传递一个明确的字体以供参考,但这不是一个非常令人满意的解决方案。

【问题讨论】:

    标签: javascript css typescript firefox fonts


    【解决方案1】:

    以这种方式获取字体有点痛苦,但我发现 Firefox 会分别返回元素当前字体的各个方面,例如 font-sizefont-family。它们都可以被查询并组装成一个字体字符串:

      if (typeof font === 'string')
        context.font = (font ? font : 'normal 12px sans-serif');
      else if (typeof font === 'object') {
        let style = window.getComputedStyle(font);
        let elementFont = style.getPropertyValue('font');
    
        if (elementFont)
          context.font = elementFont;
        else {
          const fontStyle = style.getPropertyValue('font-style');
          const fontVariant = style.getPropertyValue('font-variant');
          const fontWeight = style.getPropertyValue('font-weight');
          const fontSize = style.getPropertyValue('font-size');
          const fontFamily = style.getPropertyValue('font-family');
    
          elementFont = (fontStyle + ' ' + fontVariant + ' ' + fontWeight + ' ' + fontSize + ' ' + fontFamily)
            .replace(/ +/g, ' ').trim();
    
          if (elementFont)
            context.font = elementFont;
          else if (fallbackFont)
            context.font = fallbackFont;
          else
            context.font = 'normal 12px sans-serif';
        }
      }
    

    【讨论】:

      【解决方案2】:

      这是我用来从 getComputedStyle() 返回的对象中安全检索 .font 属性的函数。在 Chrome/Safari/Firefox 中测试。请注意,我还将 Firefox 的字体拉伸百分比值转换为关键字,因为百分比值似乎不适用于像 measureText() 这样的 Canvas。

      function getFontFromComputedStyle (computedStyle) {
        let font = computedStyle.font;
        // Firefox returns the empty string for .font, so create the .font property manually
        if (font === '') {
          // Firefox uses percentages for font-stretch, but Canvas does not accept percentages
          // so convert to keywords, as listed at:
          //   https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch
          let fontStretchLookupTable = {
            '50%': 'ultra-condensed',
            '62.5%': 'extra-condensed',
            '75%': 'condensed',
            '87.5%': 'semi-condensed',
            '100%': 'normal',
            '112.5%': 'semi-expanded',
            '125%': 'expanded',
            '150%': 'extra-expanded',
            '200%': 'ultra-expanded'
          };
          // If the retrieved font-stretch percentage isn't found in the lookup table, use
          // 'normal' as a last resort.
          let fontStretch = fontStretchLookupTable.hasOwnProperty(computedStyle.fontStretch)
            ? fontStretchLookupTable[computedStyle.fontStretch]
            : 'normal';
          font = computedStyle.fontStyle
            + ' ' + computedStyle.fontVariant
            + ' ' + computedStyle.fontWeight
            + ' ' + fontStretch
            + ' ' + computedStyle.fontSize
            + '/' + computedStyle.lineHeight
            + ' ' + computedStyle.fontFamily;
        }
        return font;
      }
      

      用法:

      getFontFromComputedStyle(getComputedStyle(elem))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-05
        • 1970-01-01
        相关资源
        最近更新 更多