」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 帆布與SVG:選擇合適的工具

帆布與SVG:選擇合適的工具

發佈於2025-02-21
瀏覽:899

HTML5 Canvas与SVG:选择哪一个?

Canvas vs SVG: Choosing the Right Tool for the Job

HTML5 Canvas和SVG都是基于标准的HTML5技术,可用于创建令人惊艳的图形和视觉效果。本文探讨一个关键问题:在项目中选择哪一个技术更合适?换句话说,在哪些情况下更倾向于使用HTML5 Canvas而不是SVG?

首先,让我们简要介绍HTML5 Canvas和SVG。

关键要点

  • HTML5 Canvas和SVG都是用于创建图形和视觉体验的HTML5技术。Canvas依赖于分辨率,用于动态渲染图表、游戏图形、艺术作品或其他视觉图像。SVG(可缩放矢量图形)是一种XML文件格式,在缩放时可保持其质量。
  • HTML5 Canvas和SVG的工作方式根本不同。Canvas是一种即时图形系统,一旦像素绘制完成,就会被丢弃。SVG采用保留模式,绘制的每个对象都会添加到浏览器的内部模型中,这对于开发人员来说更容易,但可能会影响性能。
  • HTML5 Canvas非常适合图形密集型、高度交互式游戏、生成式艺术以及需要在小表面上绘制大量对象的场景。但是,放大或在Retina显示屏上显示时,其质量可能会下降。
  • 对于需要可缩放性的场景(例如高保真、复杂的图形,如建筑和工程图、生物图和组织结构图),SVG更可取。SVG在可访问性方面也更好,因为它可以被人类和机器读取。
  • 可以将HTML5 Canvas和SVG结合起来用于高级场景。例如,基于Canvas的游戏可以使用SVG图像作为精灵,或者绘图程序可以使用SVG设计其用户界面,并嵌入Canvas元素进行绘图。

什么是HTML5 Canvas?

WHATWG规范对canvas元素的介绍如下:

canvas元素为脚本提供了一个依赖于分辨率的位图画布,可用于动态渲染图表、游戏图形、艺术作品或其他视觉图像。

换句话说,标签提供了一个表面,您可以使用JavaScript可编程接口逐像素创建和操作光栅图像。

这是一个基本的代码示例:

(此处应嵌入CodePen示例,展示基本的Canvas形状)

Canvas vs SVG: Choosing the Right Tool for the Job

由于依赖于分辨率,在上创建的图像在放大或在Retina显示屏上显示时,质量可能会下降。

绘制简单的形状只是冰山一角。HTML5 Canvas API允许您绘制弧线、路径、文本、渐变等。您还可以逐像素操作图像。这意味着您可以替换图形某些区域中的颜色,可以动画化您的绘图,甚至可以将视频绘制到画布上并更改其外观。

什么是SVG?

SVG代表可缩放矢量图形。根据规范:

SVG是一种用于描述二维图形的语言。作为独立格式或与其他XML混合使用时,它使用XML语法。与HTML5混合使用时,它使用HTML5语法……

SVG绘图可以是交互式和动态的。动画可以通过声明方式(即通过在SVG内容中嵌入SVG动画元素)或通过脚本定义和触发。

SVG是一种XML文件格式,用于创建矢量图形。可缩放的特性使其能够在保持清晰度和高质量的同时增加或减少矢量图像。(HTML5 Canvas生成的图像无法做到这一点)。

以下是使用SVG绘制的相同红色正方形(之前使用HTML5 Canvas创建):

(此处应嵌入CodePen示例,展示基本的SVG形状)

您可以使用SVG执行大部分可以使用Canvas执行的操作,例如绘制形状和路径、渐变、图案、动画等等。但是,这两种技术的工作方式根本不同。与基于Canvas的图形不同,SVG具有DOM,因此CSS和JavaScript都可以访问它。例如,您可以使用CSS更改SVG图形的外观,使用CSS或JavaScript为其节点设置动画,使任何部分像

一样响应鼠标或键盘事件。正如在以下部分中将更清楚地看到的那样,当您需要在下一个项目中在Canvas和SVG之间进行选择时,这种差异起着重要的作用。

即时模式和保留模式

区分即时模式和保留模式至关重要。HTML5 Canvas是前者的示例,SVG是后者的示例。

即时模式意味着,一旦您的绘图在画布上,画布就会停止跟踪它。换句话说,作为开发人员,您需要制定绘制对象的命令,创建和维护最终输出应是什么样子的模型或场景,并指定需要更新的内容。浏览器的图形API只是将您的绘图命令传达给浏览器,然后浏览器执行这些命令。

