为什么我的 SVG 文件不使用我的字体文件?

2023-12-02

我在同一目录中有这个 SVG 文件这个字体的TTF 文件。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  version="1.1"
  width="150"
  height="100"
  viewBox="0 0 150 100"
>
  <style type="text/css">
    @font-face {
      font-family: "easyPrint";
      src: url('./easy-print.regular.ttf');
    }   
  </style>
  <text
    x="10"
    y="30"
    class="word"
    font-family="easyPrint"
    font-size="25"
  >
    TEST
  </text>
  <text
    x="10"
    y="80"
    font-size="25"
  >
    TEST
  </text>
</svg>

当我这样做时,我得到两种不同的字体。应该是我的自定义字体的字体与您在字体系列中给它乱码时看到的字体相同。这与默认值不同。

我也尝试过使用 OTF 文件。具体字体并不重要。我只是想生成一堆具有特定字体的文本 SVG 图像。


如果您需要 svg 文件完全独立,
您应该考虑将字体文件嵌入为 base64 资源(使用类似转换器):

1. 示例:嵌入为 base64 的字体

<p>This svg would always display the custom font (inlined svg, referenced in img element, opened directly in browser.)<br /> (Letter a is not contained in the reduced character subset)</p>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 100">
<style>
@font-face {
    font-family: 'easyPrint';
     src: url('data:font/woff2;charset=utf-8;base64,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') format('woff2');
    font-weight: normal;
}
  </style>
  <text
    x="10"
    y="30"
    class="word"
    font-family="easyPrint"
    font-size="25"
  >
    TESTa
  </text>
</svg>

您可以通过对字体进行子集化来显着减小文件大小:
只有选定的角色才可用。

transfonter settings

2. 示例:Svg2Png

此方法要求将字体内联为 dataURL。
否则,png 输出将呈现默认字体,如 Times。

function svg2Png(selector) {
  const svgEl = document.querySelector(selector);
  let svgVB = svgEl.getAttribute('viewBox');
  let svgVBArr = svgVB ? svgVB.split(' ') : '';
  let svgVBW = svgVBArr ? svgVBArr[2] : '';
  let svgVBH = svgVBArr ? svgVBArr[3] : '';

  let svgClientBB = svgEl.getBoundingClientRect();
  let svgClientW = svgClientBB.width;
  let svgClientH = svgClientBB.height;

  let svgBB = svgEl.getBBox();
  let svgW = svgVBW? svgVBW : svgBB.width;
  svgW = svgClientW > svgW ? svgClientW : svgW;
  let svgH = svgVBH? svgVBH : svgBB.height;
  svgH = svgClientH > svgH ? svgClientH : svgH;


  let blob = new Blob([svgEl.outerHTML], {type: 'image/svg+xml'});
  let URL = window.URL;
  let blobURL = URL.createObjectURL(blob);
  let tmpImg = new Image();
  tmpImg.src = blobURL;
  tmpImg.width = svgClientW > svgW ? svgClientW : svgW;
  tmpImg.height = svgClientH > svgH ? svgClientH : svgH;

  tmpImg.onload = () => {
    let canvas = document.createElement("canvas");
    canvas.width = svgW;
    canvas.height = svgH;
    let context = canvas.getContext("2d");
    
    // draw blob img to canvas with some delay
    setTimeout(function () {
      context.drawImage(tmpImg, 0, 0, svgW, svgH);
      let pngDataUrl = canvas.toDataURL();
      let svgImg = document.createElement("img");
      svgImg.width = svgW;
      svgImg.height = svgH;
      svgImg.class = "svgImg";
      svgImg.src = pngDataUrl;
      // just additional wrapping for example usage
      let imgWrp = document.createElement("div");
      imgWrp.setAttribute("class", "img-wrp");
      imgWrp.appendChild(svgImg);
      document.body.appendChild(imgWrp);
    }, 300);
  };
}
    svg,
        img{
            border:1px solid #ccc
        }

        .svg-wrp{
            position:relative;
            overflow:auto;
            resize:both;
            width:50%;

        }
<div class="btn-wrp">
  <button type="button" onclick="svg2Png('svg')">svg2Png</button>
</div>

<div class="svg-wrp">

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 100">
<style>
@font-face {
    font-family: 'easyPrint';
     src: url('data:font/woff2;charset=utf-8;base64,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') format('woff2');
    font-weight: normal;
}
  </style>
  <text
    x="10"
    y="30"
    class="word"
    font-family="easyPrint"
    font-size="25"
  >
    TEST
  </text>
