HTML5中的绘图SVG VS Canvas
來源是微軟的官方文檔:
http://msdn.microsoft.com/zh-cn/library/gg193983
Canvas
另一種向用戶提供更豐富的圖形體驗的方法,通過 <canvas> 標記提供,該標記由 Apple for Safari 在 HTML5 中或在其他圖形小工具中引入。它在繪制即時模式圖形(包括矩形、路徑和圖像)方面公開更具編程性的體驗,與 SVG 類似。即時模式圖形呈現是一個“觸發即忘”模型,該模型將圖形直接呈現到屏幕上,但隨后對所完成的操作不保留任何上下文。與保留模式相反,不保存呈現的圖形;要在每次需要新框架時描述整個場景,開發人員需要重新調用所有必需的繪圖命令,而不考慮實際更改(SVG 已知擁有“場景圖”)。
元素
為了使用畫布 (Canvas) 功能,Web 開發人員直接引入了一個 Canvas 元素:
HTML <canvas id="myCanvas" width="1200px" height="1200px"></canvas>然后使用 <canvas> 傳統的2D基礎庫 API 來繪制圖像和矢量。
使用 JavaScript 代碼執行對畫布上圖形的操作,通過添加對圖形的支持可以獲得 Web 開發人員熟悉使用的優勢。
JavaScript var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d");如前面提到的,存在與 SVG 中相似的形狀和對象,舉例來說,開發人員可以使用下面的代碼來繪制矩形:
JavaScript ctx.fillStyle = "rgb(0,0,255)"; ctx.fillRect(10, 10, 100, 100);稍后將討論這些方法的優缺點以及適當的方案。
最終結果與在 SVG 中相同。http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/canvasintro.htm
但正如 SVG 一樣,Canvas 具有更復雜的幾何基元,區別在于這些基元采用函數形式。
事件的可編程性
為了能夠繪制比矩形更復雜的圖形(如前面顯示的夏威夷地圖),canvas?API 提供了一個路徑 API,該路徑 API 支持與 SVG 中的?<path>?元素相似的命令,只是你要對每一行代碼段調用相應的 API,而不是在單個屬性中列出它們:
JavaScript ctx.beginPath(); ctx.moveTo(233.08751,519.30948); ctx.lineTo(235.02744,515.75293); ctx.lineTo(237.29070000000002,515.42961); ctx.lineTo(237.61402,516.23791); ctx.lineTo(235.51242000000002,519.30948); ctx.lineTo(233.08751,519.30948); ctx.closePath();有關夏威夷地圖,請參閱?http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/canvasmap.htm。
路徑 API 并不局限于?moveTo?和?arc,它包含相同的 SVG 方向相位(包括二次曲線和貝塞爾曲線)。
通過有限的事件和功能可以捕獲鼠標在圖像上的位置。因為不存在圖形保留知識,所以編程人員必須轉換?mouseX?標記的單個元素上的?mouseY、<canvas>?坐標,然后將該命令相應地傳送到位于內存中結構中的形狀。第三方庫為支持更復雜的路徑而存在,這包括內置?isPointInPath?API,但后者被限制為最后路徑繪制。因而與 SVG 不同,既沒有任何樣式也不支持多個幾何圖上的命中檢測。另外,因為 Canvas 不支持可伸縮性,所以縮放時夏威夷地圖將很快失真:
Canvas 是一個功能強大的低級別 API,開發人員利用它可以提供新的圖形體驗。
Canvas 與 SVG 的簡要摘要
下面是簡要摘要,可幫助你確定何時使用 Canvas 而不使用 SVG 或者何時使用 SVG 而不使用 Canvas 來創建矢量圖形。
| 基于像素(動態 .png) | 基于形狀 |
| 單個 HTML 元素 | 多個圖形元素,這些元素成為 DOM 的一部分 |
| 僅通過腳本修改 | 通過腳本和 CSS 修改 |
| 事件模型/用戶交互顆粒化 (x,y) | 事件模型/用戶交互抽象化 (rect, path) |
| 圖面較小時、對象數量較大 (>10k)(或同時滿足這二者)時性能更佳 | 對象數量較小 (<10k)、圖面更大(或同時滿足這二者)時性能更佳 |
?
在上表中,考慮這二者在現有軟件方面的意象模型。Canvas 類似于 MSPaint,在其中,你可以使用形狀和其他工具來繪制和創建圖像。SVG 類似于 Office PowerPoint 幻燈片,它具有可編程的支持并且能夠添加主題。
何時使用?<canvas>、何時使用 SVG:方案
這一節介紹這兩種技術的技術優勢和限制,包括用于確定一種技術何時相對于另一種技術更適合的常用方法。應該注意的是,SVG 和?<canvas>?都能實現幾乎相同的結果,功能也完全重復。介紹以下特定情況非常重要:<canvas>?明顯好于 SVG,或相反,二者組合更加合適,或可以使用和考慮任一技術。
這些方案比較清晰地描述了更適合使用 SVG 的情況、更適合使用 Canvas 的情況,以及其他介于這之間的情況。它們描述了每種技術的優缺點,以便開發人員可以了解相應技術的行為并針對其應用程序做出好的選擇。
從性能方面選擇
有時存在一些外部影響,要求獨立于(或幾乎獨立于)功能選擇技術。有關使用 Canvas 或 SVG 的問題,存在兩個主要區別。
有時開發人員的知識、技能組合和現有資產會對技術的選擇起到重大作用。如果開發人員具備低級別圖形 API 方面的深層知識,但在 Web 技術方面知識有限,則很可能會選擇 Canvas 技術。
另外,性能對于高流量的網站來說是絕對關鍵的。可以對這兩種技術的性能特征加以比較。這可能會要求開發 Canvas 沒有附帶的輔助功能、自定義樣式以及更粒度化的用戶交互功能。雖然 Canvas 通常被視為具有高性能,但是并不意味著它就是明顯的選擇。下圖顯示了 SVG 對象和 Canvas 對象之間在呈現時間上的差異。
一般情況下,隨著屏幕大小的增大,畫布將開始降級,因為需要繪制更多的像素。隨著屏幕上的對象數目增多,SVG 將開始降級,因為我們正不斷將這些對象添加到 DOM 中。這些度量不一定準確,以下方面的不同一定會引起變化:實現和平臺、是否使用完全硬件加速的圖形,以及 JavaScript 引擎的速度。
高保真度的復雜矢量文檔
高保真度的復雜矢量文檔已經成為并將繼續成為 SVG 的最有效點,原因主要有兩個。存在足夠多的極為詳細的文檔,包括由 CAD 程序生成的那些文檔,針對這些文檔,SVG 的?scalable?部分提供了獨立文檔形式或嵌入網頁中的文檔形式的詳細視圖。通過該技術還可以進行高保真打印。SVG 的聲明性性質向工具、客戶端或服務器端提供從數據庫生成形狀的能力。 最后,我們看到了政府機構的發展,因工程圖(為了專利)或工業圖(為了城市規劃目的)緣故從建議支持轉變為對 SVG 的必需支持。這種轉變還將繼續,因為對于公眾使用的電子文檔(如下),政府部門越來越不是只喜歡一家供應商:
- 建筑圖、工程圖和樓層圖
- 電子圖、航空圖和示意圖
- 組織結構圖
- 地圖
- 生物圖
以下各圖顯示了前一方案中可以保留的詳細信息示例。第一個圖像顯示可以在測試驅動網站上找到的網頁快照。它包含呼吸系統圖和元素周期表。
http://ie.microsoft.com/testdrive/Graphics/RealWorldDataAndDiagrams/Default.xhtml
第二個圖像顯示同一張圖放大 1000% 后的效果
盡管考慮到觀察大的示意圖的有用性,但在需要細化到細節處時或者出于工程目的需要打印整個示意圖時,具有可縮放性的?S?將變得足夠清晰和有價值。出于這些原因,我們將高保真度的復雜矢量文檔放在譜表的遠端,接近 SVG,如下圖中所示。
這些文檔也可以受益于交互性,這是 SVG 使這些方案最適合于保留圖形模式的第二方面。
增強的 Web 圖形
SVG 作為圖像格式
SVG 另外還常用于簡單圖像,無論是應用程序還是網頁中的圖像,大圖像還是小圖像。由于 SVG 要加載到 DOM 中,或者創建圖像前至少要進行解析,所以性能會稍微有所下降,但相比于呈現網頁的成本(大約幾毫秒),這種下降是極其微小。
在文件大小方面(為了評估網絡流量的目的),下面演示的兩個圖像是一樣的,只差了 1K(SVG 稍微大點,沒有壓縮)。
與以前一樣,因為 SVG 作為圖像格式是可縮放的,所以如果開發人員想要以更大的比例使用該圖像,或者用戶使用高 DPI的屏幕,則可移植網絡圖形 (PNG) 要么會變得異常,要么需要更大形式的文件來實現保真。
SVG 因此可以充當非常好的圖像替換格式,甚至對網頁上最簡單的圖像也是如此。靜態 WebApp/網頁圖像因此落在譜表的 SVG 端。
像素操作
在譜表的另一端,當使用 Canvas 時可以獲得快速的繪圖速度,且不需要保留相應信息。存在若干種最適合于 <canvas> 的實時數據方案。使用光線跟蹤在像平面上通過像素跟蹤光線路徑并模擬其與虛擬對象相遇的效果,可以水化圖像。 下圖顯示了這種模擬。
需要很多計算,因此速度依賴于瀏覽器中的 JavaScript 引擎速度。然而盡管大多數情況下本地代碼無可置疑要更快一些,但是隨著 JavaScript 引擎逐漸成熟,我們開始看到在像程序集和 C++ 這樣的時期內這種差距在縮小。
光線跟蹤(通常在 Web 上的背景中完成)獲得的效果甚為廣泛。范圍從創建許多不同的視覺效果(包括根據其他簡單矢量圖形創建逼真的圖像)到應用照片過濾器以去除紅眼。
因為 Canvas API 允許開發人員讀寫像素,所以這里唯一的限制是速度和想象力。上一個示例由 Adam Burmister 提供并且位于?http://labs.flog.co.nz/raytracer/?上。 在此示例中,可通過大量的庫來實現創建最終圖像所需的計算,但主結束函數是?fillRect。
JavaScript setPixel: function(x, y, color){var pxW, pxH;pxW = this.options.pixelWidth;pxH = this.options.pixelHeight;this.canvas.fillStyle = color.toString();this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH); },出于此原因,高性能圖形(如光線跟蹤器)作為 Canvas 方案落在譜表的最左端,如下圖所示。
注意生成上述光線跟蹤器的作者 注意 因為該方案將產生靜態圖像,所以桌面軟件經過了很好的調整以適合光線跟蹤器所需的大量浮動操作。
下至金屬像素操作的有趣實現是圖像的過濾器應用。過濾器已存在于 Web 上,且需要顯著的處理速度(受益于其對圖形管道中更深層的硬件加速圖形的應用),因此開發人員可以試用邊緣檢測或其他數學表達式等算法。
實時數據
對于更常見的方案,Canvas 非常適合輸出實時數據。請注意如何簡便地確定這些方案,因為已經表明使用 Canvas 難以進行用戶交互。因此,下面將討論非交互的實時數據可視化。
今天的天氣數據可以通過特定間隔內服務器上生成的圖像非常靜態地呈現,也可以盡可能快地通過客戶端第三方插件呈現。盡管 ECWMF 已經研究過使用 SVG 而不使用服務器生成的圖像如何節省成本,但是 Canvas 在天氣模式(以及其他快速的實時數據)的大多數圖形表示形式方面,明顯是贏家。下圖顯示以圖形方式顯示在地圖上的天氣模式。
如你可以從上圖中看到的,沒有必要存在大的繪圖圖面,而且屏幕上的對象數量是相當高的。通過使用 Canvas API,可以在不影響 DOM 的情況下快速繪制(和擦除)這些對象。盡管可以使用 SVG Ellipse 完成此操作,但是將它們加載到 DOM 中以及通過動畫修改它們的成本是非常高的。事實上,無論你是在圖像中還是在數據動畫中看到大量的形狀(尤其是不相似的形狀)要進行分析,通常都會指出 Canvas 是要使用的技術。這里的實際限制是受 CPU 速度和 JavaScript 引擎速度的控制,能多快可視化顯示數據。但除了占用 CPU 的光線跟蹤方案之外,仍然可以實現合理的動畫。Reasonable?描述客戶端可以使用 JavaScript 執行的操作與服務器可以通過電線計算和封送的操作之間的相對動畫。
此方案似乎是?<canvas>?的關鍵用例。
像素替換(綠屏)
另一個使用 Canvas 的可能情況是,在視頻上進行顏色檢測以便用其他場景或圖像替換背景色。像光線跟蹤器或過濾器一樣,因 JavaScript 中當前性能速度限制的緣故,很可能會使用桌面軟件預處理任何需要高的最終產品質量的現實方案。但是,由于 <canvas> 是為低級別像素讀取和寫入設計的,因此諸如?greenscreen?替換之類的方案甚至無法使用 SVG 完成。
從兩個視頻中讀寫像素到另一個視頻中所需的代碼要求使用兩個視頻、兩個畫布和一個最終畫布。一次捕捉視頻上的一幀,然后繪制到兩個單獨的畫布上。這樣允許讀回數據。
JavaScript ctxSource1.drawImage(video1, 0, 0, videoWidth, videoHeight); ctxSource2.drawImage(video2, 0, 0, videoWidth, videoHeight);因此,下一步是檢索每個繪制圖像的句柄,以便你可以檢查每個單獨的像素。
JavaScript currentFrameSource1 = ctxSource1.getImageData(0, 0, videoWidth, videoHeight); currentFrameSource2 = ctxSource2.getImageData(0, 0, videoWidth, videoHeight);獲取后,代碼將瀏覽綠屏的像素數組,搜索綠色像素,如果找到,代碼將用背景場景中的像素替換所有綠色像素。
JavaScript for (var i = 0; i < n; i++) {// Grab the RBG for each pixel:r = currentFrameSource1.data[i * 4 + 0];g = currentFrameSource1.data[i * 4 + 1];b = currentFrameSource1.data[i * 4 + 2];// If this seems like a green pixel replace it:if ( (r >= 0 && r <= 59) && (g >= 74 && g <= 144) && (b >= 0 && b <= 56) ) // Target green is (24, 109, 21), so look around those values.{pixelIndex = i * 4;currentFrameSource1.data[pixelIndex] = currentFrameSource2.data[pixelIndex];currentFrameSource1.data[pixelIndex + 1] = currentFrameSource2.data[pixelIndex + 1];currentFrameSource1.data[pixelIndex + 2] = currentFrameSource2.data[pixelIndex + 2];currentFrameSource1.data[pixelIndex + 3] = currentFrameSource2.data[pixelIndex + 3];} }最后,像素數組將寫入到目標畫布中。
JavaScript ctxDest.putImageData(currentFrameSource1, 0, 0);http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/canvasgreenscreen.htm(若要完整地查看 greenscreen 代碼,請查看該頁的源代碼。)
組合/交叉方案
以下方案可以在 SVG 或 Canvas 中完成,都可以獲得適當的結果,但你可能會更喜歡一項技術勝過另一項技術。
圖表和圖形
需要矢量圖形的圖表和圖形的譜表很寬廣。大部分這些圖形最好使用 SVG 進行創建,因為它們具有下列三個特征之一:
- 圖形是從可以輕松轉換為 XML (SVG) 的現有數據生成的
- 它們需要用戶交互
- 優點是可在網頁上設置樣式
我們使用可顯著增加方案范圍的交互功能來擴展高保真文檔方案。 其中包括:
- 交互的組織結構圖和流程圖
- 數據圖(環形圖、條形圖、散點圖)
- 交互式地圖 - 路徑查找
- 建筑圖、工程圖和樓層圖
- 航班或音樂廳的座位圖
已經確定快速的實時數據處理已針對 Canvas 進行了更好地優化(主要取決于速度)。
二維游戲
制作休閑游戲(此處定義為 Web 上的簡單二維游戲)時,開發人員需要在 canvas 和 svg 之間做出選擇。因為歷史上游戲庫一直利用較低級別的圖形 API,所以將傾向于選擇?<canvas>。
當庫的其他組成部分(如受歡迎的物理引擎)比圖形層要明顯深時,圖形將變成實現細節。邊框、速度、大小和位置等圖形幾何將傳遞給引擎,而引擎隨后將用速度、碰撞和位置進行響應。圖形位于堆棧中的最高層。
通過由同一作者開發的兩個游戲來演示獨立于游戲邏輯的圖形概念,旨在說明?<svg>?和?<canvas>:SVG-oids?和?canvas-pinball。一個出色的、獨立于游戲引擎的圖形層示例是將?canvas-pinball?與?SVG-Dice?進行比較(當兩者都使用相同的物理引擎時)。
盡管游戲和演示邏輯是不同的,但是這兩個游戲的物理引擎都會跟蹤位置、碰撞、速度以及游戲組成部分的其他物理方面。
對于 canvas-pinball,自定義的更高級別的動畫管理器通過使用一系列 Canvas API 重新繪制場景。
JavaScript if (animationsInProgress) {ctx.save();ctx.lineWidth = 2.0;ctx.beginPath();ctx.moveTo(89, 322);ctx.lineTo(101, 295);...ctx.stroke();ctx.restore();ctx.moveTo(tVp.x, tVp.y); }對于 SVG Dice,自定義的更高級別的動畫管理器使用組轉換通過 DOM 在屏幕上重新定位現有圖形。
JavaScript if (animationsInProgress) {this.rotation += (this.circleBody.m_linearVelocity.x/20);var transFormString = "translate(" +Math.round(this.circleBody.m_position.x) + "," +Math.round(this.circleBody.m_position.y) + ") scale (" +this.scale.toString() + ") rotate(" +Math.round(this.rotation).toString() + "," +Math.round(this.xTrans).toString() + "," +Math.round(this.yTrans).toString() + ")";this.die2.setAttribute("transform", transFormString); }一種技術要重新繪制和重新定位形狀,而另一種技術只需重新定位,但需要在內存中維護形狀,這會帶來成本。此成本對于大多數休閑游戲來說都是相當低的,但預期是使用較低級別的 API 實現即時模式圖形的游戲更加讓人熟悉。
高級方案
可能大部分功能強大的方案都會涉及組合整個圖形、樣式和文檔技術。
用戶界面設計
幾年前可能就在爭論 SVG 是否是適合用于用戶界面設計的技術。這些要求與 SVG 一致。事實上,Linux 操作系統的至少一個前端完全建立在 SVG 之上。滑塊、復選框、圓形按鈕等控件以及其他標準固有控件集中的非框控件都很適合在矢量圖形中使用。但是,隨著 CSS 的最近和未來開發(包括圓角、漸變、過濾器和打印機事件),可以通過標準的框模型 HTML 文檔中心構造來開發大多數這些控件。其他控件(尤其是使用最新 CSS Grid 和 Flexbox 模型的控件)都更好地面向 HTML 元素,至少作為容器。
此處提供了一個豐富的數據驅動圖表的示例。 盡管該示例的輸出沒有架構好,但顯示的最終結果正確。 圖形和圖表控件是眾所周知的難開發,但第三方以及 Microsoft 已經成功了。 通過在客戶端或服務器端提供最新的數據綁定抽象,客戶端的 Web 呈現主要保持靜態或者需要插件,這樣可減輕開發人員的負擔。 下面我們利用了 SVG 的豐富性來提供增強的用戶體驗。 無論代碼如何(將傳遞給客戶端,又或許在將來更多的聲明性交互中使用),圖表都用兩個關鍵組件來呈現。 工具和數據。圖形工具或背景是基本的靜態 SVG:
HTML <rect id="tipsh" x="20" y="100" width="194" height="34" rx="5" ry="5" /> <rect id="tip" x="20" y="100" width="190" height="30" rx="5" ry="5" /> <text id="tiptxt" x="40" y="120" font-size="12" font-family="Arial" fill="#ffffff" visibility="hidden">milliseconds</text> <polygon id="arrow" points="10,110 20,105 20,115" style="fill:#ffffff" /> <line x1="3" x2="460" y1="359" y2="359" style="stroke:#cccccc;stroke-width:1"/>然后每個單獨的數據點要么傳遞到客戶端并進行操作,要么在服務器上生成:
HTML <text x="10" y="348" font-size="12" font-family="Arial">{Page}.svg</text> <rect x="115" y="350" width="86" height="8" style="fill:url(#inverseblue);filter:url(#Gaussian_Blur);" rx="12" ry="12"/> <rect x="115" y="333" width="86" height="17" rx="12" ry="12" οnmοuseοver="changeColor(evt)" οnmοusemοve="changeText(evt,'2 milliseconds')" οnmοuseοut="changeTextNotOver(evt)" /> <text x="171" y="345" font-size="11" font-family="Arial" fill="#ffffff">6.1%</text>http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/svgchart.htm
結論
通過最新瀏覽器中提供的現有矢量圖形技術的分析功能,可以交互方式使用標準 Web 技術來滿足現有的和新的方案。 從今以后,我們將擁有巨大的機會可以讓聲明性動畫支持廣告版位。 通過使用方案驅動的功能開發,我們可以在競爭中處于領先地位,并在 Web 應用程序和網頁中提供基于標準的圖形豐富的體驗。
轉載于:https://www.cnblogs.com/c4895007/p/4105764.html
總結
以上是生活随笔為你收集整理的HTML5中的绘图SVG VS Canvas的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 项目开发总结报告
- 下一篇: 计算KL散度与JS散度的MATLAB程序