使用 icomoon 从 svg Figma 图标生成字体时自动填充颜色

2023-11-26

我想将 svg 转换为图标字体我的 HTML/CSS 中的元素使用爱可梦应用程序

<svg width="325" height="350" viewBox="0 0 325 350" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M205.43 59.38C205.43 26.5853 232.015 0 264.81 0C297.605 0 324.19 26.5853 324.19 59.38C324.19 92.1747 297.605 118.76 264.81 118.76C246.525 118.76 230.17 110.495 219.277 97.4975L116.536 157.274C117.985 162.41 118.76 167.83 118.76 173.43C118.76 178.348 118.162 183.127 117.035 187.697L222.002 248.758C232.806 237.522 247.991 230.53 264.81 230.53C297.605 230.53 324.19 257.115 324.19 289.91C324.19 322.705 297.605 349.29 264.81 349.29C232.015 349.29 205.43 322.705 205.43 289.91C205.43 280.791 207.486 272.152 211.159 264.431L109.497 205.292C98.9566 221.836 80.4498 232.81 59.38 232.81C26.5853 232.81 0 206.225 0 173.43C0 140.635 26.5853 114.05 59.38 114.05C79.7735 114.05 97.7659 124.331 108.457 139.992L209.556 81.1716C206.893 74.4248 205.43 67.0733 205.43 59.38ZM264.81 19C242.509 19 224.43 37.0787 224.43 59.38C224.43 81.6813 242.509 99.76 264.81 99.76C287.111 99.76 305.19 81.6813 305.19 59.38C305.19 37.0787 287.111 19 264.81 19ZM59.38 133.05C37.0787 133.05 19 151.129 19 173.43C19 195.731 37.0787 213.81 59.38 213.81C81.6813 213.81 99.76 195.731 99.76 173.43C99.76 151.129 81.6813 133.05 59.38 133.05ZM224.43 289.91C224.43 267.609 242.509 249.53 264.81 249.53C287.111 249.53 305.19 267.609 305.19 289.91C305.19 312.211 287.111 330.29 264.81 330.29C242.509 330.29 224.43 312.211 224.43 289.91Z" fill="#0D0F13"/>
</svg>

但每次我生成图标字体文件三个圆圈之一填充黑色在 icomoon 预览中以及在 HTML 中使用时:

<span class="icon icon-share">

enter image description here


此渲染问题是由于不理想引起的路径方向.

path directions

你的图标是一个复合路径 - 它包含多个子路径(切出的“孔”)。

通常,您可以通过切换路径方向来定义哪些形状应被解释为实体或切口:
例如。如果外部形状的路径命令具有顺时针方向,则内部形状的路径命令应使用逆时针方向。

无论您使用顺时针还是逆时针或相反,都没有关系。内部(切出)路径只需使用相反的方向。
本文还解释了:填充规则的缠绕顺序

Svg:填充规则=“evenodd”

原始 svg 文件渲染得很好,因为它有一个fill-rule="evenodd"应用于路径元素。

显然,icomoon 字体生成器希望您的图标具有上述交替方向。
换句话说,将 svg 转换为字体文件时不能使用填充规则。

修复路径方向

这是一个用于修复内部路径的帮助程序脚本。

const svg = document.querySelector('svg');
const path = svg.querySelector('path');

function fixPath(path) {
  // get pathData array
  let pathData = path.getPathData({
    normalize: true
  });
  // split sub paths
  let pathDataSubArr = splitSubpaths(pathData);
  let fixedPathData = fixInnerPathDirections(path, pathDataSubArr);
  path.setPathData(fixedPathData);
}


/**
 * helpers
 */
