奇怪的对角线 viewBox SVG 行为

问题描述

试图弄清楚这个 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,10*1,7*2
<svg viewBox="0 0 10 14">
      <use href="#Atom"/>
      <use href="#Atom" y="7"/> 
</svg>

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

//"diagonal" stack ->viewBox = 0,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 的宽度和高度都是原始的两倍。这不起作用。

strange behaviour screenshot

正如你从图片中看到的那样,符号都被弄乱了(好像我有一个错误的 viewBox)

This 是我正在寻找的东西(尽管您可以看到我正在使用溢出:可见并且符号从视图框中消失)

kinda expected result

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

这是玩这个东西的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>

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...