svg : viewBox + preserveAspectRatio 属性演示
<style>.ma p { margin: 10px 0; }
.ma svg { margin: 10px; border: 1px solid gray; }
.ma fieldset { margin: 10px; width: 400px; }
.ma input { margin: 10px 2px 10px 10px; }
.rred { color: red; }
</style>
<div class="ma">
<p>以下演示,左边的红色方框是 viewBox 属性的虚拟,具体值在演示下方有提供,右边是效果,不同的对齐参数和伸缩参数,连同 viewBox 的具体设置,均会影响 viewBox 的最终呈现效果。具体如何影响,请参阅 <a href="https://www.huachaowang.com/forum.php?mod=viewthread&tid=72139">理解 svg 的 viewBox 属性(二)</a>。</p>
<svg width="300" height="240">
<circle cx="100" cy="100" r="90" fill="olive" />
<rect id="vbRect1" x="10" y="10" width="61" height="169" fill="none" stroke="red" />
<circle cx="10" cy="10" r="5" fill="purple" />
<circle cx="71" cy="100" r="5" fill="purple" />
</svg>
<svg id="vbSvg" width="300" height="240" viewBox="10 10 61 169" preserveAspectRatio="xMidYMid meet">
<circle cx="100" cy="100" r="90" fill="olive" />
<rect id="vbRect2" x="10" y="10" width="61" height="169" fill="none" stroke="red" />
<circle cx="10" cy="10" r="5" fill="purple" />
<circle cx="71" cy="100" r="5" fill="purple" />
</svg>
<p>viewBox 代码:viewBox="<span id="vbox" class="rred">10 10 61 169</span>" preserveAspectRatio="<span id="ratio" class="rred">xMidYMid meet</span>"</p>
<fieldset>
<legend>设置viewBox参数</legend>
<input id="vb1" type="radio" value="10 10 61 169" name="vb" checked />
<label for="vb1" class="rred">10 10 61 169</label>
<input id="vb2" class="rdXym" type="radio" value="10 10 169 61" name="vb" />
<label for="vb2">10 10 169 61</label>
</fieldset>
<fieldset>
<legend>设置对齐参数</legend>
<input id="xym1" type="radio" value="xMinYMin" name="xym" />
<label for="xym1">xMinYMin</label>
<input id="xym2" type="radio" value="xMinYMid" name="xym" />
<label for="xym2">xMinYMid</label>
<input id="xym3" type="radio" value="xMinYMax" name="xym" />
<label for="xym3">xMinYMax</label>
<br>
<input id="xym4" type="radio" value="xMidYMin" name="xym" />
<label for="xym4">xMidYMin</label>
<input id="xym5" type="radio" value="xMidYMid" name="xym" checked />
<label for="xym5" class="rred">xMidYMid</label>
<input id="xym6" type="radio" value="xMidYMax" name="xym" />
<label for="xym6">xMidYMax</label>
<br>
<input id="xym7" type="radio" value="xMaxYMin" name="xym" />
<label for="xym7">xMaxYMin</label>
<input id="xym8" type="radio" value="xMaxYMid" name="xym" />
<label for="xym8">xMaxYMid</label>
<input id="xym9" type="radio" value="xMaxYMax" name="xym" />
<label for="xym9">xMaxYMax</label>
</fieldset>
<fieldset>
<legend>设置伸缩参数</legend>
<input id="rdMeet" name="meet" type="radio" value="meet" checked />
<label for="rdMeet"> meet :按短边比例伸缩</label>
<br>
<input id="rdSlice" name="meet" type="radio" value="slice" />
<label for="rdSlice"> slice :按长边比例裁剪</label>
</fieldset>
<p>【说明】</p>
<pre>
<span class="rred">meet</span> (默认值):
宽高比将会被保留
整个SVG的viewbox在视图范围内是可见的
尽可能地放大SVG的viewbox,同时仍然满足其他的条件
在这种情况下,如果图形的宽高比和视图窗口不匹配,则某些视图将会超出viewbox范围,
即SVG的viewbox视图将会比可视窗口小
<span class="rred">slice</span>:
宽高比将会被保留
整个视图窗口将覆盖viewbox
SVG的viewbox属性将会被尽可能的缩小,但是仍然符合其他标准
在这种情况下,如果SVG的viewbox宽高比与可视区域不匹配,则viewbox的某些区域将
会延伸到视图窗口外部,即SVG的viewbox将会比可视窗口大
</pre>
</div>
<script>
let rdXym = document.getElementsByName('xym'),
rdMeet = document.getElementsByName('meet'),
vbs = document.getElementsByName('vb');
let ratioNow = 'meet',
alignNow = 'xMidYMid',
vbNow = vb1.value;
let setAttr = () => {
vbSvg.setAttribute('viewBox',vbNow);
vbSvg.setAttribute('preserveAspectRatio', alignNow + ' ' + ratioNow);
ratio.innerText = alignNow + ' ' + ratioNow;
};
rdXym.forEach((item,key) => {
item.onclick = () => {
alignNow = item.value;
setAttr();
};
});
rdMeet.forEach((item,key) =>{
item.onclick = () => {
ratioNow = item.value;
setAttr();
};
});
vbs.forEach((item) => {
item.onclick = () => {
vbNow = item.value;
let vals = vbNow.split(' ');
let attrs = ['x','y','width','height'];
attrs.forEach((v,k) => {
vbRect1.setAttribute(v,vals);
vbRect2.setAttribute(v,vals);
});
setAttr();
};
});
</script>
这个在线演示好,可以直接看到不同设置的结果了{:4_199:} 在设置meet或slice,会让某一个方向被充满的,这时再调这个方向的大中小是没反应的。 红影 发表于 2023-10-31 14:07
在设置meet或slice,会让某一个方向被充满的,这时再调这个方向的大中小是没反应的。
当一个方向充满了,该方向的对齐调整就不会有响应。想一想在 Word 里,如果一行文字刚好占满整行,这时,对齐调整它会有响应吗? 山人 发表于 2023-10-31 16:05
当一个方向充满了,该方向的对齐调整就不会有响应。想一想在 Word 里,如果一行文字刚好占满整行,这时, ...
是的,这个比喻很恰当。谢谢山人{:4_187:} 红影 发表于 2023-10-31 14:07
在设置meet或slice,会让某一个方向被充满的,这时再调这个方向的大中小是没反应的。
原理:一个方向拉满了,该方向的任意一种对齐方式都一样 马黑黑 发表于 2023-10-31 17:06
原理:一个方向拉满了,该方向的任意一种对齐方式都一样
是的,所有的变化在没拉满的方向起作用。 红影 发表于 2023-10-31 20:45
是的,所有的变化在没拉满的方向起作用。
这是道理 马黑黑 发表于 2023-10-31 22:04
这是道理
这个帖子需要学的东西很多。 红影 发表于 2023-10-31 22:25
这个帖子需要学的东西很多。
多倒是不多,值的个数多但有规律,一弄懂就不用记了 马黑黑 发表于 2023-11-1 07:20
多倒是不多,值的个数多但有规律,一弄懂就不用记了
那个容易,是meet和slice理解透了不容易。 红影 发表于 2023-11-1 13:08
那个容易,是meet和slice理解透了不容易。
严格说说,meet和slice都伸缩,不同的是它们两个正好相反,meet保证短边完整,不剪裁,slice保证长边完整,剪裁多出的部分以充满对象 马黑黑 发表于 2023-11-1 19:35
严格说说,meet和slice都伸缩,不同的是它们两个正好相反,meet保证短边完整,不剪裁,slice保证长边完整 ...
嗯,都是充满,一个裁一个不裁,这样记最容易。 红影 发表于 2023-11-1 22:54
嗯,都是充满,一个裁一个不裁,这样记最容易。
充满不是绝对的,像 meet,以短边伸缩,保证viewBox选区在渲染目标上都可见,它不一定充满目标区域,且,选区以外的内容可能也可见 马黑黑 发表于 2023-11-2 07:36
充满不是绝对的,像 meet,以短边伸缩,保证viewBox选区在渲染目标上都可见,它不一定充满目标区域,且, ...
我说的是按选择参数的充满,不是图案的充满啊。 红影 发表于 2023-11-2 10:34
我说的是按选择参数的充满,不是图案的充满啊。
额 马黑黑 发表于 2023-11-2 11:54
额
这个好像是这样吧{:4_173:} 红影 发表于 2023-11-2 14:00
这个好像是这样吧
大约吧,我也不清楚 马黑黑 发表于 2023-11-2 20:01
大约吧,我也不清楚
我是跟着感觉走{:4_173:} 红影 发表于 2023-11-2 21:44
我是跟着感觉走
挺好呢