SVG使用保留模式,您只需发出要在屏幕上显示的内容的绘图指令,浏览器的图形API就会创建最终输出的内存中模型或场景,并将其转换为浏览器的绘图命令。

作为即时图形系统,Canvas没有DOM或文档对象模型。使用Canvas,您绘制像素,系统会忘记所有这些像素,从而减少了维护绘图内部模型所需的额外内存。使用SVG,您绘制的每个对象都会添加到浏览器的内部模型中,这使得您作为开发人员的生活更容易一些,但在性能方面会付出一些代价。

基于即时模式和保留模式之间的区别,以及Canvas和SVG各自的其他特定特性,可以概述一些使用一种技术而不是另一种技术可能更好地服务于项目目标的情况。

HTML5 Canvas:优点和缺点

HTML5 Canvas规范明确建议作者不应在有其他更合适的方法可用时使用元素。

例如,对于图形丰富的元素,最好的工具是HTML和CSS,而不是(顺便说一句,SVG也不是)。Zim JS画布框架的创建者和创始人Dr Abstract证实了这种观点,他写道:

DOM和DOM框架擅长显示信息,特别是文本信息。相比之下,画布是一张图片。文本可以添加到画布中,并且可以使其具有响应性,但文本不能像在DOM上那样轻松地被选择或搜索。长滚动文本页面或文本和图像页面是DOM的绝佳用途。DOM非常适合社交媒体网站、论坛、购物以及我们习惯使用的所有信息应用程序。——“何时使用JavaScript画布库或框架”

因此,这是一个关于何时不使用的明确示例。但是,何时是一个不错的选择呢?

(此处应嵌入Sarah Drasner的推文截图)

HTML5 Canvas擅长什么?

Alvin Wan根据绘制的对象数量和对象或画布本身的大小,对Canvas和SVG的性能进行了基准测试。他将结果总结如下:

总之,当处理数百甚至数千个对象时,DOM渲染的开销更为明显;在这种情况下,Canvas是明显的赢家。但是,画布和SVG都不受对象大小的影响。鉴于最终统计数据,画布在性能方面提供了明显的优势。

根据我们对Canvas的了解,特别是它在绘制大量对象方面的出色性能,以下是一些可能适合甚至优于SVG的场景。

游戏和生成式艺术

对于图形密集型高度交互式游戏,以及生成式艺术,Canvas通常是最佳选择。

光线追踪

光线追踪是一种创建3D图形的技术。

光线追踪可用于通过追踪图像平面中像素的光线路径并模拟其与虚拟对象的相遇效果来填充图像……光线追踪实现的效果……范围从……从简单的矢量图形创建逼真的图像到应用类似照片的滤镜以去除红眼。——SVG与Canvas:如何选择,Microsoft Docs。

如果您好奇,这是Mark Webster正在运行的光线追踪应用程序。

Canvas vs SVG: Choosing the Right Tool for the Job

但是,尽管HTML5 Canvas肯定比SVG更适合这项任务,但这并不一定意味着光线追踪最好在元素上执行。事实上,对CPU的压力可能相当大,以至于浏览器可能会停止响应。

在小表面上绘制大量对象

另一个示例是应用程序需要在相对较小的表面上绘制大量对象的场景——例如非交互式实时数据可视化,例如天气模式的图形表示。

Canvas vs SVG: Choosing the Right Tool for the Job

视频中的像素替换

如这篇HTML5 Doctor文章所示,另一个适合使用Canvas的示例是将视频背景颜色替换为不同的颜色、另一个场景或图像。

Canvas vs SVG: Choosing the Right Tool for the Job

HTML5 Canvas不擅长什么?

另一方面,在许多情况下,与SVG相比,Canvas可能不是最佳选择。

可缩放性

大多数可缩放性是优势的场景都将更好地使用SVG而不是Canvas。高保真、复杂的图形,如建筑和工程图、组织结构图、生物图等,就是这种情况的例子。

使用SVG绘制时,放大图像或打印图像会保留所有细节,达到很高的质量水平。您还可以从数据库生成这些文档,这使得SVG的XML格式非常适合这项任务。

此外,这些图形通常是交互式的。例如,当您在线预订机票时,请考虑座位图,这使其成为SVG等保留图形系统的绝佳用例。

也就是说,借助CreateJS和Zim(扩展CreateJS)等一些优秀的库,开发人员可以相对快速地将其鼠标事件、命中测试、多点触控手势、拖放功能、控件等等集成到基于Canvas的创作中。

可访问性

尽管您可以采取一些步骤来提高Canvas图形的可访问性——一个好的Canvas库(如Zim)可以帮助您加快此过程——但在可访问性方面,Canvas并不出色。您在画布表面上绘制的内容只是一堆像素,辅助技术或搜索引擎机器人无法读取或解释这些像素。这是SVG更可取的另一个领域:SVG只是XML,这使得人和机器都可以读取它。