function fixInnerPathDirections(path, pathDataSubArr) {
  let svg = path.closest('svg');
  let fixedPathData = [];
  let subPathEls = [];
  let bbO = path.getBBox();
  let [xO, yO, wO, hO, rO, bO] = [bbO.x, bbO.y, bbO.width, bbO.height, (bbO.x + bbO.width), (bbO.y + bbO
    .height)];
  let outerPathData = pathDataSubArr[0];
  let outerPathTmp = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  outerPathTmp.setPathData(outerPathData);
  outerPathTmp.classList.add('outer');
  let outerClockwise = isClockwise(outerPathTmp)

  pathDataSubArr.forEach(function(pathDataSub, i) {
    // create temporary subpath elements for checking positions
    let subPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    subPath.setPathData(pathDataSub);
    subPath.setAttribute('stroke', 'red');
    subPath.setAttribute('stroke-width', '1');
    subPath.setAttribute('fill', 'none');
    svg.appendChild(subPath);
    subPathEls.push(subPath);
    let bb = subPath.getBBox();
    let [x, y, w, h, r, b] = [bb.x, bb.y, bb.width, bb.height, (bb.x + bb.width), (bb.y + bb
      .height)];
    // remove temporary subpaths
    subPath.remove();

    if (i > 0) {
      // is subpath within outer path
      if (x > xO && y > yO && r < rO && b < bO) {
        let isClockwiseInner = isClockwise(subPath);
        // if subpath has same direction as outer path: reverse direction
        if (isClockwiseInner == outerClockwise) {
          pathDataSub = reversePathData(pathDataSub);
        }
      }
    }
    fixedPathData = fixedPathData.concat(pathDataSub);
  })
  return fixedPathData;
}


function reversePathData(pathData) {
  let M = pathData[0];
  let newPathData = [M];
  // split subpaths
  let subPathDataArr = splitSubpaths(pathData);
  subPathDataArr.forEach(function(subPathData, s) {
    let subPathDataL = subPathData.length;
    let closed = subPathData[subPathDataL - 1]['type'] == 'Z' ? true : false;
    let subM = subPathData[0]['values'];

    // insert Lineto if last path segment has created by z
    let lastCom = closed ? subPathData[subPathDataL - 2] : subPathData[subPathDataL - 1];
    let lastComL = lastCom['values'].length;
    let lastXY = [lastCom['values'][lastComL - 2], lastCom['values'][lastComL - 1]];
    let diff = Math.abs(subM[0] - lastXY[0]);
    if (diff > 1 && closed) {
      subPathData.pop();
      subPathData.push({
        'type': 'L',
        'values': [subM[0], subM[1]]
      });
      subPathData.push({
        'type': 'Z',
        'values': []
      });
    }
    subPathData.forEach(function(com, i) {
      // reverse index
      let subpathDataL = subPathData.length;
      let indexR = subpathDataL - 1 - i;
      let comR = subPathData[indexR];
      let comF = subPathData[i];
      let [typeR, valuesR] = [comR['type'], comR['values']];
      let [typeF, valuesF] = [comF['type'], comF['values']];
      if (typeF == 'M' && s > 0) {
        newPathData.push(comF);
      } else if (typeR != 'M' && typeR != 'Z') {
        indexR--;
        let prevCom = i > 0 ? subPathData[indexR] : subPathData[subpathDataL - 1 - i];
        let prevVals = prevCom ? (prevCom['values'] ? prevCom['values'] : [0, 0]) : [];
        prevVals = prevCom['values'];
        let prevValsL = prevVals.length;
        let newCoords = [];

        if (typeR == 'C') {
          newCoords = [
            valuesR[2], valuesR[3],
            valuesR[0], valuesR[1],
            prevVals[prevValsL - 2], prevVals[prevValsL - 1]
          ];
          if (!closed) {
            let nextVals = i < subpathDataL - 1 ? subPathData[i + 1]['values'] : lastXY;
            let lastCX = (i < subpathDataL - 2) ? nextVals[prevValsL - 2] : subM[0];
            let lastCY = (i < subpathDataL - 2) ? nextVals[prevValsL - 1] : subM[1];
            newCoords[4] = lastCX;
            newCoords[5] = lastCY;
          }
        } else {
          newCoords = [prevVals[prevValsL - 2], prevVals[prevValsL - 1]];
        }
        newPathData.push({
          'type': typeR,
          'values': newCoords
        });
      }
    })
    //use last coordinates as M values if path isn't closed
    if (!closed) {
      newPathData[0]['values'] = lastXY;
    }
    if (closed) {
      newPathData.push({
        'type': 'Z',
        'values': []
      });
    }
  });
  return newPathData;
}

/**
 * check path direction of polygon
 * based on answer:
 * @mpen: https://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order/1180256#answer-46613578
 */
