如何使用Javascript更改@ font-face源?

时间:2018-06-23 18:22:11

标签: javascript css fonts webfonts

我正在为设计师设计一个简单的工具,用户可以输入一些文本,然后生成各种字体以找到适合其项目的最佳选择。

我正在努力寻找最佳的字体加载方式。显然,我并不是真的想一次加载所有字体,因此仅在生成字体后才需要加载。使用@font-face CSS规则将是理想的选择,但我似乎无法弄清楚如何使用Javascript更改字体的src。

现在,我的方法是使用Google字体,在该字体中,您可以使用<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">之类的CSS链接加载字体。然后,我可以使用Javascript更改该链接的href,该链接将以新字体加载。但是这种方法将我限制为仅使用Google字体,而能够加载本地Web字体,TypeKit字体等是理想的选择。

是否有人对加载字体的最佳方法或如何使用Javascript访问CSS中的@font-face规则有任何建议?

2 个答案:

答案 0 :(得分:1)

设置一个样式表来控制字体,并带有一个ID,可让您删除它并随意重建它。例如:

function setFontTo(fontName) {
  const styleId = 'font-style-sheet';

  // Get a reference to the current in-use stylesheet, if there is one.
  var fontStyleSheet = document.getElementById(styleId);

  // Then define a new stylesheet with an updated @font-face rule:
  var newFontStyleSheet = document.createElement("style");
  newFontStyleSheet.id = styleId;
  newFontStyleSheet.textContent = `
    @font-face {
      font-family: 'main-dynamic-font';
      src: url(assets/fonts/${fontName}.woff) format('woff');
    }
  `;

  // Then we swap: add the new rule first, then remove the old one.
  // That way you don't get a flash of unstyled text.
  document.head.appendChild(newFontStyleSheet);

  if (fontStyleSheet) {
    fontStyleSheet.parent.removeChild(fontStyleSheet);
  }
}

然后确保在CSS文件/捆绑包中定义一个使用该字体的类,如下所示:

.main-content {
  font-family: 'main-dynamic-font', serif;
}

然后在您的标记中,将该类用于需要使用用户选择的字体来设置文本样式的任何元素:

<div class="main-content blah blah ...">
  ...
</div>

最后,请确保您的字体选择器允许用户选择作为名称值映射到实际字体文件名的字体名称(并确保始终使用woff):

<select id="font-picker">
  <option value="roboto-regular">Roboto (regular)</option>
  ...
</select>

具有用于该选择器的js处理程序。

fontSelector = document.getElementById("font-picker");
fontSelector.addEventListener("change", evt => {
  // read the selected value, and then call the font swap function here.
});

答案 1 :(得分:0)

此演示通过一些单选按钮与用户进行交互。每个单选按钮对应于Google字体的字体系列。被注释掉的部分将处理localStorage(离开页面时丢失样式将毫无意义)。它无法在SO上正常运行,但可以将您的更改保存在不太严格的环境中(正常情况下)。

参考文献

HTMLFormControlsCollection

Event Delegation

CSS Variables

Template Literals


演示

//document.onDOMContentLoaded = init;

var form = document.forms.font;

form.addEventListener('change', fontInput);

function fontInput(e) {
  var fc = form.elements;
  var fam = ['Montserrat', 'Roboto', 'Open Sans', 'Raleway', 'Quicksand'];
  var idx = parseInt(fc.font.value, 10);
  var family = `${fam[idx]}`;
  var url = `https://fonts.googleapis.com/css?family=`;
  var fontUrl;
  if (e.target.name === 'font') {
    var famFont = family.replace(/\s/g, `+`);
    fontUrl = `${url}${famFont}`;
    document.getElementById('link').href = fontUrl;
    console.log(fontUrl);
    //localStorage.setItem('fontUrl', fontUrl);
  }
  cssVAR(family);
  e.stopPropagation();
}

function cssVAR(str) {
  var root = document.documentElement
  root.style.setProperty('--fam', str);
  return false;
}

/*
function init(e) {
  var saved = localStorage.getItem('fontUrl');
  if (!saved) {
    localStorage.setItem('fontUrl', 'https://fonts.googleapis.com/css?family=Open+Sans');
    document.getElementById('link').href = 'https://fonts.googleapis.com/css?family=Open+Sans';
  } else {
    document.getElementById('link').href = saved;
  }
}
*/
:root {
  --fam: "Raleway";
}

.as-console-wrapper {
  width: 40%;
  margin-left: 60%;
  max-height: 60px;
}

.as-console-row:after {
  display: none;
}

body {
  font-family: var(--fam);
}

#font {
  font-family: Consolas;
  font-size: 13px;
}
<link href='https://fonts.googleapis.com/css?family=Raleway' rel='stylesheet' id='link'>
<form id='font'>
  <fieldset>
    <legend>Font-Family</legend>
    <label>Montserrat</label>
    <input type='radio' value='0' name='font'>
    <label>Roboto</label>
    <input type='radio' value='1' name='font'>
    <label>Open Sans</label>
    <input type='radio' value='2' name='font'>
    <label>Raleway</label>
    <input type='radio' value='3' name='font' checked>
    <label>Quicksand</label>
    <input type='radio' value='4' name='font'>
  </fieldset>
</form>
<h1>Dynamic CSS</h1>
<p><q>The face of the moon was in shadow.</q></p>
<cite>Mr. Spaceship, by Philip K. Dick</cite>