SVG
- 不依賴分辨率
- 支持事件處理器
- 最適合帶有大型渲染區域的應用程序(比如谷歌地圖)
- 復雜度高會減慢渲染速度(任何過度使用 DOM 的應用都不快)
- 不適合游戲應用
Canvas
- 依賴分辨率
- 不支持事件處理器
- 弱的文本渲染能力
- 能夠以 .png 或 .jpg 格式保存結果圖像
- 最適合圖像密集型的游戲,其中的許多對象會被頻繁重繪
大概就是這樣,如果你要使用SVG,應該考慮是否更應該采用Canvas,並且還需要知道並不是所有瀏覽器都支持它,IE8或以下就不支持SVG,除此以外的現代瀏覽器包括IE9+基本都支持。IE它有自己的一套方案:VML,這個你自己去搜索相關資料。另外也可以通過安裝插件使得其支持SVG,比如adobe出品的svg viewer。
在HTML中使用SVG
基礎部分看W3SCHOOL的教程:http://www.w3school.com.cn/svg/index.asp,很簡單,花30分鍾就可以掃完。
特別要注意SVG in HTML部分,它介紹了如何在HTML中使用SVG,可能會比較麻煩,慶幸的是在支持HTML5的瀏覽器中,可以直接創建SVG標簽:
<html> <body> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="190"> <polygon points="100,10 40,180 190,60 10,60 160,180" style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;" /> </svg> </body> </html>
這種方式稱為內聯SVG
,有了這個內聯方式JavaScript就好控制得多了。
分組元素<g>
g元素可以對多個元素進行分組,使其更具語義化,並且方便對分組里的元素進行統一處理,比如樣式、動畫等。
<g> <rect x="10" y="10" width="40" height="40" ry="10"/> <rect x="80" y="80" width="40" height="40" ry="10"/> <rect x="150" y="150" width="40" height="40" ry="10"/> </g>
解決text文本排版問題
在SVG中對文本排版比較頭疼,你不能像HTML那樣輕易的把文本放到一個“矩形容器”(比如DIV)里,因為那些標簽都是封閉的(在開始標簽中進行關閉)。簡單的做法是把文字和矩形設定到相近的坐標中,使其看起來是“一起的”(難道這就是世界上最遙遠的距離?):
<rect x="10" y="10" width="100" height="40" style="fill:rgb(255,255,255);stroke-width:1;stroke:rgb(0,0,0)"/> <text x="35" y="35" font-size="16" style="fill:rgb(0,0,0);">text</text>;
顯然這種方式是很難管理,當我想更換一個位置的時候,我必需把矩形和文本的位置都進行調整,現在只有兩個元素還好說,一旦多起來,那簡直就是噩夢。而g元素可以幫我們解決這個問題。
先把它們都放到一個g元素里,這樣里面所有元素的位置都是相對於這個g元素的,通過更改g元素的位置,可以達到調整整個分組的位置的效果。但需要通過transform才能有效,而不是x和y:
<g transform="translate(50,50)"> <rect x="0" y="0" width="100" height="40" style="fill:rgb(255,255,255);stroke-width:1;stroke:rgb(0,0,0)"/> <text x="25" y="25" font-size="16" style="fill:rgb(0,0,0);">text</text>; </g>
現在矩形和文本的x和y軸都是相對於g的位置而言的,translate(50,50)
表示 x="50", y="50" 這樣應該很好理解吧?
通過Javascript DOM控制SVG
頁面上已經存在一個SVG容器,這個容器帶有帶有一個XML命名空間http://www.w3.org/2000/svg
和一個idmain
:
<svg xmlns="http://www.w3.org/2000/svg" id="main" version="1.1" height="200"></svg>
下面我們使用一系列的DOM方法在容器里添加一個矩形:
- 通過
document.getElementById
根據元素ID
來獲取
這個容器對象 - 使用
document.createElementNS
創建
一個帶http://www.w3.org/2000/svg
命名空間的矩形對象 - 使用
element.setAttribute
設置這個矩形對象的屬性
- 使用
element.appendChild
把它添加
到容器里
代碼:
<script> var main = document.getElementById( "main" ); var rect = document.createElementNS( "http://www.w3.org/2000/svg", "rect" ); rect.setAttribute( "width", 100 ); rect.setAttribute( "height", 30 ); rect.setAttribute( "style", "fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)" ); main.appendChild( rect ); </script>
設置文本
textContent屬性
可以獲取和設置text元素文本:
// SVG
<text id="text" x="25" y="25" font-size="16" style="fill:rgb(0,0,0);">foo</text>; // JS <script> var text = document.getElementById( "text" ); console.log( text.textContent ); // foo text.textContent = "Hello world!"; // 重新設置文本 </script>
獲取元素高寬和坐標
getBBox方法
可以獲取所有元素的高寬和坐標:
// SVG
<text id="text" x="25" y="25" font-size="16" style="fill:rgb(0,0,0);">foo</text>; // JS <script> var text = document.getElementById( "text" ); console.log( text.getBBox() ); // {height: 16, width: 32, y: 11, x: 25} </script>
事件處理
SVG也可以像HTML那樣為元素添加自定義事件。
使用on + 事件名
屬性監聽:
// SVG
<text id="text" x="25" y="25" font-size="16" style="fill:rgb(0,0,0);">foo</text>; // JS <script> var text = document.getElementById( "text" ); // 點擊文本時彈出其內容 text.onclick = function() { alert( this.textContent ); }; </script>
也可以使用element.addEventListener
方法監聽:
// SVG
<text id="text" x="25" y="25" font-size="16" style="fill:rgb(0,0,0);">foo</text>; // JS <script> var text = document.getElementById( "text" ); // 點擊文本時彈出其內容 // 事件名前面不帶on text.addEventListener( 'click', function() { alert( this.textContent ); } ); </script>
兩種方法有什么不同?on + 事件名
屬性只能為同一個事件添加一個處理方法,再對這個屬性進行設置時會覆蓋掉上一個方法,而element.addEventListener
多次使用也不會覆蓋上一個,而是從原來的事件上疊加。