Html 快速响应的交互式图表/图形:SVG、Canvas 还是其他?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12310024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 02:42:39  来源:igfitidea点击:

Fast and responsive interactive charts/graphs: SVG, Canvas, other?

htmlcanvassvgd3.jskineticjs

提问by Andrew Mao

I am trying to choose the right technology to use for updating a project that basically renders thousands of points in a zoomable, pannable graph. The current implementation, using Protovis, is underperformant. Check it out here:

我正在尝试选择正确的技术来更新一个项目,该项目基本上在可缩放、可平移的图形中呈现数千个点。当前使用 Protovis 的实现性能不佳。在这里查看:

http://www.planethunters.org/classify

http://www.planethunters.org/classify

There are about 2000 points when fully zoomed out. Try using the handles on the bottom to zoom in a bit, and drag it to pan around. You will see that it is quite choppy and your CPU usage probably goes up to 100% on one core unless you have a really fast computer. Each change to the focus area calls a redraw to protovis which is pretty darn slow and is worse with more points drawn.

完全缩小时大约有 2000 个点。尝试使用底部的手柄放大一点,然后拖动它来平移。您会看到它非常不稳定,除非您拥有一台非常快的计算机,否则您的 CPU 使用率可能会在一个内核上达到 100%。对焦点区域的每次更改都会调用对 protovis 的重绘,这非常慢,并且绘制的点越多越糟糕。

I would like to make some updates to the interface as well as change the underlying visualization technology to be more responsive with animation and interaction. From the following article, it seems like the choice is between another SVG-based library, or a canvas-based one:

我想对界面进行一些更新,并更改底层的可视化技术,以提高动画和交互的响应速度。从下面的文章中,似乎可以在另一个基于 SVG 的库或基于画布的库之间进行选择:

http://www.sitepoint.com/how-to-choose-between-canvas-and-svg/

http://www.sitepoint.com/how-to-choose-between-canvas-and-svg/

d3.js, which grew out of Protovis, is SVG-based and is supposed to be better at rendering animations. However, I'm dubious as to how much better and what its performance ceiling is. For that reason, I'm also considering a more complete overhaul using a canvas-based library like KineticJS. However, before I get too far into using one approach or another, I'd like to hear from someone who has done a similar web application with this much data and get their opinion.

d3.js 源于Protovis,是基于 SVG 的,应该更擅长渲染动画。但是,我怀疑它的性能上限是多少。出于这个原因,我也在考虑使用像KineticJS这样的基于画布的库进行更全面的改革。但是,在我深入使用一种或另一种方法之前,我想听听已经使用这么多数据完成类似 Web 应用程序的人的意见,并听取他们的意见。

The most important thing is performance, with a secondary focus on ease of adding other interaction features and programming the animation. There will probably be no more than 2000 points at once, with those small error bars on each one. Zooming in, out, and panning around need to be smooth.If the most recent SVG libraries are decent at this, then perhaps the ease of using d3 will outweigh the increased setup for KineticJS, etc. But if there is a huge performance advantage to using a canvas, especially for people with slower computers, then I would definitely prefer to go that way.

最重要的是性能,其次是易于添加其他交互功能和编写动画。一次可能不会超过 2000 个点,每个点上都有那些小误差条。放大、缩小和平移需要平滑。如果最新的 SVG 库在这方面表现不错,那么使用 d3 的便利性可能会超过 KineticJS 等增加的设置。但是如果使用画布有巨大的性能优势,尤其是对于计算机速度较慢的人,那么我肯定更愿意走那条路。

Example of app made by the NYTimes that uses SVG, but still animates acceptably smoothly: http://www.nytimes.com/interactive/2012/05/17/business/dealbook/how-the-facebook-offering-compares.html. If I can get that performance and not have to write my own canvas drawing code, I would probably go for SVG.

NYTimes 使用 SVG 制作的应用程序示例,但动画仍然可以接受:http://www.nytimes.com/interactive/2012/05/17/business/dealbook/how-the-facebook-offering-compares.html . 如果我可以获得那种性能并且不必编写自己的画布绘图代码,我可能会选择 SVG。

I noticed that some users have used a hybrid of d3.js manipulation combined with canvas rendering. However, I can't find much documentation about this online or get in contact with the OP of that post. If anyone has any experience doing this kind of DOM-to-Canvas (demo, code) implementation, I would like to hear from you as well. It seems to be a good hybrid of being able to manipulate data and having custom control over how to render it (and therefore performance), but I'm wondering if having to load everything into the DOM is still going to slow things down.

我注意到一些用户使用了d3.js 操作与画布渲染的混合。但是,我在网上找不到太多关于此的文档或与该帖子的 OP 取得联系。如果有人在执行这种 DOM 到画布(演示代码)实现方面有任何经验,我也希望收到您的来信。它似乎是能够操作数据和对如何呈现数据(以及性能)进行自定义控制的很好的混合体,但我想知道是否必须将所有内容加载到 DOM 中仍然会减慢速度。

I know that there are some existing questions that are similar to this one, but none of them exactly ask the same thing. Thanks for your help.

