蚂蚁部落

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 75|回复: 3

[SVG进阶教程] SVG viewbox和preserveAspectRatio详解

[复制链接]
发表于 2016-12-13 10:07:56 | 显示全部楼层 |阅读模式
本帖最后由 antzone 于 2016-12-14 22:11 编辑

SVG viewbox和preserveAspectRatio详解:
在默认情况下,用户坐标系统和视窗坐标系统是完全重合的,具体可以参阅SVG 坐标系统详解一章节。
使用transform属性可以创建新的当前用户坐标系统,具体可以参阅以下两篇文章:
(1).SVG transform用法详解一章节。
(2).SVG transform变换深入理解一章节。
其实采用viewbox属性也可以创建新的当前用户坐标系统,下面就通过代码实例对此属性的使用做一下详细介绍。
首先看一段代码实例:
[HTML] 纯文本查看 复制代码运行代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>蚂蚁部落</title>
<style>
* {
  margin:0px;
  padding:0px;
}
svg {
  border:1px solid blue;
  width:400px;
  height:200px;
  margin:100px;
  overflow:visible;
}
</style>
</head>
<body>
  <svg viewBox="0 0 200 100">
    <rect 
          x="10" y="5" 
          width="20" height="20" 
          fill="blue" />
  </svg>                     
</body>
</html>

创建一个宽高分别为20px的矩形,然而实际的表现却是尺寸明显大于20px。
之所以出现上面的效果,就是viewBox属性的原因。
语法结构如下:
[XML] 纯文本查看 复制代码
viewBox="<min-x>, <min-y>, <width>, <height>"

特别说明:参数之间即可用逗号分隔也可以用空格分隔。
参数解析:
(1).<min-x>和<min-y>:规定viewBox的左上角左上角的坐标。
(2).<width>和<height>:规定viewBox的尺寸。
看了上面的代码和语法结构,可能对viewBox属性的作用还是一头雾水,不要着急下面分布进行介绍:
如果没有应用viewBox属性,那么代码的表现如下:
1.jpg
我们暂且称呼由viewBox定义的矩形为"视框",如果将这个视框也绘制出来,那么效果如下:
2.jpg
最后,红色框会逐渐放大,直到填满整个视窗,里面的蓝色矩形也会跟随同比例放大,演示效果如下:
[HTML] 纯文本查看 复制代码运行代码
<!doctype html><html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>蚂蚁部落</title>
<style>
* {
  margin:0px;
  padding:0px;
}
svg {
  border:1px solid blue;
  width:400px;
  height:200px;
  margin:100px;
  overflow:visible;
}
#rect{
  animation:rect 2s forwards; 
}
@keyframes rect{ 
  from {
    transform:scale(1)

  } 
  to {
    transform:scale(2)
  } 
} 
#box{
  animation:box 2s forwards; 
}
@keyframes box{ 
  from {
    width:200px;
    height:100px;

  } 
  to {
     width:400px;
    height:200px;
  } 
}
</style>
</head>
<body>
  <svg>
    <rect id="rect"
          x="10" y="5"
          width="20" height="20"
          fill="blue" />

    <rect id="box"
          x="0" y="0"
          width="200"
          height="100"
          fill="none"
          stroke="red" />
  </svg>                     
</body>
</html>

特别说明:上面代码为了便于对viewBox属性理解进行的动画演示,不要关注代码的实质内容。
通过上面的代码我们可以对viewBox得出一个通俗的理解,那就是通过"视框"进行适当的矩阵变换以适应指定区域的边界(通常是视窗)。
<min-x>和<min-y>规定的是transform:translate()变换,<width>和<height>规定的是transform:scale()变换。
在上面的代码中,viewBox属性值前两个参数都是0,所以进行的是transform:scale(2)缩放变换。
再来看一段代码实例:
[HTML] 纯文本查看 复制代码运行代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>蚂蚁部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border: 1px solid blue;
  width: 400px;
  height: 200px;
  margin: 100px;
  overflow: visible;
}
</style>
</head>
<body>
  <svg viewBox="-10 -10 200 100">
    <rect
          x="10" y="5"
          width="20" height="20"
          fill="blue" />
  </svg>
</body>
</html>

