摘要:SVG繪製的任何一個時刻,你可以通過嵌套svg或者使用例如symbol的元素來建立新的viewport和用戶座標系。第一件需要注意的是內容svg元素不需要聲明一個命名空間xmlns因爲默認和外層svg的命名空間相同。

SVG繪製的任何一個時刻,你可以通過嵌套svg或者使用例如symbol的元素來建立新的viewport和用戶座標系。在這篇文章中,我們將看一下我們如何這樣做,以及這樣做如何幫助我們控制SVG元素並讓它們變得更加靈活(或流動)。

嵌套svg元素

在SVG繪製過程中的任何一個時刻,你可以創建一個新的視窗其中包含的圖形是通過把一個svg元素包含在另一箇中繪製的。通過建立新視窗,你隱性得建立了一個新視窗座標系和新用戶座標系。

例如,試想有一個svg以及裏面的內容:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 
  <!-- some SVG content --> 
  <svg> 
    <!-- some inner SVG content --> 
  </svg> 
</svg> 

第一件需要注意的是內容svg元素不需要聲明一個命名空間xmlns因爲默認和外層svg的命名空間相同。當然,如果在HTML5文檔中外層svg也不需要命名空間。

你可以使用一個嵌套的SVG來把元素組合在一起然後在父SVG中定位它們。現在,你也可以把元素組合在一起並且使用組g來定位-通過把元素包括在一組g元素中。你可以使用transform屬性在畫布中定位它們。然而,使用svg肯定好過使用g。使用x和y座標來定位,在許多情況下,比使用變換更加方便。另外,svg元素接受寬高值,g不行。這意味着,svg也許並必要的,因爲它可以創建一個新的viewport和座標系,你可以不需要也不想要。

通過給svg聲明寬高值,你把內容限制在通過x,y,width和height屬性定義的viewport的邊界。任何超過邊界的內容會被裁切。

如果你不聲明x和y屬性,它們默認是0。如果你不聲明height和width屬性,svg會是父SVG寬度和高度的100%。

另外,聲明用戶座標系而不是默認的也會影響內部svg的內容。

給svg內的元素百分比值的聲明會根據svg計算,而不是外層svg。例如,下面的代碼會導致內層SVG等於400單位,裏面的長方形是200個單位:

<svg width="800" height="600"> 
  <svg width="50%" ..> 
    <rect width="50%" ... /> 
  </svg> 
</svg> 

如果最外層svg的寬度爲100%(例如,如果它在一個文檔中內聯或者你想要它可以流動),內層SVG會擴展拉伸來保持寬度爲外層SVG的一半-這是強制的。

嵌套SVG在給SVG畫布中的元素增加靈活性和擴展性時尤其有用。我們知道,使用viewBox值和preserveAspectRatio,我們已經可以創建響應式SVG。最外層svg的寬度可以設置成100%來確保它擴展拉伸到它的容器(或頁面)擴展或拉伸。然後通過使用viewBox值和 preserveAspectRatio,我們可以保證SVG畫布可以自適應viewport中的改變(最外層svg)。我在CSSConf演講的幻燈片中寫到了關於響應式SVG的內容。你可以在這裏查看這個技術。

然而,當我們像這樣創建一個響應式SVG,整個畫布以及所有繪製在上面的元素都會有反應並且同時改變。但有時候,你只想讓圖形中的一個元素變爲響應式,並且保持其他東西“固定”在一個位置和/或尺寸。這時候嵌套svg就很有用。

svg元素有獨立於它父元素的座標系,它可以有獨立的 viewBox 和 preserveAspectRatio 屬性,你可以任意修改裏面內容的尺寸和位置。

所以,要讓一個元素更加靈活,我們可以把它包裹在svg元素中,並且給svg一個彈性的寬度來適應最外層SVG的寬度,然後聲明preserveAspectRatio=”none”這樣的話裏面的圖形會擴展和拉伸到容器的寬度。注意svg可以多層嵌套,但是爲了讓事情簡潔,我在這篇文章裏只嵌套一層深度。

爲了達到這個效果,蛋的上半部分必須和其他部分分離出來單獨包含一個自己的svg。這個svg包含框會有一個IDupper-shell。

然後,我們保證新的svg#upper-shell和外層SVG有一樣的高度和寬度。可以通過在svg上聲明width=”100%” height=”100%”或者不聲明任何高度和寬度來實現。如果內層SVG上沒有聲明任何寬高,它會自動擴展爲外層SVG寬高的100%。

爲了確保上殼被“抬”起或定位在svg#upper-shell頂部的中心,我們將使用適當的preserveAspectRatio值來確保viewBox被定位在視窗的頂部中心-值是xMidYMin。

SVG圖形的代碼如下:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 
  <!-- ... --> 
  <svg viewBox="0 0 315 385" preserveAspectRatio="xMidYMid meet"> 
  <!-- the chicken illustration --> 
    <g id="chicken"> 
    <!-- ... --> 
    </g> 
  <!-- path forming the lower shell --> 
    <path id="lower-shell" fill="url(#gradient)" stroke="#000000" stroke-width="1.5003" d="..."/> 
  </svg> 
 
  <svg id="upper-shell" viewBox="0 0 315 385" preserveAspectRatio="xMidYMin meet"> 
  <!-- path forming the upper shell --> 
    <path id="the-upper-shell" fill="url(#gradient)" stroke="#000000" stroke-width="1.5003" d="..."/> 
  </svg> 
</svg> 

使用iframe建立新視窗

代表SVG文件的iframe元素建立新座標系的情況類似於上述解釋的image元素的情況。iframe元素也可以有x,y,width和height屬性,除了它自身的preserveAspectratio之外。

使用foreignObject建立新視窗

foreignObject元素建立一個新的viewport來渲染這個元素的內容。

foreignObject標籤允許你把非SVG內容添加到SVG文件中。通常,foreignObject的內容被認爲不同於命名空間。例如,你可以把一些HTML放到SVG元素的中間。

foreignObject接收屬性包括x,y,height和width,用來定位對象和調整尺寸,創建用於呈現它裏面所引用的內容的範圍。

有需要關於foreignObject元素的要說因爲它給內容創建了新的viewport。如果你感興趣,可以查看MDN entry或者在The Nitty Gritty Blog上查看Christian Schaeffer創建的實際使用。

<svg width="812.595" height="1138.155" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:html="http://www.w3.org/1999/xhtml">
  <foreignObject font-style="normal" font-weight="normal" style="vector-effect: non-scaling-stroke;" id="svg_157" font-size="14" height="207" width="341.00001" y="209.84497" x="63.40503">
    <div align="left" style="vector-effect: non-scaling-stroke; color: rgb(63, 63, 63);" font-color="black" class="text-wrapper" o-bind="text:invoice" xmlns="http://www.w3.org/1999/xhtml">
      <h4>Shanghai electromechanical Co., Ltd.</h4>
      <br>
      <h4>Introduction</h4>
      Shanghai Mechanical was founded in Feb., 2006.We specialize in designing and manufacturing port mechanical spare parts and provide maintenance service.
    </div>
  </foreignObject>
</svg>
相關文章