</svg>

</div>

3. 示例:创建 svg,其中文本呈现为路径

这个例子使用了awesomeopentype.js 库.
Opentype.js 有一个方便的功能font.getPath()允许您将字符串渲染为 svg<path>基于之前加载的字体文件的元素。

let svgcontainer = document.querySelector('#svgcontainer');
let inputText = document.querySelector('#inputText');
// opentype.js accepts only ttf and otf
let fontFile = 'https://fonts.gstatic.com/s/firasans/v15/va9E4kDNxMZdWfMOD5Vvl4jO.ttf';
inputText.addEventListener('change', function(e) {
  let testString = e.currentTarget.value;
  let params = {
    string: testString,
    font: fontFile,
    fontSize: 100,
    x: 0,
    y: 0,
    decimals: 3
  }
  text2Path(params)
})

//default
let params = {
  string: inputText.value,
  font: fontFile,
  fontSize: 100,
  x: 0,
  y: 0,
  decimals: 3
}
text2Path(params)

function text2Path(params) {
  opentype.load(params.font, function(err, font) {
    if (!err) {
      let options = params.options;
      let path = font.getPath(params.string, params.x, params.fontSize, params.fontSize, options);
      let textPath = path.toSVG(params.decimals);
      let newSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
      newSvg.classList.add('svgText');
      newSvg.setAttribute('xmlns', "http://www.w3.org/2000/svg");
      newSvg.insertAdjacentHTML('beforeend', textPath);
      svgcontainer.appendChild(newSvg);

      // adjust bbox
      let bb = newSvg.getBBox();
      newSvg.setAttribute('viewBox', '0 0 ' + (bb.width + bb.x) + ' ' + (params.fontSize * 1.5));

      //add downloadbtn
      let btnDownload = document.createElement("a");
      btnDownload.setAttribute('download', 'font-' + params.string + '.svg');
      btnDownload.textContent = 'Download';
      let dataURl = getDataUrl(newSvg.outerHTML, 'image/svg+xml');
      btnDownload.href = dataURl;
      svgcontainer.appendChild(btnDownload)

    } else {
      console.log('Font could not be loaded: ' + err);
    }
  });
}

function getDataUrl(str, mime) {
  let dataUrl = 'data:' + mime + ';base64,' + btoa(unescape(encodeURIComponent(str)))
  return dataUrl;
}
.svgText {
  height: 10em;
  display: inline-block;
  border: 1px solid #ccc;
}

a {
  display: block
}
<script src="https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js"></script>

<div class="layout">
  <div class="frm-wrp">
    <input id="inputText" type="text" value="Test">
  </div>
  <div class="svgcontainer" id="svgcontainer"></div>
</div>

替代方案:在图形编辑器中将文本转换为路径

