快速响应的交互式图表/图表:SVG,Canvas,其他?

时间:2012-09-06 23:56:45

标签: html5 canvas svg d3.js kineticjs

我正在尝试选择合适的技术来更新项目,该项目基本上可以在可缩放的可缩放图形中渲染数千个点。使用Protovis的当前实现表现不佳。在这里查看:

http://www.planethunters.org/classify

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

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

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

d3.js,源自Protovis,基于SVG,supposed to be better at rendering animations。但是,我怀疑它有多好,它的性能上限是多少。出于这个原因,我也在考虑使用像KineticJS这样的基于画布的库进行更彻底的改造。然而,在我使用一种或另一种方法走得太远之前,我想听听那些用这么多数据做过类似网络应用并得到他们意见的人。

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

使用SVG的NYTimes制作的应用程序示例,但仍然可以顺利地动画: 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(democode)实现的经验,我也想听听你的意见。它似乎是一个很好的混合体,能够操纵数据并对如何渲染数据进行自定义控制(以及性能),但我想知道是否必须将所有内容加载到DOM中仍然会减慢速度。< / p>

我知道有一些类似于这个问题的现有问题,但它们都没有提出同样的问题。谢谢你的帮助。

后续行动:我最终使用的实施工作是https://github.com/zooniverse/LightCurves

5 个答案:

答案 0 :(得分:181)

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

这些示例使用D3的zoom behavior来实现缩放和平移。除了圈子是用Canvas还是SVG渲染之外,另一个主要区别是你是使用几何还是语义缩放。

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

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

然而,没有灵丹妙药的表现,这四种可能的方法并没有开始涵盖整个可能性空间。例如,你可以结合几何和语义缩放,使用几何用于平移(更新“变换”属性)并且仅在缩放时重绘单个圆的方法。您甚至可以将这些技术中的一种或多种与CSS3变换结合起来以添加一些硬件加速(如hierarchical edge bundling example中所述),尽管这可能很难实现并且可能会引入视觉伪像。

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

正如这些示例所示,您可以将D3与Canvas一起使用,即使D3的某些部分是特定于SVG的。另请参阅此force-directed graph和此collision detection example

答案 1 :(得分:8)

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

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

  • 画一个明星,
  • 添加星标
  • 删除明星

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

如果你继续假设框架速度很快,那么很明显导致性能不足的是大量的星星和处理它们是框架无法为你做的事情,至少我不知道这件事。

我想说的是,问题的根源导致计算几何的基本问题,即:range searching和另一个计算机图形:level of detail

要解决您的性能问题,您需要实现一个良好的预处理器,该预处理器能够非常快速地找到要显示的星星,并且可能能够根据缩放来聚集靠近在一起的星星。保持你的视野生动和快速的唯一方法就是尽可能地保持明星的数量。

正如你所说,最重要的是性能,而不是我倾向于使用canvas,因为它可以在没有DOM操作的情况下工作。它还提供了使用webGL的机会,这大大提高了图形性能。

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

PS:In this Book你可以找到关于网络图形,技术,画布,SVG和DHTML的优缺点的非常详细的讨论。

答案 2 :(得分:7)

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

我们尝试了Highcharts(基于SVG的JavaScript Charting库)和CanvasJS(基于Canvas的JavaScript Charting库)。虽然Highcharts是一个出色的图表API并提供更多功能,但我们决定使用CanvasJS。

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

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

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

同样,刷新时间为5秒CanvasJS渲染比Highcharts更具响应性。

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

对于离线报告说,我会选择Highcharts,因为它的API更灵活。

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

当性能非常关键时,应考虑画布。 SVG的灵活性。并不是画布框架不灵活,但是为了获得与svg框架相同的功能,需要为canvas框架做更多的工作。

答案 3 :(得分:3)

也可以查看Meteor Charts,它建立在超级快速KineticJS框架之上:http://meteorcharts.com/

答案 4 :(得分:0)

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