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

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

Http://www.planethunters.org/classify

当完全放大时,大约有2000个点。尝试使用底部的手柄放大一点,并拖动它来平移。您将看到它非常不稳定,您的 CPU 使用率可能会在一个核上达到100% ,除非您拥有一台真正快速的计算机。对焦点区域的每一个变化都要求重新绘制原始视觉,这非常缓慢,而且绘制的点越多,情况就越糟糕。

我想对界面进行一些更新,同时改变底层的可视化技术,使其能够更好地响应动画和交互。从下面的文章中可以看出,要么选择另一个基于 SVG 的库,要么选择基于画布的库:

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

D3.js 是从 Protovis 发展而来的,基于 SVG,是 应该更擅长渲染动画。然而,我怀疑它的性能有多好,它的性能上限是多少。出于这个原因,我还考虑使用像 KineticJS这样的基于画布的库进行更全面的修改。然而,在我深入使用这种或那种方法之前,我想听听那些用这么多数据做过类似 web 应用程序的人的意见,并听听他们的意见。

最重要的是性能,其次是易于添加其他交互特性和动画编程。一次可能不会超过2000个点,每个点上都有小的误差线。放大,缩小,移动需要平滑。如果最新的 SVG 库在这方面还不错,那么使用 d3的容易程度可能会超过 KineticJS 增加的设置,等等。但是,如果使用画布有巨大的性能优势,特别是对于计算机速度较慢的人来说,那么我肯定更愿意这样做。

例如,纽约时报制作的应用程序使用了 SVG,但仍然可以平滑地运行: Http://www.nytimes.com/interactive/2012/05/17/business/dealbook/how-the-facebook-offering-compares.html.如果我可以获得这样的性能,而不必编写自己的画布绘图代码,我可能会选择 SVG。

我注意到一些用户使用了 d3.js manipulation combined with canvas rendering的混合体。然而,我在网上找不到太多关于这方面的文档,也联系不到那篇文章的 OP。如果有人有任何实现这种 DOM-to-Canvas (小样密码)的经验,我也想听听您的意见。它似乎是一个很好的混合体,既可以操作数据,又可以自定义控制如何呈现数据(因此也可以控制性能) ,但我想知道是否必须将所有内容加载到 DOM 中仍然会降低速度。

我知道有一些现存的问题和这个类似,但是没有一个问题是完全一样的。谢谢你的帮助。

跟进 : 我最终使用的实现位于 < a href = “ https://github.com/zooniverse/LightCurves”rel = “ norefrer”> https://github.com/zooniverse/lightcurves

38529 次浏览

我认为在 你的案子中,帆布和 svg 之间的决定并不像是“骑马”和“开保时捷”之间的决定。对我来说,这更像是关于汽车颜色的决定。

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

  • 画一颗星星,
  • 加一个星号
  • remove a star

以线性时间为单位。所以,如果你的框架的决定是好的,它会更快一点,否则就会慢一点。

如果你继续假设这个框架只是速度快,那么很明显,性能的缺乏是由于大量的星级导致的,并且处理它们是没有一个框架可以为你做的事情,至少我不知道这一点。

我想说的是,这个问题的基础导致了一个基本的计算几何问题,即: abc0和另一个计算机图形学: 详细程度

为了解决你的性能问题,你需要实现一个良好的预处理器,它能够非常快地找到星星显示,也许能够聚集星星靠近在一起,这取决于缩放。唯一能让你的视野生动和快速的就是尽可能减少画星星的数量。

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

顺便说一下: 你检查了 纸张吗? 它使用画布,但模拟矢量图形。

你可以找到一个非常详细的讨论关于网络图形,技术,利弊的画布,SVG 和 DHTML。

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

这些示例使用 D3的 zoom behavior来实现缩放和平移。除了圆圈是在 Canvas 还是 SVG 中呈现之外,另一个主要区别在于使用的是 geometric还是 语义上的缩放。

几何缩放意味着对整个视图应用一个变换: 当你放大时,圆圈会变大。相反,语义缩放意味着对每个圆应用变换: 当你放大时,这些圆保持相同的大小,但它们分散开来。Planethunters.org 目前使用语义缩放,但考虑其他情况可能会有用。

几何缩放简化了实现: 您只需要应用一次转换和缩放,然后所有的圆都会被重新呈现。SVG 实现特别简单,只需更新一个“转换”属性。两个几何缩放示例的性能感觉都非常好。对于语义缩放,您将注意到 D3明显比 Protovis 快。这是因为它为每个缩放事件做的工作要少得多。(Protovis 版本必须重新计算所有元素的所有属性。)基于 Canvas 的语义缩放比 SVG 稍微快一些,但是 SVG 的语义缩放仍然感觉有反应。

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

尽管如此,我个人还是更喜欢 尽可能多地使用 SVG,当呈现成为瓶颈时,只在“内部循环”中使用 Canvas。SVG 在开发方面有很多便利之处,例如 CSS、数据连接和元素检查器,因此从 Canvas 开始进行优化往往为时过早。将 Canvas 与 SVG 结合起来,就像你链接的 Facebook IPO 可视化一样,是一种灵活的方式,既可以保留大部分这些便利,又可以维持最佳性能。我还在 立体主义中使用了这种技术,在 立体主义中,时间序列可视化的特殊情况很适合位图缓存。

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

也许还可以看看流星图,它是建立在超级快速的 KineticJS 框架: http://meteorcharts.com/之上的

我最近开发了一个接近实时的仪表板(每5秒刷新一次) ,并选择使用用画布渲染的图表。

我们尝试了 Highchart (基于 SVG 的 JavaScript 图表库)和 CanvasJS (基于 Canvas 的 JavaScript 图表库)。虽然 Highchart 是一个很棒的制图 API,并且提供了更多的特性,但是我们还是决定使用 CanvasJS。

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

因此,在15分钟内: 900分(每秒数据点数) x2(线条组合图) x4图表 = 7200分总和。

使用 chrome 分析器,与 CanvasJS 的内存从来没有超过30 MB,而与高图表的内存使用超过600 MB。

同时刷新时间为5秒,CanvasJS 渲染的响应速度比 Highchart 更快。

我们使用一个定时器(setInterval 5秒)发出4个 REST API 调用,从连接到 Elasticsearch 的后端服务器中提取数据。JQuery.post ()接收每个更新为数据的图表。

这就是说,对于离线报告,我会选择高图,因为它的 API 更加灵活。

还有一些 Zing 图表声称使用了 SVG 或者 Canvas,但是并没有查看它们。

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

我还发现,当我们打印带有 SVG 图形的 PDF 页面时,生成的 PDF 仍然包含基于矢量的图像,而如果打印带有 Canvas 图形的页面,生成的 PDF 文件中的图像是光栅化的。