function isClockwise(path, divisions = 50) {
  var length = path.getTotalLength();
  let p1 = path.getPointAtLength(0);
  let A = [p1.x, p1.y];
  let p2 = path.getPointAtLength(length * 0.25);
  let B = [p2.x, p2.y];
  let p3 = path.getPointAtLength(length * 0.75);
  let C = [p3.x, p3.y];
  let poly = [A, B, C];
  let end = poly.length - 1;
  let sum = poly[end][0] * poly[0][1] - poly[0][0] * poly[end][1];
  for (let i = 0; i < end; ++i) {
    const n = i + 1;
    sum += poly[i][0] * poly[n][1] - poly[n][0] * poly[i][1];
  }
  let cw = sum > 0 ? true : false;
  return cw;
}


function splitSubpaths(pathData) {
  let pathDataL = pathData.length;
  let subPathArr = [];
  let subPathMindex = [];
  pathData.forEach(function(com, i) {
    let [type, values] = [com['type'], com['values']];
    if (type == 'M') {
      subPathMindex.push(i);
    }
  });
  //split segments after M command
  subPathMindex.forEach(function(index, i) {
    let n = subPathMindex[i + 1];
    let thisSeg = pathData.slice(index, n);
    subPathArr.push(thisSeg)
  })
  return subPathArr;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/path-data-polyfill.min.js"></script>


<p><button type="button" onclick="fixPath(path)">Fix path directions</button></p>
<svg width="325" height="350" viewBox="0 0 325 350" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="
        M205.43 59.38C205.43 26.5853 232.015 0 264.81 0C297.605 0 324.19 26.5853 324.19 59.38C324.19 92.1747 297.605 118.76 264.81 118.76C246.525 118.76 230.17 110.495 219.277 97.4975L116.536 157.274C117.985 162.41 118.76 167.83 118.76 173.43C118.76 178.348 118.162 183.127 117.035 187.697L222.002 248.758C232.806 237.522 247.991 230.53 264.81 230.53C297.605 230.53 324.19 257.115 324.19 289.91C324.19 322.705 297.605 349.29 264.81 349.29C232.015 349.29 205.43 322.705 205.43 289.91C205.43 280.791 207.486 272.152 211.159 264.431L109.497 205.292C98.9566 221.836 80.4498 232.81 59.38 232.81C26.5853 232.81 0 206.225 0 173.43C0 140.635 26.5853 114.05 59.38 114.05C79.7735 114.05 97.7659 124.331 108.457 139.992L209.556 81.1716C206.893 74.4248 205.43 67.0733 205.43 59.38Z
        
        M264.81 19C242.509 19 224.43 37.0787 224.43 59.38C224.43 81.6813 242.509 99.76 264.81 99.76C287.111 99.76 305.19 81.6813 305.19 59.38C305.19 37.0787 287.111 19 264.81 19Z
        
        M59.38 133.05C37.0787 133.05 19 151.129 19 173.43C19 195.731 37.0787 213.81 59.38 213.81C81.6813 213.81 99.76 195.731 99.76 173.43C99.76 151.129 81.6813 133.05 59.38 133.05Z
        
        
        M224.43 289.91C224.43 267.609 242.509 249.53 264.81 249.53C287.111 249.53 305.19 267.609 305.19 289.91C305.19 312.211 287.111 330.29 264.81 330.29C242.509 330.29 224.43 312.211 224.43 289.91Z
        
        " fill="#0D0F13" />
    </svg>

(检查开发工具中的元素以获取新路径)

怎么运行的

  1. 解析路径命令(使用路径数据polyfill 作者:Jarek Foksa)
    1.2 以标准化方式检索路径数据(path.getPathData({normalize: true}):
    所有命令将仅使用绝对值转换为缩减集M, L, C, Z命令。
  2. 将路径数据拆分为子路径(每个子路径以新的开头M命令)
  3. 检查子路径是否与外部形状相交
  4. 检查外部和内部子路径之间的方向(使用isClockwise(path) helper)
  5. 如果需要的话反转子路径方向(reversePathData(pathdata))
  6. 连接子路径并覆盖原始路径d财产

Codepen 示例

你也可以使用这个codepen helper:修复 svg 复合路径方向
该脚本将保留原始命令类型 - 所以A, Q命令不会转换为三次贝塞尔曲线。

HTML/CSS 示例

@font-face {
    font-family: 'icomoon';
    src: url('data:font/woff2;charset=utf-8;base64,d09GMgABAAAAAAKsAA0AAAAABpgAAAJWAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP0ZGVE0cGh4GYACCXhEICoIwgicLDgABNgIkAxgEIAWDGwdFG5gFyJ4FdpMzjFBuZhHDYhE2Lyuvefjx8LVWvt89OwuoLkDsUKWigS2BIwnAKmwRyqeiD1z8VXT0WrS2WSR7w9M/YpFmHip+uESqS2jQkv/fzbMtejpWgbRBCusLh5mNJZxQLwq8+J+4Gbcs0ayoyySyNm4KAw7HxADTzsMwkLHPpyWQZQUKD0Zv7Xy3GOQpg6RIkmGRRZTNaBEChl5xBP7+oo23DrQwAJIQKkKBhJyGYq1CepJu3KLi+GdF1DGd6Klcj0blY/2GbQYFAcSpCPnkiQjsIBSYSGQ1aKhJkjB1VP8HxD9n+u8YsSw0AIRMlEQGIiEBAIICrg7RJwElaKGKPeAyoAAEQihyzqva7VbQSyfP/JuzIacHG9Ph+enDBacfK4dHbovJUxU8A6u/WJQ7Xqm9+nF6qDkbiclwo2VkBgb1ANjxPsxY2H3AZ4bRsplS0Zw5z18lt1pWnMqpZVxycbNKnuXD1oYHbk6mZGvfmfmdMLq4AgJQAH3+SAIPQNz+esn3KSVZ/Z/wwqyM0of8OfegJoEw3uUoQP4sfyGUBSC2AvhN/opAaTcRSAAA6HgjQKjqIZBUzUUgq1qPQKFqBwIVTacQKFXdF6BhvJcsirrQIQIJGQtkZClQIBuxigFprNRxvmfDSncH5TTVNTU14OCqn9JsAJswRX01GR14mZYGrQlL5G2Yjq6yW8/JxgFnVkarTN86GzQ19OgVMQ1MR0YPk6eXNaYXISRh2uCeHNrBzTrX/NNhDoTEti+JJEWWoyj3Hxm3Sk58/FjZQZy3Ai5jAAAA') format('woff2');
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

.icon{
  font-family: 'icomoon';
  font-size:5vw
}

.icon-share:before {
  content: "\e900";
}
<span class="icon icon-share">

替代方案:paper.js:

如果您的应用程序已经使用 paper.js 您也可以使用它reorient()固定路径方向的方法。查看相关帖子“Paper.js 重新定向:SVG 子路径丢失”

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 icomoon 从 svg Figma 图标生成字体时自动填充颜色 的相关文章

  • UITextField 字体大小在开始或停止输入字符时发生变化

    我见过很多线程 但没有找到解决这个问题的任何具体解决方案 我使用 XIB 创建了 UITextfield 尚未以编程方式对该字段执行任何操作 一旦我开始打字 文本字段的字体就会改变 一旦我将焦点移出文本字段 并且随着键盘消失 字体大小就会减
  • 在 SVG 中设置悬停语句样式

    我正在计划一个基于这个 SVG 插图的网络 菜单 我的想法的原则 一个样式为活动的圆圈 一个样式为悬停的圆圈以及一个也需要设置样式的伴随笔画 https i stack imgur com H397o png 当我阅读 SVG 文件的规范时
  • 使用 Javascript 动态添加时,SVG 元素无法正确缩放

    我正在尝试使用 Javascript 在 Bootstrap Grid 中添加 SVG 控件 我可以使用 Javascript 添加 SVG 但页面的缩放 调整大小的行为并不像使用静态 HTML 构建的那样 单击 添加页面 按钮时 一组新的
  • 设置 jdialog 框中文本的格式

    我有一个 JOptionPane JOptionPane showMessageDialog null text 文字是一个刺 String text Hello world 我想做的是改变文本的颜色 特别是一个单词 让我们说 你好 所以我
  • 使用自定义 TTF 字体进行 DrawString 图像渲染

    我在服务器端使用 GDI 创建图像 并将其传输到用户的浏览器 没有一个标准字体符合我的要求 因此我想加载 TrueType 字体并使用此字体将字符串绘制到图形对象 using var backgroundImage new Bitmap b
  • CSS 中的 Data-URI SVG 背景在 Firefox 中不起作用

    好的 这就是我想做的 我的 css 文件中有这段代码 form row textfield hover textfield m hover background image url data image svg xml base64 PHN
  • 修复 Raphaël 路径节点上 Tipsy 工具提示的位置

    这是一个非常具体且有些复杂的问题 所以我设置了一个最小测试用例 http reveal dk 8080 revealit dk tipsytest 在阅读本文的其余部分之前 您可能应该先了解一下 我的页面显示悬停时突出显示区域的图像Raph
  • 在 swift 中使用自定义字体[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我需要一个用于 swift sprite kit iOS 的字体 该字体用于商业目的 我正在尝试拥有一
  • svg路径指针事件-点击检测

    我正在编写一些 HTML 以便可以使用 HTML SVG 和 PATH 标签绘制贝塞尔曲线 我的曲线效果非常好 现在我想添加一项功能 如果用户将鼠标悬停在曲线上 我会更改颜色 但实际情况是 SVG 创建了一个包含路径的大框 并捕获所有点击
  • SVG 沿圆弧添加文本

    我正在尝试绘制 SVG 径向饼图 如下所述 色卡 https stackoverflow com a 18210763 1395178 现在我尝试将文本与圆弧一起添加到每个切片 我试图展示Text 1具有与 M 和 A 值完全相同的 x y
  • 具有宽度/高度的 SVG 在 IE9/10/11 上无法缩放

    IE 9 10 11 存在一个已知问题 如果您有一个 SVG 文件
  • 为什么 Firefox 对 Helvetica 的处理方式与 Chrome 不同?

    Firefox 和 Mac 版 Chrome 中以 Helvetica 呈现的文本的垂直位置及其内容区域的大小有所不同 例如 在 Chrome 中 如果行高与字体大小相同 则下行部分将被剪裁 我调整了图中块元素的位置 保持基线一致 以说明大
  • 我可以在 Chrome 中禁用本地字体吗?

    我工作的系统总是因为谷歌字体加载而出错 但我看不到字体何时未加载 因为我在本地 对于 Photoshop 有所有这些字体 所以字体在我的计算机上看起来不错 所以 我想在 Chrome 中禁用所有这些字体 这样我就可以快速查看谷歌字体是否正确
  • d3.js:在 SVG 线性渐变中过渡颜色?

    正如标题所说 使用D3 js 是否可以实现线性渐变的颜色过渡 例如 如果我有这个渐变 var gradient svg append svg defs append svg linearGradient attr id gradient a
  • 在 Android 中使用矢量图像在真实设备上出现问题。 SVG-android

    I use svg android jar from https github com pents90 svg android其工作正常 但仅在 Eclipse 中的模拟器设备上 啊啊啊啊 在真实设备上它只是空的imageView在屏幕上
  • 使用 JTextPane 制作文本下划线字体?

    我有一堂课的名字是fontlist我想使用以下划线字体文本窗格但我发现很难得到这个 粗体或斜体都可以正常工作 但是当我添加下划线代码时 它会给我一些错误 我的代码是 import java awt import java awt font
  • Android 上默认安装哪些字体? [复制]

    这个问题在这里已经有答案了 Android 设备上默认安装哪些字体 我知道关于机器人字体 http www droidfonts com and Roboto https developer android com design style
  • Svg 点击事件无法正常工作

    我试图让我的 SVG 看起来像一个 饼形 看起来一切都很好 此外 我希望它们每个都有不同的点击事件 function one alert 1 function two alert 2 function three alert 3 funct
  • 将自定义字体与 wkhtmltopdf 一起使用

    我正在尝试在使用 wkhtmltopdf 生成的 PDF 中使用自定义字体 我读到您不能使用 google webfonts 并且 wkhtmltopdf 使用 truetype ttf 文件 谁能证实这一点吗 所以我从 google we
  • 为什么字体扩展仅适用于 PDF,而不适用于其他格式(HTML、XLS、DOC)?

    通过 Jaspersoft Studio 我们使用以下设置将用于 Web 应用程序的内置 Windows Calibri 字体变体导出到字体扩展 JAR 中 导出的jrfontextensions jar内的目录结构如下 jrfontext

随机推荐