svg采用相似canvas的坐标系统,以左上角为0,0原点,从左往右计算x值,从上到下计算y值。这个和HTML中标示位置的方法相同。
咱们来看一个例子javascript
<svg width="400" height="200" viewBox="0 0 200 50" style="border:1px solid greenyellow"> <rect with="150" height="150" x="10" y="10" fill="#008d46"/> </svg>
在绝大多数状况下SVG文档中的一个像素对应输出设备上的一个像素(例如显示屏幕上)
由于SVG是一个可无极缩放的矢量图形绘制标记语言。其作大的特色是在任意大小的显示设备上均可以不失精度的表现原始图形。SVG就有关于absolute unit和user unit的说法-在定义大小是不明确指定单位
没有特别的说明,一个user unit等于一个屏幕单位(一个像素),能够给经过设置viewBox属性的方法改变默认的状况,能够放大或缩小对应的值
例如<svg width="100" height="100">
定义了一个100px_*_100px的svg canvas,这里一个user unit等于一个屏幕像素
咱们再来看一个例子css
<svg width="200" height="200" viewBox="0 0 100 100">
html
这里的svg在宽度上一个userunit为2个屏幕像素,高度上一个userunit为2个屏幕像素。也就是说整个以viewBox为参考系定义的svg图像需在宽度和高度上各放大2倍显示到svg viewport上java
那么这里就有一个原始视图窗口和当前须要显示的目标视图窗口之间的映射关系的问题。这里的原始视图就是viewBox所设置的视图窗口,而目标视图窗口就是viewport。一个原则原始视图要求铺满viewport的大小,viewBox属性值格式为 (min-x,min-y,width,height),须要说明的时width和height并非表示viewBox的实际的宽度和高度,这个是指在min-x和min-y都为0的状况西下成立,viewBox的实际独宽度为minx-x+width,高度为min-y+heightjquery
<svg width="400" height="200" viewBox="0 0 200 100" style="border:1px solid greenyellow"> <rect with="100" height="100" x="0" y="0" fill="#008d46"/> </svg>
以上面的svg为例canvas
viewport的大小就是400200的矩形区域,具体的坐标位置以svg元素所在的页面的的位置。以HTML页面为参考系svg
viewBox的大小就是200500的矩形区域,位置坐标为(0,0)以viewBox为参考系ui
由于viewBox的宽高比为2,viewport的宽高比也为2,那么放大2倍后viewBox恰好铺满viewport:),
(咱们就能够认为0.5个userunit对应一个屏幕像素)spa
以viewBox为参考系的svg下的graphic elements也等同的放大2倍,也就是如今看到的绿色的矩形大小为200_*_200code
可是实际不少SVG的viewBox的宽高比和viewport的宽高比是不一样有差别的。那么在不一样的状况下viewBox和viewport怎么处理?viewBox的4个参数到底有什么做用?viewBox比viewport区域大能够吗?SVG是怎么处理的呢?可就要和下面的preserveAspectRatio属性值相关了
preserveAspetRation属性是和viewBox属性配合使用的。viewBox属性值能够指明graphic element是否能够等比例缩放(宽高比相同的状况下)以扩展到viewport指定的大小区域中。
preserveAspetRation属性指出了如何缩放及若是对齐viewBox到viewport上
若是没有指定viewBox属性,那么此属性是会被忽略的
先在这里声明一点,它的默认值为xMidYMid meet。
那么xMid、YMid、meet都是些什么样的值,干吗用的?就要从preserveAspetRation的可选值讲起
preserveAspectRation的值为[defer]<align>[meetOrSlice]-以可选的defer开始+<align>+可选的meet或者Slice。
defer这个值只在image元素中有效表示只在img显示出来后才计算使用preserveAspectRation属性,对于其它元素就忽略这个值了
在讲<align>以前,有必要说明下[meetOrSlice]候选值,默认值为meet
meet viewBox保持缩放比;整个viewBox在viewport中可见;在知足前2个约束条件的基础上,尽量的放大viewBox。当viewport的宽高比和viewBox的宽高比不匹配时,取宽高缩放比中较小的那个注意这里说的是viewBox的缩放而不是图形
slice 修剪 viewBox保持缩放比;整个viewport区域被viewBox覆盖;在知足签个约束条件的基础上,尽量的缩小viewBox。当viewport的宽高比和viewBox的宽高比不匹配时,取宽高缩放比中较大的那个
<align>在viewBox的宽高比和viewport的宽高比不匹配的状况,它的值必须是如下其中一个
none
不强制进行等比例缩放,那么viewBox旗下的graphicelements就以viewBox和viewport实际的宽高比来缩放图形,尽可能把宽度和高度扩展到这个viewport上。一个后果就是图形比例会失真
<svg width="400" height="200" viewBox="0 0 200 50" preserveAspectRation="none" style="border:1px solid greenyellow"> <rect with="100" height="100" x="0" y="0" fill="#008d46"/> </svg>
咱们能够看到rect的实际的宽度变为200,而高度边变为400。这个和viewBox和viewPort的宽高比是相符合的,宽度放大2被,高度放大4倍
咱们把viewBox和viewport的宽高换一下
<svg width="200" height="50" preserveAspectRatio="none" viewBox="0 0 400 200" style="border:1px solid greenyellow"> <rect width="100" height="100" x="0" y="0" fill="#008d46" /> </svg>
那么看到的结果为
rect的宽度缩小2倍,宽度缩小4倍,原始的正方形变成了长方形
xMinYMin 强制等比例缩放,viewBox的min-x坐标值和viewport的最左边的x对齐。viewBox的min-y坐标和viewport的最左边的y坐标对齐,
一样以上面svg为例,黑色边框矩形表示viewport,粉色矩形表示viewBox,淡绿色矩形表示rect图形元素。必须先按meet或slice计算肯定放大或缩小比例,viewBox中的数值按缩放后再执行对齐
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的中点对齐。是默认配置。meet值决定了svg的缩放比为0.25(宽度上的缩放比为0.5,高度山的缩放比为0.25)。viewBox的x中点坐标为(50+400*0.5)*0.25=62.5,viewport的x中点坐标为200*0.5=100;viewBox的y中点坐标为(50+200*0.5)*0.25=37.5,viewport的y中点坐标为50*0.5=25;那么viewBox的x坐标为100-62.5=37.5,y坐标为25-37.5=-12.5,viewBox的宽度为(50+400)*0.25=112.5 高度为(50+200)*0.25=62.5。其它属性值也使相似,你能够运行附上的代码来查看效果。
最终效果以下:
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值对齐
能看到完成的定位过程
<!DOCTYPE html> <html> <head> <title>HTML/SVG Example</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="script/jquery-2.1.3.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $("button.ts").click(function() { console.log('trigger select'); var XaspectRatio=$('input[name=VP_width]').val()/$('input[name=VB_width]').val(); var YaspectRatio=$('input[name=VP_height]').val()/$('input[name=VB_height]').val(); var aspectRatio=Math.min(XaspectRatio,YaspectRatio); var preserveAspectRatioSetting=$('input[name=xAlignType]:checked').val()+''+$('input[name=YAlignType]:checked').val(); var meetOrSlice=$('input[name=meetOrSlice]:checked').val(); if(meetOrSlice==='meet'){ aspectRatio=Math.min(XaspectRatio,YaspectRatio); }else{ aspectRatio=Math.max(XaspectRatio,YaspectRatio); } console.log("meetOrSlice:"+meetOrSlice); var viewBoxX=$('input[name=VB_x]').val()*aspectRatio; var viewBoxY=$('input[name=VB_y]').val()*aspectRatio; var viewBoxWidth=$('input[name=VB_width]').val()*aspectRatio; var viewBoxHeight=$('input[name=VB_height]').val()*aspectRatio; var viewBoxxMid=viewBoxX+(viewBoxWidth)*0.5; var viewBoxYMid=viewBoxY+(viewBoxHeight)*0.5; var viewBoxxMax=(viewBoxX+viewBoxWidth); var viewBoxYMax=(viewBoxY+viewBoxHeight); var viewportX=0; var viewportY=0; var viewportWidth=$('input[name=VP_width]').val()*1; var viewportHeight=$('input[name=VP_height]').val()*1; var viewportxMid=viewportX+(viewportWidth)*0.5; var viewportYMid=viewportY+(viewportHeight)*0.5; var viewportxMax=(viewportX+viewportWidth)*1; var viewportYMax=(viewportY+viewportHeight)*1; var rectWidth=$('input[name=rect_width]').val()*aspectRatio; var rectHeight=$('input[name=rect_height]').val()*aspectRatio; var rectX=$('input[name=rect_x]').val()*aspectRatio; var rectY=$('input[name=rect_y]').val()*aspectRatio; console.log(viewBoxX+' '+viewBoxWidth+' '+viewBoxYMid); console.log(preserveAspectRatioSetting); console.log(viewportYMax+' '+viewBoxYMax); switch(preserveAspectRatioSetting){ case 'xMinYMin': viewBoxX=viewportX-viewBoxX; viewBoxY=viewportY-viewBoxY; break; case 'xMinYMid': viewBoxX=viewportX-viewBoxX; viewBoxY=viewportYMid-viewBoxYMid; break; case 'xMinYMax': viewBoxX=viewportX-viewBoxX; viewBoxY=viewportYMax-viewBoxYMax; break; case 'xMidYMin': viewBoxX=viewportxMid-viewBoxxMid; viewBoxY=viewportY-viewBoxY; break; case 'xMidYMid': viewBoxX=viewportxMid-viewBoxxMid; viewBoxY=viewportYMid-viewBoxYMid; break; case 'xMidYMax': viewBoxX=viewportxMid-viewBoxxMid; viewBoxY=viewportYMax-viewBoxYMax; break; case 'xMaxYMin': viewBoxX=viewportxMax-viewBoxxMax; viewBoxY=viewportY-viewBoxY; break; case 'xMaxYMid': viewBoxX=viewportxMax-viewBoxxMax; viewBoxY=viewportYMid-viewBoxYMid; break; case 'xMaxYMax': viewBoxX=viewportxMax-viewBoxxMax; viewBoxY=viewportYMax-viewBoxYMax; break; default: viewBoxX=viewportX-viewBoxX; viewBoxY=viewportY-viewBoxY; //xMidYMid } $('div#svg').css({ width:$('input[name=VP_width]').val(), height:$('input[name=VP_height]').val(), "margin-left":"0px", "margin-right":"0px" }); $('div#viewBox').css({ width:($('input[name=VB_width]').val()*1+$('input[name=VB_x]').val()*1)*aspectRatio, height:($('input[name=VB_height]').val()*1+$('input[name=VB_y]').val()*1)*aspectRatio, "margin-left":(viewBoxX*1)+"px", "margin-top":(viewBoxY*1)+"px" }); $('div#rect').css({ width:$('input[name=rect_width]').val()*aspectRatio, height:$('input[name=rect_height]').val()*aspectRatio, "margin-left":(rectX*1)+"px", "margin-top":(rectY*1)+"px" }); }); }); </script> </head> <body> <br> <br> <div style="margin-left:0px;width:300;height:200px;border:1px solid #cccccc;padding:30px;"> <div id="svg" style="margin-left:0px;margin-top:0px;width:200px;height:50px;border:1px solid black"> <div id="viewBox" style="margin-left:-12.5px;margin-top:-12.5px;width:100px;height:50px;background-color:red;opacity:0.3;border:0px dashed red"> <div id="rect" style="margin-left:0px;margin-top:0px;width:25px;height:25px; background-color:#008d46;opacity:1.0;border:0px dashed red"></div> </div> </div> </div> <div style="margin-top:10px;"> <div> <label>xMin:<input type="radio" name="xAlignType" value="xMin" ></label> <label>xMid(default):<input type="radio" name="xAlignType" value="xMid" checked></label> <label>xMax:<input type="radio" name="xAlignType" value="xMax"></label> </div> <div> <label>YMin:<input type="radio" name="YAlignType" value="YMin"></label> <label>YMid(default):<input type="radio" name="YAlignType" value="YMid" checked></label> <label>YMax:<input type="radio" name="YAlignType" value="YMax"></label> </div> <div> <label>meet(default):<input type="radio" name="meetOrSlice" value="meet" checked></label> <label>slice:<input type="radio" name="meetOrSlice" value="slice"></label> </div> <div> <label>viewPort width:<input type="text" name="VP_width" value="200" style="width: 50px;"></label> <label> height:<input type="text" name="VP_height" value="50" style="width: 50px;"></label> </div> <div> <label>viewBox width:<input type="text" name="VB_width" value="400" style="width: 50px;"></label> <label> height:<input type="text" name="VB_height" value="200" style="width: 50px;"></label> <label> x:<input type="text" name="VB_x" value="50" style="width: 50px;"></label> <label> y:<input type="text" name="VB_y" value="50" style="width: 50px;"></label> </div> <div> <label>Rect width:<input type="text" name="rect_width" value="100" style="width: 50px;"></label> <label> height:<input type="text" name="rect_height" value="100" style="width: 50px;"></label> <label> x:<input type="text" name="rect_x" value="0" style="width: 50px;"></label> <label> y:<input type="text" name="rect_y" value="0" style="width: 50px;"></label> </div> <button class="ts">Show</button> </div> </body> </html>