我知道存在一些与此类似的现有问题,但没有一个问的完全相同。谢谢你的帮助。

Follow-up: the implementation I ended up using is at https://github.com/zooniverse/LightCurves

跟进:我最终使用的实现是在https://github.com/zooniverse/LightCurves

回答by mbostock

Fortunately, drawing 2000 circles is a pretty easy example to test. So here are four possible implementations, two each of Canvas and SVG:

幸运的是,绘制 2000 个圆是一个非常容易测试的示例。所以这里有四种可能的实现,Canvas 和 SVG 各两个:

These examples use D3's zoom behaviorto implement zooming and panning. Aside from whether the circles are rendered in Canvas or SVG, the other major distinction is whether you use geometricor semanticzooming.

这些示例使用 D3 的缩放行为来实现缩放和平移。除了圆是在 Canvas 还是 SVG 中渲染之外,另一个主要区别是您使用几何缩放还是语义缩放。

Geometric zooming means you apply a single transform to the entire viewport: when you zoom in, circles become bigger. Semantic zooming in contrast means you apply transforms to each circle individually: when you zoom in, the circles remain the same size but they spread out. Planethunters.org currently uses semantic zooming, but it might be useful to consider other cases.

几何缩放意味着您将单个变换应用于整个视口:当您放大时,圆圈会变大。对比语义缩放意味着您单独对每个圆应用变换:当您放大时,圆保持相同的大小,但它们会散开。Planethunters.org 目前使用语义缩放,但考虑其他情况可能会有用。

Geometric zooming simplifies the implementation: you apply a translate and scale once, and then all the circles are re-rendered. The SVG implementation is particularly simple, updating a single "transform" attribute. The performance of both geometric zooming examples feels more than adequate. For semantic zooming, you'll notice that D3 is significantly faster than Protovis. This is because it's doing a lot less work for each zoom event. (The Protovis version has to recalculate all attributes on all elements.) The Canvas-based semantic zooming is a bit more zippy than SVG, but SVG semantic zooming still feels responsive.

几何缩放简化了实现:您应用一次平移和缩放,然后重新渲染所有圆。SVG 实现特别简单,只需更新一个“transform”属性。两个几何缩放示例的性能感觉都绰绰有余。对于语义缩放,您会注意到 D3 比 Protovis 快得多。这是因为它为每个缩放事件做的工作要少得多。(Protovis 版本必须重新计算所有元素的所有属性。)基于 Canvas 的语义缩放比 SVG 快一些,但 SVG 语义缩放仍然感觉响应灵敏。

Yet there is no magic bullet for performance, and these four possible approaches don't begin to cover the full space of possibilities.For example, you could combine geometric and semantic zooming, using the geometric approach for panning (updating the "transform" attribute) and only redrawing individual circles while zooming. You could probably even combine one or more of these techniques with CSS3 transforms to add some hardware acceleration (as in the hierarchical edge bundling example), although that can be tricky to implement and may introduce visual artifacts.

然而,性能没有灵丹妙药,这四种可能的方法并没有开始涵盖所有可能性。例如,您可以结合几何和语义缩放,使用几何方法进行平移(更新“变换”属性),并且在缩放时仅重绘单个圆圈。您甚至可以将这些技术中的一种或多种与 CSS3 转换相结合,以添加一些硬件加速(如分层边缘捆绑示例中所示),尽管这可能难以实现并且可能会引入视觉伪影。

Still, my personal preference is to keep as much in SVG as possible, and use Canvas only for the "inner loop" when rendering is the bottleneck. SVG has so many conveniences for development—such as CSS, data-joins and the element inspector—that it is often premature optimization to start with Canvas. Combining Canvas with SVG, as in the Facebook IPO visualization you linked, is a flexible way to retain most of these conveniences while still eking out the best performance. I also used this technique in Cubism.js, where the special case of time-series visualization lends itself well to bitmap caching.

不过,我个人的偏好是尽可能多保留在 SVG 中,并且在渲染成为瓶颈时仅将 Canvas 用于“内部循环”。SVG 为开发提供了如此多的便利——例如 CSS、数据连接和元素检查器——以至于从 Canvas 开始通常是过早的优化。将 Canvas 与 SVG 相结合,就像在您链接的 Facebook IPO 可视化中一样,是一种灵活的方式,可以保留大部分这些便利,同时仍然保持最佳性能。我还在Cubism.js 中使用了这种技术,其中时间序列可视化的特殊情况非常适合位图缓存。

As these examples show, you can use D3 with Canvas, even though parts of D3 are SVG-specific. See also this force-directed graphand this collision detection example.

如这些示例所示,您可以将 D3 与 Canvas 一起使用,即使 D3 的某些部分是特定于 SVG 的。另请参阅此力导向图和此碰撞检测示例

回答by philipp

I think that in your casethe decision between canvas and svg is not like a decision between ?riding a Horse? or driving a ?Porsche?. For me it is more like the decision about the cars color.

我认为在你的情况下,canvas 和 svg 之间的决定不像骑马?或驾驶?保时捷?。对我来说,这更像是关于汽车颜色的决定。

Let me explain: Assuming that, based on the framework the operations