不依赖于JavaScript

如果您不想在应用程序中使用JavaScript,那么Canvas就不是您的最佳选择。事实上,您使用元素的唯一方法是使用JavaScript。相反,您可以使用Adobe Illustrator或Inkscape等标准矢量编辑程序绘制SVG图形,并且可以使用纯CSS来控制其外观并执行引人注目的、细微的动画和微交互。

将HTML5 Canvas和SVG结合用于高级场景

在某些情况下,您的应用程序可以通过结合HTML5 Canvas和SVG来获得两全其美。例如,基于Canvas的游戏可以使用矢量编辑程序生成的SVG图像作为精灵,以利用其可缩放性和与PNG图像相比更小的下载大小。或者,绘图程序可以使用SVG设计其用户界面,并嵌入元素用于绘图。

最后,像Paper.js这样功能强大的库可以使您能够在HTML5 Canvas之上编写矢量图形脚本,从而为开发人员提供了一种方便的方式来同时使用这两种技术。

结论

在本文中,我探讨了HTML5 Canvas和SVG的一些关键特性,以帮助您确定哪种技术最适合特定任务。

答案是什么?

Chris Coyier同意Benjamin De Cock的观点,后者在推特上写道:

回答这个问题的一种极其基本的方法是“当您无法使用svg时使用canvas”(其中“无法”可能意味着动画化数千个对象、单独操作每个像素等)。换句话说,SVG应该是您的默认选择,canvas是您的备用方案。

— Benjamin De Cock (@bdc) 2019年10月2日

Dr Abstract提供了许多最适合使用Canvas构建的事物清单,包括交互式徽标和广告、交互式信息图表、电子学习应用程序等等。

在我看来,对于何时最好使用Canvas而不是SVG,并没有什么硬性规定。即时模式和保留模式之间的区别表明,在构建图形密集型游戏等方面,HTML5 Canvas是无可争议的赢家,而对于平面图像、图标和UI元素等,SVG则更可取。但是,在这两者之间,HTML5 Canvas还有扩展其应用范围的空间,特别是考虑到各种强大的Canvas库可以提供什么。它们不仅使在同一图形工作中更容易同时使用这两种技术,而且还使Canvas原生项目中一些难以实现的功能(如交互式控件和事件、响应能力、可访问性功能等等)现在可以为大多数开发人员所用,这为HTML5 Canvas更有趣的用途打开了大门。

Canvas与SVG的常见问题解答 (FAQs)

(此处应包含FAQ部分,根据原文内容进行改写,保持简洁明了,并使用更自然的语言表达。)

