奇怪的对角线 viewBox SVG 行为

Strange diagonal viewBox SVG Behaviour

试图弄清楚这个 svg viewBox 是如何工作的,但遗憾的是下面的代码打破了我们所知道的所有逻辑,哈哈。请有人解释这是错误还是正确的 svg 行为。我看不出我哪里错了...

<svg class="symbol"><symbol id="Atom" preserveAspectRatio="xMinYMin meet" viewBox="0 0 10 7"><path d="M3 6 4 7 6 7 4 4 5 3 8 7 10 7 5 0 0 7 2 7Z"></path></symbol></svg>

这是我的 svg 符号,我正在尝试堆叠更多符号(水平和垂直)

//vertical stack ->viewBox = 0, 0, 10*1, 7*2
<svg viewBox="0 0 10 14">
      <use href="#Atom"/>
      <use href="#Atom" y="7"/> 
</svg>

//horizontal stack ->viewBox = 0, 0, 10*2, 7*1
<svg viewBox="0 0 20 7">
      <use href="#Atom"/>
      <use href="#Atom" x="10"/>    
</svg>

//"diagonal" stack ->viewBox = 0, 0, 10*2, 7*2
<svg viewBox="0 0 20 14">
      <use href="#Atom"/>
      <use href="#Atom" x="10"/>
      <use href="#Atom" y="7"/>
</svg>

第一个是垂直的 2 个符号,所以我保留了与符号相同的 viewBox,但将高度从 7 加倍到 14。效果很好。

第二个是水平的 2 个符号,所以我保留了与符号相同的 viewBox,但将宽度从 10 加倍到 20。效果也很好。

第三个是水平2个符号,垂直2个符号,使viewBox的宽度和高度都是原来的两倍。这是行不通的。

正如您从图像中看到的那样,符号变得更加混乱(似乎我的 viewBox 有误)

This 有点像我正在寻找的东西(尽管如您所见,我正在使用溢出:可见并且符号超出了视图框)

有人可以解释一下我在这里犯了什么错误吗?非常感谢任何帮助。

这里有一个 codepen 用来玩这个东西

你的符号想要全宽或全高 当你只拉伸视口的一个维度时,它会很好地适应,因为它占据了整个宽度或高度,并且停止向另一个方向拉伸,因为它想保持纵横比。

但在这个 svg 视口中比符号大 2 倍,所以它可以全部使用

这是简单的解决方案

.svg {
  max-width: 200px;
  border: 1px solid red;
}
<svg class="svg" viewBox="0 0 20 14">
    <use href="#Atom" x="0" y="0"  width="50%" />
    <use href="#Atom" x="0" y="7"  width="50%" />
    <use href="#Atom" x="10" y="0" width="50%" />
    <use href="#Atom" x="10" y="7" width="50%" />
</svg>
<svg class="symbol"><symbol id="Atom" preserveAspectRatio="xMinYMin meet" viewBox="0 0 10 7"><path d="M3 6 4 7 6 7 4 4 5 3 8 7 10 7 5 0 0 7 2 7Z"></path></symbol></svg>


更新:

如果您不想手动将 width 添加到 use 标签并且您正在以编程方式创建它们(我假设您使用 javascript 但您可以使用相同的逻辑对于其他语言)你只想计算视口中的行和列并计算每个 use

的宽度和高度

这里有一个例子

const config = {
    svg: {
        width: 20,
        height: 14,
        rows: 2,
        cols: 2,
        symbol: '#Atom'
    }
}
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('viewBox', '0 0 '+config.svg.width+' '+config.svg.height);

for (let i = 0; i < config.svg.rows; i++) {
    for (let j = 0; j < config.svg.cols; j++) {
        const xPosition = (config.svg.width / config.svg.rows) * i;
        const yPosition = (config.svg.height / config.svg.cols) * j;

        const width = (100 / config.svg.rows);
        const height = (100 / config.svg.cols);

        const svgUse = document.createElementNS('http://www.w3.org/2000/svg', 'use');
        svgUse.setAttribute('href', config.svg.symbol);
        svgUse.setAttribute('x', xPosition);
        svgUse.setAttribute('y', yPosition);
        svgUse.setAttribute('width', width + '%');
        svgUse.setAttribute('height', height + '%');

        svg.append(svgUse);
    }
}

document.body.prepend(svg)
<!DOCTYPE html>
<html lang="en" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <svg class="symbol"><symbol id="Atom" preserveAspectRatio="xMinYMin meet" viewBox="0 0 10 7"><path d="M3 6 4 7 6 7 4 4 5 3 8 7 10 7 5 0 0 7 2 7Z"></path></symbol></svg>
    </body>
</html>

所以我最后回复了自己,但我真的要感谢@ciekals11 的输入。

获得我想要的结果的解决方案是在我的符号中指定宽度和高度属性。这使一切都完美无缺。不知道为什么它确实需要这个,但无论如何我会再次分享我的符号,这样你就可以看到区别了。

<svg class="symbol"><symbol width="10" height="7" id="Atom" preserveAspectRatio="xMinYMin meet" viewBox="0 0 10 7"><path d="M3 6 4 7 6 7 4 4 5 3 8 7 10 7 5 0 0 7 2 7Z"/></symbol></svg>