将viewBox属性值前两个参数设置为-10;下面看此效果原理动画演示:
[HTML] 纯文本查看 复制代码运行代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>蚂蚁部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border: 1px solid blue;
  width: 400px;
  height: 200px;
  margin: 100px;
  overflow: visible;
}
#rect{
  animation:rect 4s forwards; 
}
@keyframes rect{ 
  0% {
    transform:translate(0,0) scale(1)
  }
  50% {
    transform:translate(10px,10px) scale(1);
  }
  100% {
    transform:translate(10px,10px) scale(2);
  } 
} 
#box{
  animation:box 4s forwards; 
}
@keyframes box{ 
  0% {
    transform:translate(0,0)
  }  
  50% {
    transform:translate(10px,10px);
    width:200px;
    height:100px;
  }
  100% {
    transform:translate(10px,10px);
    width:400px;
    height:200px;
  } 
}
</style>
</head>
<body>
  <svg>
    <rect id="rect"
          x="10" y="5"
          width="20" height="20"
          fill="blue" />
    <rect id="box"
          x="-10" y="-10"
          width="200" height="100"
          fill="none"
          stroke="red"/>
  </svg>
</body>
</html>

特别说明:上面代码为了便于对viewBox属性理解进行的动画演示,不要关注代码的实质内容。
更为通俗的讲,我们可以认为viewBox创建一个放置在画布上的框,有一些图案会位于这个框中,然后移动这个框(框中的图案会跟随移动),让框的左上角与视窗的左上角对齐,然后进行缩放操作;总之,viewBox创建了一个新的用户坐标系,应用此属性的元素的后代会在这个新的用户坐标系中定位和确定尺寸,而不是初始坐标系。
preserveAspectRatio属性:
在上面的代码中,viewBox创建的"视框"的尺寸和SVG视窗是等比例的,也就是能够在保证宽高比的情况下,恰好缩放填满视窗。
但是在实际应用中,总会有比例不相等的情况,这时,preserveAspectRa属性的作用就体现出来了。
语法结构:
[XML] 纯文本查看 复制代码
preserveAspectRatio = defer? <align> <meetOrSlice>?

defer参数是可选的,只有当在<image>应用preserveAspectRatio才被用到,不是本文的关键,暂且不管。
参数解析:
(1).align:规定viewBox如何与SVG viewport对齐方式。
(2).meetOrSlice:可选,规定如何维持高宽比。
先看一个简单的代码片段:
[XML] 纯文本查看 复制代码
preserveAspectRatio="xMidYMid meet"

从xMidYMid(默认值)可以看出,对齐方式的确定需要横向和纵向共同完成。
分解如下:
(1).xMin:viewport和viewBox左边对齐。
(2).xMid:viewport和viewBox x轴中心对齐。
(3).xMax:viewport和viewBox右边对齐。
(4).YMin:viewport和viewBox上边缘对齐。
(5).YMid:viewport和viewBox y轴中心点对齐。
(6).YMax:viewport和viewBox下边缘对齐。
特别说明:注意大小写,和驼峰命名规则相同。
再来看meetOrSlice参数:
(1).meet:默认值,保持纵横比缩放viewBox适应viewport。
(2).slice:保持纵横比同时比例小的方向放大填满viewport。
(3).none:扭曲纵横比以充分适应viewport。
这应该是很好理解的,看一个简单的代码实例:
[HTML] 纯文本查看 复制代码运行代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>蚂蚁部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border: 1px solid blue;
  width: 400px;
  height: 200px;
  margin: 100px;
  overflow: visible;
}
</style>
</head>
<body>
  <svg 
       viewBox="0 0 200 50"
       preserveAspectRatio="xMinYMin meet">
    <rect
          x="0" y="0"
          width="200" height="50"
          fill="blue" />
  </svg>
</body>
</html>

为了便于观察出效果,我们将rect的尺寸和viewBox的尺寸设置为相同。
xMinYMin表示viewBox创建的视框与视窗左上对齐,meet表示保持纵横比例进行缩放,只要横向或者纵向一遍填充满视窗即可。
再来看一段代码实例:
[HTML] 纯文本查看 复制代码运行代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>蚂蚁部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border: 1px solid blue;
  width: 400px;
  height: 200px;
  margin: 100px;
  overflow: visible;
}
</style>
</head>
<body>
  <svg 
       viewBox="0 0 200 50"
       preserveAspectRatio="xMinYMin slice">
    <rect
          x="0" y="0"
          width="200" height="50"
          fill="blue" />
  </svg>
</body>
</html>

slice表示保持纵横比例进行缩放,但是需要比例小的方向放大填满viewport。
其他属性就不挨个演示了,比较简单,大家自行测试即可。
发表于 2016-12-20 10:32:48 | 显示全部楼层
这篇文章完美,收藏了
发表于 2016-12-24 10:58:05 | 显示全部楼层
真是太复杂了
发表于 2017-1-10 15:49:31 | 显示全部楼层
此文章必然会大火

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复返回顶部 返回列表