【技术分享】理解SVG中的Viewport和ViewBox——拖动和缩放功能的实现(上)不同于以往将SVG视为一种图案(ICON或LOGO)的概念。在这篇文章中,我们将尝试将SVG视为一个画布(Canvas),我们可以像谷歌地图一样使用鼠标直接拖动和缩放这个画布。要把SVG当做画布,实现缩放或者拖动功能,首先需要了解SVG的很多基本概念,让我们一步一步来了解。注1:在本文中我们将把SVG当作画布(Canvas)来对待,而不是探索SVG中的单个元素(例如,)。注2:本文只考虑viewport和viewBox等比例的情况。最终实现的功能是这样的:实现SVG拖拽缩放理解SVG中的Viewport和ViewBox在SVG的世界里,空间的概念可以分为两个部分:Viewport和ViewBox。在本文中,我会将Viewport比作相框,将ViewBox比作照片。视口相对容易理解。就是相框的尺寸,也就是你眼睛能看到的范围。不管你的照片有多大,实际能看到的范围就是相框的大小。在网页中,我们可以通过设置视口来调整相框的大小。ViweBox可以认为是这张照片的大小。如果照片的尺寸与相框(视口)尺寸相同,就没有问题。您可以从相框查看相同尺寸的照片。但是如果照片(viewbox)比相框大或者小,这时候就比较麻烦了。您将需要更多地控制照片在相框上的排列方式以显示您想要的内容。要呈现的东西,所以ViewBox除了可以控制照片的大小外,还可以控制照片在相框中的摆放方式。先了解一下viewport和viewbox的概念:当viewBox等于viewport时(初始化情况),我们可以直接在SVG元素上定义viewport的宽高,也可以用CSS定义,基本上就是这个DOM元素的宽高而heightof就是viewport的宽度和高度,也就是你相框的宽度和高度。然后我们可以在SVG中定义我们的图案内容,这里我们以一只鸟为例。这时候你会得到如下视口:现在我们可以设置viewBox,viewBox的设置可以写在SVG标签上,设置属性包括这四个属性,即viewBox=''。刚才我们提到,在ViewBox中除了可以控制照片的大小外,还可以控制照片在相框中的摆放方式,其中和就是用来控制照片摆放方式的照片放在一个相框中,和是照片的大小。默认情况下(没有特别设置viewBox)viewBox的大小会和视口一样,所以当我们把小鸟的照片放到svg中的时候,它会自动填满整个相框,并且两个将是类似的,代码将如下所示:照片将完全融入相框。当viewbox小于viewport时:图案将被放大。通过viewBox的设置,我们可以进一步放大或缩小我们的照片。这里有一个原理,viewBox会自动填充viewport的大小*,很抽象,假设我的viewport一开始是800x400,现在我们可以让我们的viewBox的大小变成400x200通过viewBox的设置,当我们的照片尺寸设置小于相框时,它会裁剪原照片的一小块区域(本例为400x200),然后调整大小以填充整个视口(800x400)。分解过程是这样的(绿色是viewport,蓝色是viewBox)setviewBoxsmallerthanviewport:cropping:填充视口文本模板mdimg这时候会产生一个很神奇的现象,虽然我的照片是因为设置的尺寸sheet(viewBox)比原来尺寸小了,但是因为它会自动填满整个视口,所以照片实际上被放大了。代码如下所示,设置为viewBox="00400200":当viewbox大于viewport时:pattern会类似的缩小,当我们设置的viewBox大于viewPort时,会先放大底图照片(先放大到1600x800),然后尽可能塞进视口(这里是800x400):所以,虽然viewBox设置(1600x800)比原来的viewBox尺寸(800x400),buttheactual但是,照片的实际显示会按比例缩小。代码看起来像这样,viewBox="001600800":了解SVGViewBox位置的设置在viewBox的设置中,有四个属性值viewBox='',除了我们上面说的设置照片的大小外,还可以使用和这两个属性来设置照片的位置。例如,当我将viewBox的min-x设置为150(viewBox="1500800400")时,viewBox将向左移动150个单位:我们也可以同时设置min-x和min-y时间,例如(viewBox="-400-200800400"),你会得到这样的效果:最后你实际看到的是:viewBox的四个属性值中viewBox设置的影响设置viewBox="min-xmin-ywidthheight",我们可以简单理解为前两项min-x和min-y控制平移(translate),可以达到左右移动的效果;最后两项width和height控制缩放比例(scale)。但是因为viewBox实际上影响了SVG中的坐标系(SVG坐标系后面会解释),所以会与你的直觉相悖。例如,##当你将min-x和min-y设置得较大时,你实际看到的图片会移动到左上角##;同样,##当你把宽高设置的大一些,你实际看到的图片会缩小##。这部分需要你花一些时间去实际感受一下。强烈建议使用下一段中SaraSoueidan提供的实际案例经验。为了真正体验SVG的效果,SaraSoueidan在她的文章UnderstandingSVGCoordinateSystemsandTransformations(Part1)—Theviewport,viewBox,andpreserveAspectRatio中提供了一个很好的实践案例。在左上角可以通过拖拽设置viewBox的值,体验viewBox变化的视觉显示效果。另外,由于它的viewport是(800x600),所以建议先将viewBox的长宽设置为800x600(即初始化时默认viewport=viewBox),然后我们再实际操作看看viewBox的变化会有什么效果。当viewport和viewBox的大小不一样时:preserveAspectRatio我们提到当viewBox和viewport的大小不一样时,viewBox会尽量填满整个viewport,但是在上面文章的例子中,我们都把viewBox的大小设置成和viewPort一样的比例。如果是不同的比例,应该用什么方法对齐填充呢?这时候我们就需要用到preserveAspectRatio属性。在该属性中,可以设置对齐方式(align)和填充方式(meetorslice)。在这篇文章中,我只打算讨论viewBox和viewport比例相等的情况。我觉得以等比例的情况为例先练习一下比较容易理解viewport和viewBox的概念,因为在waitingratio的情况下,preserveAspectRation的值对屏幕的呈现是没有影响的。如果想进一步了解preserveAspectRatio这个属性,可以参考这篇文章([翻译]UnderstandingSVGCoordinateSystemandTransformations@Andyyou),或者进一步参考文末列出的参考文章。深入理解SVG坐标系从上面我们可以看出,当我们为SVG元素设置viewBox时,SVG会有很多特效。我们可以把整个SVG元素看成一个画布,对其进行缩放和移动,而实际上在SVG的世界里,我们需要明白viewport和viewBox实际上是在两个不同的坐标系中。在viewport中,就是我们过去熟悉的坐标系,主要是基于浏览器中的DOM。通常称为视口坐标系(viewportcoordinatesystem)或画布坐标系(但不要与HTML中的Canva标签混淆)。一般来说,在这个坐标系下,1px就是1px大,这个坐标系是比较固定的。这个坐标系是比较固定的。在以后的文章中,我将使用术语视口坐标系。在viewBox的坐标系中,并不是我们习惯的。我们一般把viewBox的坐标系称为SVG坐标系(SVGcoordinatesystem),用户坐标系(或者当前坐标系,使用中的用户空间)。在接下来的文章中,我将使用术语SVG坐标系。在此坐标系中,值不必有单位。如果我们不给它一个单位,它会默认使用视口的单位(例如px)。不过恐怖的特别之处在于,当我们设置viewBox时,如果对图片进行了缩放,那么它的1个单位大小就不再是1px了。识别不同的坐标名称为了帮助我们进一步探索SVG坐标系和视口坐标系,我们需要识别三个不同的坐标名称,即offset、client和SVGPoint。offset和client得到的值属于视口坐标系中的坐标值(即1px才是真正的1px)。两者的区别在于offset是相对于容器左上角的一个点,即容器的左上角为(0,0);而client是相对于窗口左上角(浏览器窗口左上角)的一个点,窗口左上角为(0,0),X值越右,则Y值越大。SVG坐标系有点特殊。它有自己的坐标点,可以通过视口坐标系的客户端坐标进行转换。我们将在下一篇文章中解释如何获取这三个坐标值,但是现在你需要知道有三个不同的坐标名称。当viewBox等于viewport时,我们使用SaraSoueidan提供的交互式示例进行更多说明。一开始,我将viewBox设置为与视口相同的大小。在这种情况下,SVG坐标系中1个单位的大小将与视口大小相同,即1px。注意蓝色尺子是SVG坐标系,灰色尺子是视口坐标系:同时我们在小鸟的右下角标出点,这样我们可以了解SVG坐标的变化系统以后。一开始,因为viewport等于viewBox,所以SVG坐标系中的这个点和viewport坐标系中的offset坐标点会是(200,300):当viewBox是viewport的一半大小时,我们可以看到,当我将viewBox设置为视口的一半时(viewBox="00400300"),也就是让小鸟看起来大一倍,那么SVG坐标系中的1个单位就会成为的视口2个单位(此处为2px)。但需要注意的是,虽然图案放大了两倍,小鸟的右下角在蓝色比例尺的SVG坐标系中也是(200,300),但是灰色比例尺的视口坐标系中的偏移坐标点比例将变为双倍,即(400,600)。当viewBox的大小是视口的两倍时也是如此。当我将viewBox设置为视口大小的两倍时(viewBox="001600800"),也就是让鸟看起来大一倍,那么SVG坐标系中的1个单位就会变成1/2个单位视口(此处为0.5px)。这时你会看到,虽然在蓝色尺子的SVG坐标系中,右下角的坐标仍然是(200,300),但是视口坐标系中的偏移坐标点变成了(100,150).重点总结这篇文章中,有几个重点是你要注意的:知道有两种不同的坐标系,viewport和SVG,知道有三种不同的坐标点,offset,client,SVGPoint,并且知道offset和client属于视口坐标系;SVGPoint属于SVG坐标系。我们知道缩放和移动效果可以通过viewBox的设置来实现。OXXO主页图片来源@TeamTreehouse