2.1.SVG世界、视野、视窗的概念
viewBox的参数分别代表起点x,y,宽高width,height。并且皆是针对世界坐标系而言。
世界是客观无穷的,所以本质上不可能在浏览器上展示,所以定义一个视窗用来展示,而视野(viewBox)则是我们所看到的世界的样子(这个对于学过图形学的应该很好理解)。视窗和视野的单位尺度不同,也就是说,无论我们定义多大的视野,视窗的大小该是多少就是多少,不会随之改变(我们画图所用坐标是世界坐标,和视野是一个尺度)。
视窗是视野的容器。
以以下代码进行举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>第一个SVG示例</title>
<style>
svg{
position: absolute;
border: 1px solid green;
width: 300px;
height: 200px;
left: 50%;
top: 20%;
transform: translateX(-50%);
background: #CCCCCC;
}
</style>
</head>
<body>
<h1>Hello SVG!</h1>
<div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
<!--face-->
<circle cx="100" cy="100" r="90" fill="#39f"></circle>
<!--eye-->
<circle cx="70" cy="80" r="20" fill="white"></circle>
<circle cx="130" cy="80" r="20" fill="white"></circle>
<circle cx="65" cy="75" r="10" fill="balck"></circle>
<circle cx="125" cy="75" r="10" fill="balck"></circle>
<!--smile-->
<path d="M 50 140 A 60 60 0 0 0 150 140" stroke="white" stroke-width="3" fill="none"></path>
<!--boder-->
<polygon points="0 0 400 0 400 400 0 400" stroke="blue" stroke-width="2" fill="none"></polygon>
</svg>
</div>
</body>
</html>
效果图:
preserveAspectRatio的属性
preserveAspetRation属性和viewBox属性配合使用。viewBox属性值可以指明graphic element是否可以等比例缩放(宽高比相同的情况下)以扩展到viewport指定的大小区域中。
preserveAspetRation属性指出了如何缩放及如果对齐viewBox到viewport上
- 注意:如果没有指定viewBox属性,那么此属性是会被忽略的,它的默认值为xMidYMid meet。
preserveAspectRation的参数为[defer]<align>[meetOrSlice],[]代表可选:
-
defer这个参数只对image标签有效,这里不做讨论。
-
meetOrSlice的默认值是meet
- meet: viewBox保持缩放比;整个viewBox在viewport中可见;在满足前2个约束条件的基础上,尽可能的缩小viewBox。当viewport的宽高比和viewBox的宽高比不匹配时,取宽高缩放比中较小的那个注意这里说的是viewBox的缩放而不是图形
- slice: 修剪 viewBox保持缩放比;整个viewport区域被viewBox覆盖;在满足签个约束条件的基础上,尽可能的缩小viewBox。当viewport的宽高比和viewBox的宽高比不匹配时,取宽高缩放比中较大的那个
-
align:用于长宽比不一致的情况,有以下几种取值:
- none:不强制进行等比例缩放,那么viewBox下的graphicelements就以viewBox和viewport实际的宽高比来缩放图形,强行把宽度和高度扩展到这个viewport上。一个后果就是图形比例会失真
- xMinYMin:强制等比例缩放,viewBox的min-x坐标值和viewport的最左边的x对齐。viewBox的min-y坐标和viewport的最左边的y坐标对齐。
- xMidYMin:强制等比例缩放,viewBox的x中点和viewport的x中点对齐,viewBox的min-y和viewport的最上边y值对齐。
- xMaxYMin:强制等比例缩放,viewBox的min-x+width和viewport最右边x值对齐,viewBox的min-y和viewport的最上边y值对齐。
- xMinYMid:强制等比例缩放,viewBox的min-x和viewport的最左边x对齐,viewBox的y的中点和viewport的中点对齐。
- xMidYMid:强制等比例缩放,viewBox的x中点和viewport的x中点对齐,viewBox的y中点和viewport的中点对齐。(默认值)
- xMaxYMid:强制等比例缩放,viewBox的min-x+width和viewport的最右边的x对齐,viewBox的y中点和viewport的y中点对齐。
- xMinYMax:强制等比例缩放,viewBox的min-x和viewport最左边的x对齐,viewBox的min-y+height和viewport最下边的y值对齐。
- xMidYMax:强制等比例缩放,viewBox的x中点和viewport的x中点对齐,viewBox的min-y+height和viewport最下边的y值对齐。
- xMaxYMax:强制等比例缩放,viewBox的min-x+width和viewport的最右边x对齐,viewBox的min-y+height和viewport最下边的y值对齐。
具体定位可以运行以下代码尝试(代码来源:imooc):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ViewBox 使用演示</title>
<style>
body {
background: #eee;
}
svg {
position: absolute;
border: 1px solid green;
width: 300px;
height: 200px;
left: 50%;
top: 50%;
margin-top: -100px;
margin-left: -150px;
background: white;
}
input[type=number] {
width: 50px;
}
</style>
</head>
<body>
<h1>ViewBox 演示</h1>
<form id="form">
<fieldset>
<legend>viewBox</legend>
<label>x: <input id="vx" type="number" value="0"></label>
<label>y: <input id="vy" type="number" value="0"></label>
<label>width: <input id="vw" type="number" value="300"></label>
<label>height: <input id="vh" type="number" value="200"></label>
</fieldset>
<fieldset>
<legend>preserveAspectRatio</legend>
<label>align: <select id="align">
<option value="none">none</option>
<option value="xMinYMin">xMinYMin</option>
<option value="xMidYMin">xMidYMin</option>
<option value="xMaxYMin">xMaxYMin</option>
<option value="xMinYMid">xMinYMid</option>
<option value="xMidYMid" selected>xMidYMid</option>
<option value="xMaxYMid">xMaxYMid</option>
<option value="xMinYMax">xMinYMax</option>
<option value="xMidYMax">xMidYMax</option>
<option value="xMaxYMax">xMaxYMax</option>
</select></label>
<label>meetOrSlice: <select id="meetOrSlice">
<option value="meet">meet</option>
<option value="slice">slice</option>
</select></label>
</fieldset>
</form>
<p>
<svg id="svg" xmlns="http://www.w3.org/2000/svg">
<!--Face-->
<circle cx="100" cy="100" r="90" fill="#39F" />
<!--Eyes-->
<circle cx="70" cy="80" r="20" fill="white" />
<circle cx="130" cy="80" r="20" fill="white" />
<circle cx="65" cy="75" r="10" fill="black" />
<circle cx="125" cy="75" r="10" fill="black"/>
<!--Smile-->
<path d="M 50 140 A 60 60 0 0 0 150 140"
stroke="white" stroke-width="3" fill="none" />
<rect id="viewBoxIndicator" stroke="red" stroke-width="3.5" fill="none" />
</svg>
</p>
<script>
function update() {
var viewBox = [vx.value, vy.value, vw.value, vh.value].join(' ');
var preserveAspectRatio = [align.value, meetOrSlice.value].join(' ');
svg.setAttribute('viewBox', viewBox);
svg.setAttribute('preserveAspectRatio', preserveAspectRatio);
var rect = viewBoxIndicator;
rect.setAttribute('x', vx.value);
rect.setAttribute('y', vy.value);
rect.setAttribute('width', vw.value);
rect.setAttribute('height', vh.value);
}
form.addEventListener('input', update);
update();
</script>
</body>
</html>
效果图: