问题描述
试图弄清楚这个 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 的宽度和高度都是原始的两倍。这不起作用。
正如你从图片中看到的那样,符号都被弄乱了(好像我有一个错误的 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>