这个问题是由以下重要主题引起的,该主题是将近半年前在一个好问题中提出的。 浏览器是否绘制画布 SVG 范围之外的内容?
相互之间的交互是viewport一个viewBox相当复杂的问题,但它是理解 SVG 并在网页的布局和动画中成功使用它的基础。我已经研究过很多关于这个主题的国外互联网资源,当然,首先是w3C规范,但我不是以英语为母语的人,而且在我看来,那里的规定有些令人困惑。下面我将举例说明我是如何理解这个交互过程viewport的viewBox。
viewport是一个视口,是用户在其小工具显示屏上看到的无限 SVG 画布的一部分。比方说,视口尺寸;- width="1000" height="600" 指定原点在左上角的 SVG 文件的作者。
viewBox - 例如 - viewBox="0 0 500 300" 是用户看不到的虚拟矩形视口,但它决定了在用户显示器上显示多少无限 SVG 画布。此外,最后两个 viewBox 属性负责缩放图像。在这里阅读更多。
使用 viewBox 选择 SVG 画布片段,然后转换片段并将其呈现在用户显示器上的过程很有趣。 下面是一个解释图。
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="500" height="500" id="svg5452" version="1">
<defs>
<filter id="filter5435-6" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="1" id="feGaussianBlur5437-8"/>
</filter>
</defs>
<g id="layer1" transform="translate(0,-552.362)">
<path d="M33 752 405 567l0 0" id="path2995" style="fill:#fc0;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.3;stroke:#000"/>
<path d="m95 706 184-106 0 248-184 106z" id="path5419" transform="matrix(1.4874974,0,0,1.2712695,-7.6174194,-192.77799)" style="fill:#b3b3b3;filter:url(#filter5435-6)"/>
<path d="m132 567 0 450 0 0 0 0" id="path2993" style="fill:#fc0;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.4;stroke:#000"/>
<path d="m134 703 68-34 0 68-68 34z" id="path2999" style="fill:#94cc00;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.4;stroke:#000"/>
<path d="m347 818-212-113 0 0 0 0" id="path5215" style="fill:#b3b3b3;stroke-dasharray:0.7;stroke-dashoffset:2.8;stroke-linecap:round;stroke-width:1.4;stroke:#efd900"/>
<path d="m348 818 43-20 0 39-43 20z" id="path2997" style="fill:#fc0;stroke-dashoffset:25;stroke-linecap:round;stroke-width:0.8;stroke:#000"/>
<path d="m348 849-215-84 0 0 0 0" id="path5217" style="fill:none;stroke-dashoffset:4.3;stroke-linecap:round;stroke-width:1.4;stroke:#efd900"/>
<path d="m201 737 0 0 0 0 190 100-36-19" id="path5221" style="fill:#f10000;stroke-dashoffset:22.2;stroke-width:1.5;stroke:#ed0"/>
<path d="m391 798-189-129 0 0 0 0" id="path5219" style="fill:none;stroke-dashoffset:20.7;stroke-width:1.4;stroke:#f7f100"/>
<path d="m458 861-64-60 0 0 0 0" id="path3810" style="fill-opacity:0.9;fill:#8b91df;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.4;stroke:#000"/>
<path d="m462 869-85-50 0 0 0 0" id="path3812" style="fill-opacity:0.9;fill:#8b91df;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.4;stroke:#000"/>
<path d="m454 873-92-34 0 0" id="path3814" style="fill-opacity:0.9;fill:#8b91df;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.3;stroke:#000"/>
<path d="M454 876 352 851" id="path3816" style="fill-opacity:0.9;fill:#8b91df;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.2;stroke:#000"/>
<g id="g4066" transform="matrix(0.38032348,0,0,0.37761044,232.98885,603.74368)">
<path id="path3804" d="m526 751c0 0 20-14 67-14 56 0 67 25 67 25l0 0 0-1" style="fill:none;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.5;stroke:#000"/>
<g id="g4055">
<g id="g3872" transform="matrix(0.97932405,0.21454349,-0.03440915,0.93598881,14.984082,-76.741419)">
<g transform="matrix(0.96020224,0,0,1.0308731,23.199143,-22.772714)" id="g3863">
<path id="path3806" d="m374 326c0 16-5 29-10 29-6 0-10-13-10-29 0-16 5-29 10-29 6 0 10 13 10 29z" transform="matrix(1.2648349,0.71565329,-0.73419562,1.4071283,388.66074,-23.50662)" style="fill-opacity:0.9;fill:#8b91df;stroke:#000"/>
<g id="g3856">
<path id="path3034" d="m628 605c0 0-3 27 14 74 21 56 44 55 44 55l0 0-1 0" style="fill:none;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.5;stroke:#000"/>
<path transform="matrix(1.2648349,0.71565329,-0.73419562,1.4071283,389.06784,-30.56644)" d="m365 329c0 7-2 13-4 13-2 0-4-6-4-13 0-7 2-13 4-13 2 0 4 6 4 13z" id="path3808" style="fill:#2f003b;stroke:#000"/>
<g id="g3852">
<text xml:space="preserve" x="245" y="256" id="text3848" transform="scale(2,2)" style="-inkscape-font-specification:Rosewood Std Regular;fill:#000;font-family:Rosewood Std Regular;font-size:64;letter-spacing:0;line-height:125;word-spacing:0">
<tspan y="256" x="245" id="tspan3850"/>
</text>
</g>
</g>
</g>
</g>
</g>
</g>
<text xml:space="preserve" x="178" y="1320" id="text3906" transform="matrix(1.3253407,-0.71279682,0.02282854,0.74224528,0,0)" style="-inkscape-font-specification:Minion Pro Cond Bold;fill:#000;font-family:Minion Pro Cond;font-size:32;font-weight:bold;letter-spacing:0;line-height:125;word-spacing:0">
<tspan id="tspan3908" x="178" y="1320">
viewBox
</tspan>
</text>
<path d="m451 867-81-37" id="path4020" style="fill-opacity:0.9;fill:#8b91df;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.1;stroke:#000"/>
<text xml:space="preserve" x="821" y="-182" id="text4079" transform="matrix(0.24480584,0.87602428,-0.94306552,0.71016161,0,0)" style="-inkscape-font-specification:Minion Pro Cond Bold;fill:#000;font-family:Minion Pro Cond;font-size:30.4;font-weight:bold;letter-spacing:0;line-height:125;word-spacing:0">
<tspan id="tspan4081" x="821" y="-182">
8
</tspan>
</text>
<path d="m405 566-18 7 4 3z" id="path5286" style="fill-opacity:0.9;fill:#0b0fdb;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.4;stroke:#000"/>
<path d="m132 1017 3-15-6 0z" id="path5288" style="fill-opacity:0.9;fill:#0207df;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.4;stroke:#000"/>
<text transform="matrix(0.46123189,0.67913613,-1.0097074,0.6813736,0,0)" id="text5290" y="364" x="1089" xml:space="preserve" style="-inkscape-font-specification:Minion Pro Cond Bold;fill:#000;font-family:Minion Pro Cond;font-size:30.8;font-weight:bold;letter-spacing:0;line-height:125;word-spacing:0">
<tspan y="364" x="1089" id="tspan5292">
8
</tspan>
</text>
<text xml:space="preserve" x="164" y="622" id="text5294" transform="matrix(0.83410914,-0.33044431,-0.00717685,1.2017271,0,0)" style="-inkscape-font-specification:Minion Pro Cond Bold;fill:#000;font-family:Minion Pro Cond;font-size:28.4;font-weight:bold;letter-spacing:0;line-height:125;word-spacing:0">
<tspan id="tspan5296" x="164" y="622">
(0,0)
</tspan>
</text>
<path id="path4013" d="m359 675 32-16 0 32-32 16z" style="fill:#fc0;stroke-dashoffset:25;stroke-linecap:round;stroke-width:0.7;stroke:#000"/>
<path d="m378 778-1-72 0 0" id="path4015" style="fill:#fc0;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.4;stroke:#000"/>
<path d="m377 707-6 23 15 0z" id="path4461" style="fill:#fc0;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.5;stroke:#000"/>
<g id="g4487" transform="matrix(1.4874974,0,0,1.2712695,-0.61034849,-201.51524)">
<path d="m220 827-48 27 0 0" id="path4472" style="fill:#fc0;stroke-dashoffset:25;stroke-linecap:round;stroke-width:0.9;stroke:#000"/>
<path d="m172 855 18-5-4-8z" id="path4474" style="fill:#fc0;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1;stroke:#000"/>
</g>
<path d="m135 860 68-34 0 68-68 34z" id="path4493" style="fill:none;stroke-dashoffset:25;stroke-linecap:round;stroke-width:4.9;stroke:#000"/>
<path id="path4491" d="m170 891 68-34 0 68-68 34z" style="fill-opacity:0.9;fill:#ffcc0f;stroke-dashoffset:25;stroke-linecap:round;stroke-width:1.4;stroke:#000"/>
<path d="m315 637 32-16 0 32-32 16z" id="path4498" style="fill:none;stroke-dashoffset:25;stroke-linecap:round;stroke-width:4.9;stroke:#000"/>
<text xml:space="preserve" x="-22" y="784" id="text4596" transform="matrix(0.94153265,-0.49180502,0.20084042,0.95719004,0,0)" style="-inkscape-font-specification:Minion Pro Cond Bold;fill:#000;font-family:Minion Pro Cond;font-size:32;font-weight:bold;letter-spacing:0;line-height:125;word-spacing:0">
<tspan id="tspan4598" x="-32" y="754">
viewport
</tspan>
</text>
</g>
</svg>
viewBox 可以放置在 SVG 画布上的任何位置。它的位置取决于前两个属性:min-x、min-y。
接下来是抓取 viewBox 下面画布的 SVG 片段ом。
下一步是将 viewBox 的坐标系与视口坐标系的原点对齐。并将 viewBox 捕获的图像片段ом传回视口。审批流程正在进行中,以下是选项:
如果min-x = 0和min-y = 0,视口
а的宽度和高度分别等于 viewBox 的宽度和高度а,则片段图像不会移动或缩放。如果 viewBox 向右移动 - min-x > 0则图像向左移动。很明显,通过捕获视口右侧的图像,然后将其与原点组合,我们从而将图像向左移动。
如果 viewBox 移动到视口下方
a- min-y > 0图像将向上移动。
缩放取决于 viewporta和 viewBox的纵横比а
- 如果宽高比viewport / viewBox > 1 - 原始 SVG 片段的比例会按比例增加。
假设 viewBox 是视口大小的一半。因此,当将 viewBox 与视口组合在一起时,viewBox 的一个像素被拉伸到视口的 2 个像素。
当viewport / viewBox < 1 - 图像缩小。
比视口大的 viewBox 捕获整个视口和 SVG 画布的相邻部分,然后将其全部压缩回视口。
我再说一遍,用户在显示器上看到了一幅图像,经过所有变换后,它进入了视口。你可以推导出一个容易记住的规则:
viewBox 则相反。
因此,如果我们将 viewBox 向右移动 - min-x > 0,那么图像将向左移动。
如果我们增加 viewBox,那么图像就会缩小。
基于此,想到可以不使用CSS、JavaScript实现水平和垂直视差。为此,您只需沿着 SVG 画布移动 viewBox,如下图所示。单击开始按钮。
顶部窗口是用户看到的视口,彩色条是 SVG 画布。
水平视差的实现-这里<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" width="600" height="360" viewBox="0 0 600 360" > <title> Explanation horizontal of parallax viewBox </title> <desc> animate the horizontal parallax svg-art.ru by modifying a coordinate of the viewBox </desc> <defs> <g id="canvas-svg" stroke-width="2px"> <g id="canvas-frame1"> <rect id="v-port1" x="25" y="200" width="110" height="110" stroke="skyblue" fill="yellowgreen" /> <text id="t-port1" x="75" y="255" style="font-size: 16pt;">1 </text> <text x="26" y="303" > 0 </text> </g> <g id="canvas-frame2"> <rect id="v-port2" x="135" y="200" width="110" height="110" stroke="skyblue" fill="dodgerblue" /> <text id="t-port2" x="185" y="255" style="font-size: 16pt;">2 </text> <text x="136" y="303" > 1168 </text> </g> <g id="canvas-frame3"> <rect id="v-port3" x="245" y="200" width="110" height="110" stroke="skyblue" fill="crimson" /> <text id="t-port3" x="295" y="255" style="font-size: 16pt;">3 </text> <text x="246" y="303" > 2336 </text> </g> <g id="canvas-frame4"> <rect id="v-port4" x="355" y="200" width="110" height="110" stroke="skyblue" fill="orange" /> <text id="t-port4" x="405" y="255" style="font-size: 16pt;">4 </text> <text x="356" y="303" > 3504 </text> </g> <g id="canvas-frame5"> <rect id="v-port5" x="465" y="200" width="110" height="110" stroke="skyblue" stroke-width="1px" fill="yellow" /> <text id="t-port5" x="515" y="255" style="font-size: 16pt;">5 </text> <text x="466" y="303" > 4672 </text> </g> </g> </defs> <g id="first-rect"> <rect x="25" y="25" width="110" height="110" stroke="skyblue" stroke-width="1px" fill="yellowgreen" /> <text x="75" y="85" style="font-size: 16pt;">1 </text> <text x="26" y="135" > 0 </text> </g> <desc>The SVG canvas is infinite in size. In our example, user a viewport of SVG is in the leftmost position.</desc> <use xlink:href ="#canvas-svg" x="0" y="0"> </use> <desc> viewBox is moved along canvas SVG</desc> <g id="viewBox1"> <rect id="v-box" x="25" y="200" width="110" height="110" stroke="skyblue" stroke-width="5px" fill="none" /> <text id="t-port1" x="45" y="225" style="font-size: 16pt; fill:blue;">viewBox </text> <animateTransform attributeName="transform" type="translate" begin="startButton.click+0.5s" end="stopButton.click" dur="20s" from="0 0" to="440 0" repeatCount="indefinite" restart="whenNotActive" fill="freeze"/> </g> <desc> The image moves to the left viewport</desc> <use xlink:href ="#canvas-svg" x="0" y="0"> <animateTransform attributeName="transform" type="translate" begin="startButton.click+0.5s" end="stopButton.click" dur="20s" from="0 -170" to="-440 -170" repeatCount="indefinite" restart="whenNotActive" fill="freeze" /> </use> <desc> Grey background image of the canvas SVG</desc> <g fill="#E5E5E5" stroke="#E5E5E5"> <rect x="135" y="0" width="465" height="195" /> <rect x="0" y="0" width="25" height="195" /> <rect x="0" y="0" width="135" height="30" /> <rect x="25" y="135" width="135" height="60" /> <rect x="0" y="315" width="600" height="85" /> <rect x="0" y="195" width="25" height="120" /> <rect x="575" y="195" width="25" height="120" /> </g> <g stroke-width="1px" stroke-dasharray = "5 5"> <line x1="25" y1="140" x2="25" y2="195" stroke="blue" /> <line x1="135" y1="140" x2="135" y2="195" stroke="blue" stroke-width="1px" /> </g> <g style="font-size: 16pt; fill:blue;"> <text x="45" y="170" > viewport </text> <text x="15" y="20" style="font-size: 14pt;"> display the user's </text> <text x="230" y="90" style="font-size: 40pt; fill:#1E90FF"> canvas SVG </text> </g> <g id="startButton"> <rect x="520" y="325" rx="8" ry="8" width="60" height="20" fill="#58AE2A" /> <text x="550" y="340" font-size="16" font-weight="bold" font-family="Arial" text-anchor="middle" fill="white" >Start</text> </g> <g id="stopButton"> <rect x="450" y="325" rx="8" ry="8" width="60" height="20" fill="#1E90FF" /> <text x="480" y="340" font-size="16" font-weight="bold" font-family="Arial" text-anchor="middle" fill="white" >Stop</text> </g> </svg>在我们网站上与 enSO 的翻译文章中
viewport也有一个实际的交互示例。viewBox
以上是交互
viewport和的例子viewBox。当 SVG 文档只有
viewport,但viewBox没有注册时会发生什么?svg version="1.1" width="1280" height="1024"
1. 调整父容器或浏览器窗口大小时不会发生图像缩放。
该命令
preserveAspectRatio也将不起作用。顺便说一下,这是摆脱它的唯一方法,因为即使它没有写在 SVG 文件的标题中,默认情况下它也会有值xMidyMidviewBoxsvg version="1.1" viewBox = "0 0 640 516"
在这种情况下,它
viewport取浏览器窗口宽度和高度的100%的默认值。缩放成为可能。图像比例是根据浏览器窗口的高度和分别计算的viewBox。也就是说,当减少 时viewBox,我们会增加显示器上的图像,因为我们不会改变显示器的大小。反之亦然 - 通过缩小浏览器窗口,我们缩小了图像的大小。命令 -
preserveAspectRatio激活。下面是三个示例,说明当图像的属性发生变化时它如何影响图像的定位。preserveAspectRatio="xMinYMin meet"preserveAspectRatio="xMidYMid meet"preserveAspectRatio1="xMaxYMax meet"1. 使用 viewport 和 viewBox 在缩放时隐藏、显示图像的示例
viewport / viewBox < 1,图像相对于浏览器窗口缩小了。在示例中:
300 / 2700 = 1/9即图像会占据可见画布svg的九分之一,
(300х300)因为svg的原点是左上角,那么缩小后的图像就会在那里。viewBox从 2700 减小到 300,即减小到 size ,则viewport图像将从九分之一增大到完整尺寸。其中
viewport / viewBox = 1viewBox 调整大小动画由命令执行:
下面是一个完整的代码示例。
单击矩形上的任意位置以启动动画。
2.使用位图动画的例子
*.png让我们将图标添加到 svg 形状:下面是整个代码: