2012-12-19 62 views
4

问题: 在以下情况下,canvas比svg更适合吗?对于大量行,HTML5 SVG vs Canvas?

案例: 我画一个图表(使用d3js库)与此类似(但有更多的数据):

http://mbostock.github.com/d3/talk/20111116/iris-parallel.html

它是基于一个SVG和它的几个工作正常数千行(最多5000行),添加更多行(svg路径)会显着降低性能(页面滚动变慢)

请记住:我需要添加鼠标事件(这在svg中很方便)

+2

取决于如何绘制线条:是否可以将更多线条组合到单个路径或多边形元素中,从而减少DOM元素的数量?这可能会提高性能 - 至少值得一试。 –

+0

@ThomasW - +1。我发现这对于提高基于SVG的可视化的性能有很大的帮助。无论如何,您的用户无法理解感知数以万计的线路。 – candu

回答

4

通常svg更适合于矢量图像,就像你的例子。然而,canvas在现代浏览器中具有诸多优点,例如硬件加速,因此只要缩放,平移等,就可以绘制线条。不需要性能会使用canvas

使用canvas鼠标事件可能会非常痛苦,因为您必须手动跟踪所有内容,所以使用canvas时,使用canvas不会很有趣。然而,一旦点被绘制,折衷就是假设你只在页面行为良好时才绘制它们,不管行数是多少,因为它们都被绘制成光栅图像,并且不是DOM的一部分。

老实说尽管找到它的最好方法是测试你目前使用的画布。

+0

1.谢谢你:D,2.鼠标事件与坐标轴不相关,所以在我的情况下,我的坐标轴在100轴以下,3.实现我在Canvas中的操作并不直接,可能需要时间这就是我为什么要问的原因,4.再次感谢:D –

+1

正如我在我的答案中发布的,您可以使用drawImage方法将SVG绘制到画布上,因此您甚至不必重新实现绘图代码。 – Philipp

+0

谢谢,但我怎样才能使用drawImage?你能给我一个片段吗? –

2

当性能成为问题时,切换到画布可能是一个选项。在这种情况下,您可以画一次画布。之后,它几乎就像一个图像。绘图可能需要一些时间,但之后可以快速缩放。请注意,可以使用context.drawImage方法(example)将渲染的SVG绘制到画布上。所以你可以让你的SVG代码在后台创建一个SVG,然后将其绘制到画布上。

但请记住,只要它在画布上,它就不会像SVG一样美丽。当用户放大时,它会变得模糊或像素化,这取决于浏览器如何缩放图形。

画布上的点击事件可以通过两种方式处理。要么保留一组点击目标,并在画布上添加一个onclick事件处理程序。点击发生时,迭代数组并检查哪一个最接近点击坐标。其他选项是使用hit regions。这些必须被定义为多边形路径。

+0

非常感谢,这非常有帮助。我不需要缩放,所以我不害怕变得模糊,唯一会造成痛苦的是鼠标事件(点击和悬停) –

+0

它可能很有可能一起使用canvas和svg,例如将它们堆叠在一起并让svg端处理交互。或者将静态内容绘制到画布中,使用getDataURL获取栅格化结果,然后在元素中使用该结果。 –

+0

@AhmedMoawad我发现将动态生成的SVG绘制到画布上并不像我承诺的那样微不足道。但我设法做到了一些技巧:http://stackoverflow.com/questions/13963259/drawing-a-modified-svg-to-a-canvas/13999263#13999263 – Philipp

1

对上述所有内容+1。在使用canvas和SVG合成图像时,我看到了一些惊人的性能提升。

关于操纵鼠标事件画布上的形象,我想象如你所描述的图像,最好的办法就是将它抽象掉使用库类似如下:

保持你的代码从画布本身的离开,让图书馆做y的思考OU。

+1

画布API是一个非常简单的。如果你不需要一个完整的场景图实现,我建议你和一些[自定义帮助函数](https://github.com/forresto/web-interactive-workshop#processing-not-processing)你写你自己的图书馆。 – forresto

+0

+1如果场景很简单,则在库上使用“本机”API –