在web上做动画我们有很多选择:svg,dom,canvas,flash等等。但是根据业务场景我们一定能找到最优的技术解决方案,但是何时选择dom,何时使用canvas呢,以及2者的区别是什么呢。是选择能快速开发的dom,还是选择对性能消耗较小的canvas呢。下文从浏览器渲染方面对技术选型做了解释。
Did you know that you have a choice in how you can get things to display in your browser? Well...you do! The most common approach for getting content to display on your screen is by working with DOM elements. This is where you (and 99% of the entire world) create HTML, CSS, and JavaScript and have elements appear magically. The other approach uses the canvas element. With a canvas, you manually specify exactly what you want drawn and displayed on your screen. Both of these approaches have their uses. For the kinds of visually complex applications you will be creating, knowing when to use which is a good thing for you to be aware of.
To help you with this, let's take a step back. In fact, let's take many steps back and look at how our two approaches map to how your browser translates what you want into something that gets displayed. Core to this translation are two modes called Retained Mode and Immediate Mode. While it may not seem like it right now, understanding the details of both of these modes will help you know when to rely on the DOM APIs and when to use canvas to display visuals on the screen.
为了让你理解这些,让我们回到很早以前看看这2种转换方法是如何将你要展示的内容显示到浏览器中的。这个命令的转换的核心有2种:驻留模式和快速模式。我解释的虽然现在看起来不太准确,但是理解这2种转换的细节将会帮助你知道你何时该使用DOM、何时该使用canvas来完成你的图形展示。
Onwards!
让我们继续
Retained Mode (DOM)
驻留模式
In a retained mode system, the way you get things to display on the screen is by sending your hopes, dreams, and desires to your browser's Graphics API. This API, much like Santa Claus, gives you whatever you ask for.
在驻留模式中,你通过浏览器图形化接口让显示器显示你想展示的东西。这个接口就像圣诞老人,给你你想要的。
The following diagram roughly describes the division of labor between you, the Graphics API, and your browser:
下面的图片粗略的描述了你、图形化接口、浏览器之间的工作分割
The yellow box represents the HTML, CSS, and JavaScript that makes up your application. While you may not have thought about your markup and code in quite this way, almost everything you specify is nothing more than a drawing instruction that tells your browser what to display on the screen.
黄色盒子代表构建你应用的html、css和js。虽然你可能没有想过这个api的具体实现,但是api帮助你完成你定义的结构,然后转换,然后将转换展示到显示器上。
This translation between your raw markup and code to something visual is handled by your browser's Graphics API. This API takes what you specify and creates an in-memory model (often referred to as a scene, object list or display list) of what the final output should look like. Once it creates this model, the final step is to translate the model into the arcane draw commands that your browser understands.
你的原始标记代码变成可视化图形是通过图形接口来转换的。图形化接口需要你指定和创建一个存在内存的模型(我们可以称之为场景,对象列表和显示列表),这个模型最终会输出一个你输入的图像。一旦api创建了这个模型,那么最后一步就是api就会把模型表述的图像通过浏览器能理解的命令画在你的浏览器。
All of this happens very seamlessly behind the scenes. You simply define your application. The details of getting what you defined into something you can see is automatically handled for you.
所以的这一切都是在后台无缝的完成。你只需要写好html,css,js定义好你的app。api会自动帮你处理好你定义的东西。
Immediate Mode (Canvas)
快速模式
Contrasting the gentle comforts of a retained mode system is the immediate mode one where...well, let's just look at the diagram first:
相对于使用起来很舒服的驻留模式就是立即模式,让我先看看下面这张图:
In an immediate mode system, you do all of the heavy lifting. You not only specify what needs to be drawn, you also create and maintain the model as well. As if all of this wasn't enough, you also specify the draw commands to get your browser to actually update! Your browser's Graphics API, the API that did so much for you in the retained mode world, doesn't do much here. It simply takes your draw commands and sends them off to the browser for execution.
在立即模式系统中,你的工作量有很大的提升。你不仅需要指定什么需要画,你还要创建和维护一个模型。
In HTML, immediate mode comes into play when you are using the canvas element. Anything you wish to draw inside it requires you to issue primitive draw commands and handle all aspects of managing the scene and redrawing when changes happen.
在html中canvas的渲染就是使用快速模式。在快速模式中,你想要画的东西是通过原始的画图命令并且你要管理好当前场景和重绘时带来的改变。
When to Use Which?
如何抉择
Whenever a section heading promises a clear answer, you know that the answer is never clear. This time is no exception. Choosing between the immediate mode-ness of the canvas and the retained mode-ness of your DOM is not an exclusive decision. It can actually be quite scandalous! You can choose just one, the other, or even both.
In this section, let's build on the overview you saw in the previous section and look at the advantages and disadvantages of each of the approaches.
在这个部分,让我们建立在你以前看的概述部分,看看2种技术实现的优点和缺点。
The DOM
The DOM
Since we are talking about the DOM here, you will spend a majority of the time, possibly even all of your time, in this retained mode world. Despite the comforts it provides, it isn't perfect.
既然我们开始探讨dom了,那么我们将会在驻留模式中花较多时间,或者更多时间来理解它。
Let's look at its perfections and imperfections in more detail:
让我们来详细看看dom的优点和缺点
- Easy to use. The DOM abstracts away a lot of the details that would otherwise get you bogged down. Examples of details that can bog down even the best of us include layout, event handling, clean up, selection/highlighting, accessibility, being DPI friendly, and so on.
- Redrawing is handled for you. You only specify what you want to display on the screen. The details of how to do that and how often to refresh are all left to the Graphics API to handle.
- CSS! CSS! CSS! You can easily modify the visuals of your DOM elements using CSS.
- Animations are easy to define and modify. Because of the CSS support, you can easily define animations or transitions, specify an easing function, make a few other tweaks, and you are good to go. This applies to JavaScript-based animations as well. If you are using JavaScript to animate an element's properties, you just have to get your requestAnimationFrame loop setup to update the property values. Everything else is taken care off...such as when to redraw or how to maintain a smooth frame rate.
- Memory intensive. You know all of the details that get taken care of for you when using a DOM element? Well, that care doesn't come cheap. Your DOM elements are very complex little things, and all of this complexity takes up space in your browser's memory. The more elements you are dealing with, the more resource hungry it all gets.
Less control over how things get drawn. For certain graphics-related tasks, the default rendering may be a bit limiting. Browsers optimize for their particular needs, and those optimizations may go counter to what you want to do.
- 使用简单。DOM封装了很多细节出来以让你简单使用。比如布局,事件,移除,选择,可访问,甚至可以像素级别的控制,等等
- 你可以控制重绘。你只需要在显示器指定你希望展示的内容。而展示的细节和刷新频率完全是交给api来完成的。
- 你可以简单的通过css来改变dom的展示样式
- 动画是很容易定义和修改的。通过css你可以很容易的定义动画和变形,或者可以指定一个动画函数。当然通过js来完成动画也是可以的。如果你使用js修改元素属性来完成动画,你只需要通过requestAnimationFrame循环来修改属性值。而其他的一切都是给api来完成...比如什么做重绘或者如何做到平滑的动画帧率。
- 内存消耗。你确定当你使用dom的时候你知道api的实现细节?api帮你做的事可不是很便宜。你的dom节点是一个很复杂的小东西,而复杂性和内存消耗成正比。你需要的dom越多,就越吃内存。
无法控制绘画的细节。在某些绘画场景中,默认的渲染可能有很多限制。浏览器会做出一些它自己的优化,而这个优化可能与你想做的事相反
The Canvas
If this were a popularity contest, I would feel pretty bad for immediate mode and the canvas element that uses it. Fortunately, it isn't! Immediate mode systems certainly carry their own weight - even in the more limited cases they are used in.
如果这是一个流行的比赛,我对canvas元素使用立即模式感到很糟糕。幸运的是,canvas并不是这样。
Let's look at some of their cool (and less cool) features in more detail:
让我们来详细看看它很酷(和一些不酷)的特性。
- Fast. Really fast. Because an immediate mode system doesn't maintain its own model, your code is all that stands between you and the browser redrawing. The many layers of abstraction that slow operations down simply do not exist in the immediate mode world.
- You have a lot of flexibility. Since your code controls all aspects of when and how something is drawn to the screen, you can tweak and customize the output any way you would like.
- Great for dealing with many elements. Compared to a retained mode system where every little addition to your scene takes up extra memory, immediate mode systems don't have that problem. Generally, an immediate mode system will always use less memory than a retained mode system - something that becomes more noticeable as you add more and more elements into the mix.
- It can be slow when drawing to large areas. How quickly a redraw completes is proportional to the number of pixels you are re-drawing. If your addressing a really large area, things could get slower if you are not careful and do not optimize appropriately.
- It is complex. Because you are handling more of what it takes to get something to display on the screen, there are a lot more details for you to keep track of. Getting up to speed with the various draw commands and how they are used is no picnic either.
- 快速、真的很快。因为在立即模式中,它不需要维护视图模型,所以的浏览器重绘都是基于你的代码。在立即模式中不存在能让处理变慢的多层次抽象。
- 灵活性很高。一旦你可以通过你的代码可以方方面面何时绘制到屏幕,那么你可以用你喜欢的渲染方式想怎么画就怎么画
- 可以控制更多的元素。相比驻留模式中的每增加一点东西到场景中就要消耗一些内存,及时模式并没有这个问题。一般来说,在立即模式中消耗的内存比驻留模式少——在你添加了很多元素时这种现象越发的明显。
- 当你需要展示一个很大的图像时,性能就会变的很差。因为重绘的复杂度和你图像的像素成正相关。如果你不够仔细并且不做优化,当你画越大图像你会渲染的越慢
- 复杂。随着你需要处理更多的展示内容,你就越要关注图像渲染细节。快速掌握各种绘图命令和它们是如何使用的是不是件容易的事。
Summary
总结
Understanding the retained mode and immediate mode differences makes it much easier to sympathize with the DOM on certain things and with the canvas on others. By now, hopefully you have a good idea of when to use one over the other. In case it helps, here is my short list on when I use canvas and when I use the DOM.
理解了保留模式和直接模式的差异,会让你更简单的区分何时该使用dom,何时该使用canvas。到现在为止,希望你能明白如何抉择。如果我所讲的对你有帮助,那么我对何时用dom何时用canvas做了一个简短列表
When I Use a Canvas
我何时选择canvas
- Complex visualizations
- Animations involving content that nobody needs to interact with ((example)[http://www.kirupa.com/snippets/amorphous_circles_snippet.htm])
Pixel manipulation (example)
- 复杂的动画
- 弱人机交互的动画
像素级别处理
When I Use the DOM
我何时选择DOM
This is pretty simple. I use the DOM for everything else that I don't use a canvas for. The canvas has very limited uses for the kinds of things that I do.
这很简单,只要我不用canvas我就用dom完成动画。在很多我的产品实现中canvas有很大局限性。