这可能是最方便的解决方案。

  • 确保所需的字体已在本地安装(在您的操作系统中)。
  • 在 inkscape 等图形编辑器中打开 svg。
  • 选择你<text>元素并将它们转换为路径:
    inkscape:路径/对象到路径
    Adobe Illustrator:输入/创建轮廓
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我的 SVG 文件不使用我的字体文件? 的相关文章

  • 如何仅在单击子级时触发父级单击事件

    子级和父级都是可点击的 子级可以是带有 jQ uery 单击事件的链接或 div 当我点击子事件时 如何只触发父事件而不触发子事件 DOM 事件阶段 活动分为三个阶段 Capture 第一阶段是 捕获 其中从事件处理程序开始调用
  • jQuery hide() 动画向右滑动

    使用 jQuery 的hide 使用可选的持续时间参数的函数 我可以在我的网站上获得一些警报框 以优雅地滑出屏幕并消失 隐藏动画的默认方向似乎是向左滑动 尽管此行为未在hide 定义页 http api jquery com hide 我需
  • 对(静态)CSS 文件所做的更改未反映在 Django 开发服务器中

    我正在使用 Django 制作一个 Web 应用程序 但在将 CSS 文件 存储在我的应用程序的静态目录中 中所做的更改反映到开发服务器上时遇到了一些问题 需要明确的是 服务器能够访问静态文件 但是 它目前停留在我的 CSS 文件的旧版本上
  • FF 和 Webkit 中边框折叠的差异

    我有一个包含以下规则的表 table cellspacing 0 cellpadding 0 style width 100 并且单元格具有以下 CSS td padding 4px height 22px border 1px solid
  • 始终滚动 div 元素而不是页面本身

    我有一个带有内部的页面布局 div 包含页面上重要内容的元素 设计的重要部分是 content height 300px width 500px overflow scroll 现在 当包含的文本大于 300px 时 我需要能够滚动它 是否
  • 如何使

    我有一个列表 用作选项卡列表 div ul class TabControl li a href search Funds Funds 60 a li li a href search Companies Companies 4 a li
  • 将自定义 CSS 添加到使用 Compass 生成的精灵中

    我有这个代码my images scss file icon layout smart icon sprite dimensions true import icon png include all icon sprites 输出是这样的
  • 限制在三角形内

    我正在寻找一段通用代码 javascript 它可以与 jquery UI 一起使用来限制三角形内 div 的移动 拖动 与此类似 http stackoverflow com questions 8515900 how to constr
  • 输入数字最大属性调整字段大小

    当在 Chrome 中向输入数字字段添加最大值时 它将根据最大值的宽度重新调整字段的大小 看来我无法控制调整大小的行为
  • 是否可以在 Javascript 中的 css3 转换期间获取目标计算的 css 属性值?

    是否有可能在 Javascript 中的 css3 转换期间获取目标 最终 计算的 css 属性值 我找到了这个答案 是否可以在 Javascript 中的 css3 转换期间获取目标 css 属性值 https stackoverflow
  • CSS Font-Face url 不起作用?

    我在使用 font face 选择器时遇到了一些问题 我有以下问题 font face font family MuseoSans 700 src url http mysite co uk clients reload Images st
  • 粘表行

    我正在尝试实现一个像 iOS 那样的日历列表视图 基本上 我现在正在做的就是循环遍历我的事件数组 如果是新日期 则打印日期标题 否则打印日历事件 我想让日期标题行保持粘性 直到它们 滚动走 我怎样才能做到这一点 我看到很多关于粘性标题的示例
  • 混合混合模式:乘法在 Chrome 中不起作用

    我正在尝试使用mix blend mode multiply在 Chrome 上 但它无法按预期工作 当我添加时magenta cyan and yellow在一起它不会给我黑色但brown https i stack imgur com
  • 从 Bootstrap 4 网格中删除装订线

    在 Bootstrap 4 中 我被要求自定义桌面的默认网格系统 如下所示 其中 容器 桌面断点为1280px 我尝试过的例子是 body margin top 3rem l wrap max width 1280px margin rig
  • IE10中的图像插值

    这是我的用例 我有一个采用响应式设计的网页 该页面垂直分成两半 我想在右侧显示图像 呈现为 PNG 或 JPG 的 PDF 页面 调整窗口大小后 图像的大小应立即更改 我以为我已经解决了这个问题 我将服务器上的图像渲染得足够大 以适应最大可
  • 如何翻转 Twitter Bootstrap 的工具提示

    我正在使用 Twitter 的 Bootstrap 来实现工具提示 目前 工具提示显示在链接上方 我希望工具提示出现在链接下方 我该怎么做呢 我正在触发工具提示 它明确指出 底部 但它不想为我工作 tooltip tooltip place
  • IE8 中空 div 层的 z-index 问题

    我在 IE8 中遇到 z index 问题 其他尚未测试 以下 JS 创建一些 html css document write img src border 0 document write div style background col
  • iOS 键盘显示后分屏宽度

    我刚刚开始研究 Cordova 应用程序对分屏多任务处理的支持 到目前为止 该应用程序在模拟器中的 iPad 上显示和调整大小都很好 但是当我单击编辑字段并显示软件键盘时 100 宽度的值开始返回整个屏幕 而不是给出的窗口 初始显示 到目前
  • 如何在不设置动画的情况下突然更改 CSS 动画中的属性

    这是我试图弄清楚的 但没有使用 51 关键帧作为实现更改的黑客方法transform origin 这里有一个小提琴演示 http jsfiddle net p7pswnpq keyframes spin 0 transform origi
  • 在桌面和移动设备上编写 2 列和 3 列的 Flexbox 代码(换行)

    我真的很难弄清楚这个 CSS flexbox 解决方案 基本上有两个问题 一个是 2 列布局 另一个是 3 列布局 2 列 我认为这可能非常简单 3 列 这可能更高级一些 容器类是 嗯 container 而孩子们只是 left right

随机推荐