让我解释一下:假设,基于框架的操作

  • draw a star,
  • add a star and
  • remove a star
  • 画一颗星星,
  • 添加一颗星和
  • 删除一颗星

take linear time. So, if your decision of the framework was good it is a bit faster, otherwise a bit slower.

采取线性时间。所以,如果你对框架的决定是好的,它会快一点,否则会慢一点。

If you go on assuming that the framework is just fast, than it becomes totally obvious that the lack of performance is caused be the high amount of stars and handling them is something none of the frameworks can do for you, at least I do not know about this.

如果你继续假设框架很快,那么很明显,性能不足是由大量的星星造成的,处理它们是任何框架都无法为你做的,至少我不知道对这个。

What I want to say is that the base of the problem leads to a basic problem of computational geometry, namely: range searchingand another one of computer graphics: level of detail.

我想说的是,问题的基础引出了计算几何的一个基本问题,即:范围搜索和另一个计算机图形学:细节层次

To solve your performance problem you need to implement a good preprocessor which is able to find very fast which stars to display and is perhaps able to cluster stars which are close together, depending on the zoom. The only thing that keeps your view vivid and fast is keeping the number of stars to draw as low possible.

为了解决您的性能问题,您需要实现一个良好的预处理器,它能够非常快地找到要显示的星星,并且可能能够根据缩放将距离很近的星星聚类。唯一能让您的视图保持生动和快速的方法是尽可能减少要绘制的星星数量。

As you stated, that the most important thing is performance, than I would tend to use canvas, because it works without DOM operations. It also offers the opportunity to use webGL, what increases graphic performance a lot.

正如您所说,最重要的是性能,而不是我倾向于使用画布,因为它无需 DOM 操作即可工作。它还提供了使用 webGL 的机会,这大大提高了图形性能。

BTW: did you check paper.js? It uses canvas, but emulates vector graphics.

顺便说一句:你检查paper.js 了吗?它使用画布,但模拟矢量图形。

PS: In this Bookyou can find a very detailed discussion about graphics on the web, the technologies, pros and cons of canvas, SVG and DHTML.

PS:在本书中,您可以找到有关 Web 图形、技术、canvas、SVG 和 DHTML 的优缺点的非常详细的讨论。

回答by user432024

I recently worked on a near-realtime dashboard (refresh every 5 seconds) and chose to use charts that render using canvas.

我最近在一个近实时仪表板(每 5 秒刷新一次)上工作,并选择使用使用画布呈现的图表。

We tried Highcharts(SVG based JavaScript Charting library) and CanvasJS(Canvas based JavaScript Charting library). Although Highcharts is a fantastic charting API and offers way more features we decided to use CanvasJS.

我们尝试了 Highcharts(基于 SVG 的 JavaScript 图表库)和 CanvasJS(基于 Canvas 的 JavaScript 图表库)。尽管 Highcharts 是一个很棒的图表 API 并且提供了更多的功能,但我们还是决定使用 CanvasJS。

We needed to display at least 15 minutes of data per chart (with option to pick range of max two hours).

我们需要为每个图表显示至少 15 分钟的数据(可选择最多两个小时的范围)。

So for 15 minutes: 900 points(data point per second) x2(line and bar combination chart) x4 charts = 7200 points total.

所以 15 分钟:900 点(每​​秒数据点)x2(线和条组合图)x4 图表 = 总共 7200 点。

Using chrome profiler, with CanvasJS the memory never went above 30MB while with Highcharts memory usage exceeded 600MB.

使用 chrome profiler,CanvasJS 内存从未超过 30MB,而 Highcharts 内存使用量超过 600MB。

Also with refresh time of 5 seconds CanvasJS rendering was allot more responsive then Highcharts.

此外,刷新时间为 5 秒,CanvasJS 渲染比 Highcharts 响应更快。

We used one timer (setInterval 5 seconds) to make 4 REST API calls to pull the data from back end server which connected to Elasticsearch. Each chart updated as data is received by JQuery.post().

我们使用一个计时器(setInterval 5 秒)进行 4 次 REST API 调用,以从连接到 Elasticsearch 的后端服务器拉取数据。JQuery.post() 接收作为数据更新的每个图表。

That said for offline reports I would go with Highcharts since its more flexible API.

也就是说,对于离线报告,我会使用 Highcharts,因为它的 API 更灵活。

There's also Zing charts which claims to use either SVG or Canvas but haven't looked at them.

还有 Zing 图表声称使用 SVG 或 Canvas,但没有看过它们。

Canvas should be considered when performance is really critical. SVG for flexibility. Not that canvas frameworks aren't flexible, but it takes allot more work for canvas framework to get the same functionality as an svg framework.

当性能真的很关键时,应该考虑画布。SVG 的灵活性。并不是画布框架不灵活,而是画布框架需要做更多的工作才能获得与 svg 框架相同的功能。

回答by Eric Rowell

Might also look into Meteor Charts, which is built on top of the uber fast KineticJS framework: http://meteorcharts.com/

也可以看看 Meteor Charts,它建立在 uber fast KineticJS 框架之上:http://meteorcharts.com/