【问题标题】:Merge multiple SVG elements into one SVG and download it with React将多个 SVG 元素合并为一个 SVG 并使用 React 下载
【发布时间】:2022-12-18 09:12:29
【问题描述】:

我的应用程序中有一个徽标创建器。

用户必须在输入字段中键入 smthn(例如“TESTING”),然后它会在预览块中呈现。

预览中的每个字母都是 svg 元素:

(每个字母可以是字形字母或普通字母,表示有2种不同的字体)

const C = ({ glyph }) => {
    if (!glyph) {
        return (
            <svg width="93" height="132" viewBox="0 0 93 132" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path
                    d="M75 41.76L87.6 34.92C82.2 21.6 67.2 10.8 49.08 10.8C19.92 10.8 4.8 30.12 4.8 54C4.8 77.88 19.2 97.2 49.08 97.2C67.2 97.2 82.2 86.4 87.6 73.08L75 66.12C71.04 75.72 61.92 84 48.48 84C30.72 84 19.68 71.76 19.68 54C19.68 36.24 30.72 24 48.48 24C61.92 24 71.04 32.28 75 41.76Z"
                    fill="currentColor"
                />
            </svg>
        );
    } else {
        return (
            <svg width="96" height="132" viewBox="0 0 96 132" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path
                    d="M20.4 51.24H33.6C33.6 31.92 42.24 24 54.36 24C64.92 24 72.36 29.16 76.2 40.56L88.8 33.6C83.4 19.2 71.64 10.8 54.48 10.8C32.04 10.8 18.72 25.08 18.72 51.24H4.8C4.8 80.52 24.48 97.08 49.8 97.08C70.68 97.08 83.04 85.8 89.16 74.04L77.64 67.44C71.88 77.16 64.2 83.64 50.4 83.64C33.12 83.64 21.12 71.16 20.4 51.24Z"
                    fill="currentColor"
                />
            </svg>
        );
    }
};

我通过单击字母更改字形状态(这是悬停视图):

它在开发者工具中的样子:

我期待什么:

下载点击:

我需要将此徽标(“TESTING”)下载为 .svg 文件。

const svgHtml = Array.from(logoRef.current.querySelectorAll('span'))
            .map((el) => el.innerHTML)
            .join('\n');

const svg = `
    <svg xmlns="http://www.w3.org/2000/svg">
        ${svgHtml}
    </svg>
`;

const blob = new Blob([svg], { type: 'image/svg+xml' });
createDownloadLink(blob, `${inputText}.svg`);

实际行为:

所有字母都没有预览中的相对定位:

你有什么想法我该怎么做?

或者,也许您有更好的解决方案?

提前致谢

【问题讨论】:

  • 一种方法:将所有字母作为符号放在 svg 元素&lt;symbol viewBox="0 0 87 132" ... 的 <defs> 中。给符号一个id。为了显示字母 usa 具有所需大小(width="87" height="132")和位置(x 和 y 属性)的 &lt;use href="#theID"&gt; 元素
  • 将您的字母 svgs 转换为适当的 .woff 或 .ttf 字体文件(例如使用 fontello 或 icomoon 应用程序)并通过 opentype.js 生成组合文本路径可能更容易。见codepen example

标签: javascript reactjs svg


【解决方案1】:

你需要计算x偏移量在合并它们之前每个字母 svg 的值,因为它们不知道它们在 HTML DOM 上下文中的位置(即作为 &lt;span&gt; 元素的子元素)。

此偏移值将增加 viewBox 宽度
(3. viewBox 参数:viewBox="0 0 93 132" => width=93):

JavaScript 示例

let spans = document.querySelectorAll('span');
let svgMarkup = '';
let xOffset = 0;
let viewBoxHeight = 132;
let letterSpacing = 5;
spans.forEach((span,i)=>{
  let svg = span.querySelector('svg');
  let style = window.getComputedStyle(span)
  let color = style.color;
  let viewBox = svg.getAttribute('viewBox').split(' ');
  let width = +viewBox[2];
  let glyph = svg.querySelector('path');
  // clone path to apply offset
  let glyphCloned = glyph.cloneNode(true);
  // apply x offset by translate()
  glyphCloned.setAttribute('transform', `translate(${xOffset} 0)`);
  glyphCloned.style.color=color;
  let glyphMarkup = glyphCloned.outerHTML;
  glyphCloned.remove();
  svgMarkup+=glyphMarkup;
  // increment offset for next letter
  xOffset += i==spans.length-1 ? width : width+letterSpacing;
})

let svgCombined = `
<svg id="combined" xmlns="http://www.w3.org/2000/svg" width="${xOffset}" height="${viewBoxHeight}" viewBox="0 0 ${xOffset} ${viewBoxHeight}">
  ${svgMarkup} 
</svg>`;

document.body.insertAdjacentHTML('beforeend', svgCombined);
svg{
  height:10em;
  width:auto;
  border:1px solid #ccc;
}


.blue{
  color:blue
}
<span><svg width="93" height="132" viewBox="0 0 93 132" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M75 41.76L87.6 34.92C82.2 21.6 67.2 10.8 49.08 10.8C19.92 10.8 4.8 30.12 4.8 54C4.8 77.88 19.2 97.2 49.08 97.2C67.2 97.2 82.2 86.4 87.6 73.08L75 66.12C71.04 75.72 61.92 84 48.48 84C30.72 84 19.68 71.76 19.68 54C19.68 36.24 30.72 24 48.48 24C61.92 24 71.04 32.28 75 41.76Z" fill="currentColor" />
  </svg>
</span>
<span class="blue">
  <svg width="96" height="132" viewBox="0 0 96 132" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M20.4 51.24H33.6C33.6 31.92 42.24 24 54.36 24C64.92 24 72.36 29.16 76.2 40.56L88.8 33.6C83.4 19.2 71.64 10.8 54.48 10.8C32.04 10.8 18.72 25.08 18.72 51.24H4.8C4.8 80.52 24.48 97.08 49.8 97.08C70.68 97.08 83.04 85.8 89.16 74.04L77.64 67.44C71.88 77.16 64.2 83.64 50.4 83.64C33.12 83.64 21.12 71.16 20.4 51.24Z" fill="currentColor" />
  </svg>
</span>
<span><svg width="93" height="132" viewBox="0 0 93 132" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M75 41.76L87.6 34.92C82.2 21.6 67.2 10.8 49.08 10.8C19.92 10.8 4.8 30.12 4.8 54C4.8 77.88 19.2 97.2 49.08 97.2C67.2 97.2 82.2 86.4 87.6 73.08L75 66.12C71.04 75.72 61.92 84 48.48 84C30.72 84 19.68 71.76 19.68 54C19.68 36.24 30.72 24 48.48 24C61.92 24 71.04 32.28 75 41.76Z" fill="currentColor" />
  </svg>
</span>


<p>Combined Svg</p>

上面的示例也将只选择 &lt;path&gt; 元素而不是它们的父元素 &lt;svg&gt;s。
事实上,您还可以通过x 属性设置偏移量。
然而,很多图形应用程序与嵌套 svgs 斗争- 所以只复制路径通常是独立 svg 的更强大的解决方案。

此外,我们根据所有组合字母 svg 的总宽度和高度添加 viewBox

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-16
    • 1970-01-01
    • 2014-05-19
    • 2019-08-12
    • 2021-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多