最新教學 更多>
  • 如何在Java字符串中有效替換多個子字符串?
    如何在Java字符串中有效替換多個子字符串?
    在java 中有效地替換多個substring,需要在需要替換一個字符串中的多個substring的情況下,很容易求助於重複應用字符串的刺激力量。 However, this can be inefficient for large strings or when working with nu...
    程式設計 發佈於2025-07-23
  • 反射動態實現Go接口用於RPC方法探索
    反射動態實現Go接口用於RPC方法探索
    在GO 使用反射來實現定義RPC式方法的界面。例如,考慮一個接口,例如:鍵入myService接口{ 登錄(用戶名,密碼字符串)(sessionId int,錯誤錯誤) helloworld(sessionid int)(hi String,錯誤錯誤) } 替代方案而不是依靠反射...
    程式設計 發佈於2025-07-23
  • C++20 Consteval函數中模板參數能否依賴於函數參數?
    C++20 Consteval函數中模板參數能否依賴於函數參數?
    [ consteval函數和模板參數依賴於函數參數在C 17中,模板參數不能依賴一個函數參數,因為編譯器仍然需要對非contexexpr futcoriations contim at contexpr function進行評估。 compile time。 C 20引入恆定函數,必須在編譯時進...
    程式設計 發佈於2025-07-23
  • 為什麼PHP的DateTime :: Modify('+1個月')會產生意外的結果?
    為什麼PHP的DateTime :: Modify('+1個月')會產生意外的結果?
    使用php dateTime修改月份:發現預期的行為在使用PHP的DateTime類時,添加或減去幾個月可能並不總是會產生預期的結果。正如文檔所警告的那樣,“當心”這些操作的“不像看起來那樣直觀。 ; $ date->修改('1個月'); //前進1個月 echo $ date->...
    程式設計 發佈於2025-07-23
  • 在Python中如何創建動態變量?
    在Python中如何創建動態變量?
    在Python 中,動態創建變量的功能可以是一種強大的工具,尤其是在使用複雜的數據結構或算法時,Dynamic Variable Creation的動態變量創建。 Python提供了幾種創造性的方法來實現這一目標。 利用dictionaries 一種有效的方法是利用字典。字典允許您動態創建密鑰並...
    程式設計 發佈於2025-07-23
  • 為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
    為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
    The Mystery of "Broken" Two-Phase Template Instantiation in Microsoft Visual C Problem Statement:Users commonly express concerns that Micro...
    程式設計 發佈於2025-07-23
  • 使用jQuery如何有效修改":after"偽元素的CSS屬性?
    使用jQuery如何有效修改":after"偽元素的CSS屬性?
    在jquery中了解偽元素的限制:訪問“ selector 嘗試修改“:”選擇器的CSS屬性時,您可能會遇到困難。 This is because pseudo-elements are not part of the DOM (Document Object Model) and are th...
    程式設計 發佈於2025-07-23
  • 為什麼在我的Linux服務器上安裝Archive_Zip後,我找不到“ class \” class \'ziparchive \'錯誤?
    為什麼在我的Linux服務器上安裝Archive_Zip後,我找不到“ class \” class \'ziparchive \'錯誤?
    class'ziparchive'在Linux Server上安裝Archive_zip時找不到錯誤 commant in lin ins in cland ins in lin.11 on a lin.1 in a lin.11錯誤:致命錯誤:在... cass中找不到類z...
    程式設計 發佈於2025-07-23
  • 為什麼HTML無法打印頁碼及解決方案
    為什麼HTML無法打印頁碼及解決方案
    無法在html頁面上打印頁碼? @page規則在@Media內部和外部都無濟於事。 HTML:Customization:@page { margin: 10%; @top-center { font-family: sans-serif; font-weight: ...
    程式設計 發佈於2025-07-23
  • 同實例無需轉儲複製MySQL數據庫方法
    同實例無需轉儲複製MySQL數據庫方法
    在同一實例上複製一個MySQL數據庫而無需轉儲在同一mySQL實例上複製數據庫,而無需創建InterMediate sqql script。以下方法為傳統的轉儲和IMPORT過程提供了更簡單的替代方法。 直接管道數據 MySQL手動概述了一種允許將mysqldump直接輸出到MySQL cli...
    程式設計 發佈於2025-07-23
  • 如何使用組在MySQL中旋轉數據?
    如何使用組在MySQL中旋轉數據?
    在關係數據庫中使用mySQL組使用mySQL組進行查詢結果,在關係數據庫中使用MySQL組,轉移數據的數據是指重新排列的行和列的重排以增強數據可視化。在這裡,我們面對一個共同的挑戰:使用組的組將數據從基於行的基於列的轉換為基於列。 Let's consider the following ...
    程式設計 發佈於2025-07-23
  • 如何在鼠標單擊時編程選擇DIV中的所有文本?
    如何在鼠標單擊時編程選擇DIV中的所有文本?
    在鼠標上選擇div文本單擊帶有文本內容,用戶如何使用單個鼠標單擊單擊div中的整個文本?這允許用戶輕鬆拖放所選的文本或直接複製它。 在單個鼠標上單擊的div元素中選擇文本,您可以使用以下Javascript函數: function selecttext(canduterid){ if(d...
    程式設計 發佈於2025-07-23
  • 在JavaScript中如何並發運行異步操作並正確處理錯誤?
    在JavaScript中如何並發運行異步操作並正確處理錯誤?
    同意操作execution 在執行asynchronous操作時,相關的代碼段落會遇到一個問題,當執行asynchronous操作:此實現在啟動下一個操作之前依次等待每個操作的完成。要啟用並發執行,需要進行修改的方法。 第一個解決方案試圖通過獲得每個操作的承諾來解決此問題,然後單獨等待它們: c...
    程式設計 發佈於2025-07-23
  • 為什麼我在Silverlight Linq查詢中獲得“無法找到查詢模式的實現”錯誤?
    為什麼我在Silverlight Linq查詢中獲得“無法找到查詢模式的實現”錯誤?
    查詢模式實現缺失:解決“無法找到”錯誤在銀光應用程序中,嘗試使用LINQ建立錯誤的數據庫連接的嘗試,無法找到以查詢模式的實現。 ”當省略LINQ名稱空間或查詢類型缺少IEnumerable 實現時,通常會發生此錯誤。 解決問題來驗證該類型的質量是至關重要的。在此特定實例中,tblpersoon可能...
    程式設計 發佈於2025-07-23
  • PHP未來:適應與創新
    PHP未來:適應與創新
    PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。 引言在編程世界中,PHP一直是網頁開發的中流砥柱。作為一個從1994年就開始發展...
    程式設計 發佈於2025-07-23

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3