Can D3 SVG Scene and Canvas be layered together?

2,650 views
Skip to first unread message

Stardrive

unread,
Mar 23, 2012, 7:54:40 PM3/23/12
to d3-js
I'm hoping that a svg scene and a canvas can be layered together? I'm
looking into this just recently having come from Java. I first
discovered d3, which I think is the best thing since sliced bread.
Now, I'm also discovering some decent canvas based frameworks and I'm
wondering if anyone here has experience putting d3 together with a
canvas?

The canvas framework I like is here : http://www.kineticjs.com/how-it-works.php

What would be really great is if a canvas and the d3 svg scenegraph
could be combined. I'm not sure how this would work best? One example
of a canvas and svg working together as layers is here :
http://svg-wow.org/blog/2010/09/06/graffitis

In the end my app has a music score model of data which d3 is perfect
for converting it into all types of visualizations. One of the
visualizations is music notation. What is needed is an efficient
solution where some things like staff lines (that do not need to be re-
rendered to often) can be rendered to a background canvas while other
things are rendered to foreground layers and can be hit via svg. So
both immediate and retained forms of rendering are required for the
best possible solution.

Is there any best advice on how to combine a canvas and d3 into one
powerhouse surface?

If this ends up being super simple please enlighten me as I am still
very new to HTML5 and its related technology layers, thanks.

Kai Chang

unread,
Mar 23, 2012, 8:17:13 PM3/23/12
to d3...@googlegroups.com
It is quite simple. Just layer them on top of one another!

You can use d3 utilities just for data transformation. Here's an
example that uses d3.layout.stack() and renders with Underscore.js:

exposedata.com/canvas/stacked.html

Perhaps someone will create a chart class which renders to canvas.

http://bost.ocks.org/mike/chart/

rektide

unread,
Mar 24, 2012, 11:36:37 AM3/24/12
to d3...@googlegroups.com
You can put a canvas into svg via foreginObject. No idea w/r/t svg in a canvas.

Stardrive

unread,
Mar 25, 2012, 1:17:05 AM3/25/12
to d3-js
Thanks, this and the suggestion by rektide below are both good for
some scenarios.

Having a performant rendering surface that is also configurable via a
layered approach would be optimal for d3. Having looked high and low
through the HTML5 landscape recently and searched out many discussions
on HTML5 performance in hybrid apps and the differences between svg
and canvas rendering it seems that this is a very important
consideration. Here is one comparison of performance I saw:

http://smus.com/canvas-vs-svg-performance

What is required by my app is a rendering surface that is layered. It
should be possible to configure a composite surface with any number
and order of both canvas and svg stacked elements. In such an ideal
solution d3 would render some data and then also convert it to canvas
ops targeted at a specific layer in the composite surface. Then d3
would also render other data into svg only and target that at another
layer that has its own DOM. In my scenario the noteheads (not the
stems, etc) would be ideal candidates for a DOM layer where they can
also be hitable.

I've seen one sample of a canvas layer and svg layer working together
by Vincent Hardy (author of GLF) here:

http://svg-wow.org/blog/2010/09/06/graffitis/

One of the better canvas layer solutions I've seen is here:

http://www.kineticjs.com/how-it-works.php

Maybe the three.js framework could be used to augment d3 and form a
composite layer surface solution for d3?

There are other svg2canvas options but they are all silos so I'm not
sure how useful they are. Still there may be some ideas worth looking
at. Here are some of those available options:

http://www.professorcloud.com/svg-to-canvas/
http://code.google.com/p/canvg/
http://jsfiddle.net/q8cqT/

These are converters which is a part of the solution. The bigger more
robust thing to achieve would be a layer framework extension module
for d3 where any composite surface can be configured/composed out of
canvas and svg elements. The layers could share common layout and size
attributes by virtue of being in the same composite. Then d3 would
auto convert its rendered svg to canvas ops if given data was being
targeted as one of the optional canvas layers.

What are your thoughts? Would a composite surface be a possibility for
d3?

Mike Bostock

unread,
Mar 25, 2012, 11:16:05 AM3/25/12
to d3...@googlegroups.com
> Then d3 would auto convert its rendered svg to canvas ops if given
> data was being targeted as one of the optional canvas layers.

D3 would never work this way; it doesn't abstract the rendering layer.
When you say append("element"), you are creating an element and adding
that to the DOM. That's it. It goes against the design to have an
operation that purports to create or modify DOM elements implicitly do
something else, like render to canvas. If you want that, you could try
a shim (see also [1]), but that's no guaranteed performance
improvement.

Since D3 does not hide the underlying representation, you are free to
do whatever you like, mixing and matching elements and rendering
systems. I frequently combine SVG, HTML and Canvas depending on what
I'm trying to visualize. Canvas is great if you need to render
hundreds of thousands elements, and you're willing to sacrifice the
data-join and transition abstractions. But in that case, you're
dropping down a layer of abstraction and making canvas calls (perhaps
in conjunction with scales and layouts, and in the future path
generators).

Mike

[1] http://bl.ocks.org/1276463

james northrup

unread,
Mar 25, 2012, 11:44:39 AM3/25/12
to d3...@googlegroups.com

Stardrive

unread,
Mar 25, 2012, 1:22:40 PM3/25/12
to d3-js
Thanks for this information.

If D3 will always put all elements into the DOM, then are they also
displayed right away? Or am I to understand that the elements can
then
yet be displayed as SVG or on a Canvas?

I do not understand the following:

> Since D3 does not hide the underlying representation, you are free to
> do whatever you like, mixing and matching elements and rendering
> systems.

Is the representation the DOM that D3 creates?

I frequently combine SVG, HTML and Canvas depending on what
> I'm trying to visualize.

What I would find most helpful is if I could understand how much of
D3 is used in a scenario where you use SVG, HTML and Canvas together.
In the flow of using model data and processing it with D3 where is
it then taken and re-directed to a Canvas? Is there a example of this
flow I can learn from?

In my scenario I have data flowing into D3 and some of this data will
be rendered as retained SVG and other data will be rendered to an
immediate Canvas. The type of data to render to the Canvas is indeed
thousands of smaill decorative items that do not need to have a SVG
element. SVG elements would be used for pickable items like noteheads
only not decorative items like stems, accidentals, flags, etc.

> Canvas is great if you need to render
> hundreds of thousands elements, and you're willing to sacrifice the
> data-join and transition abstractions. But in that case, you're
> dropping down a layer of abstraction and making canvas calls (perhaps
> in conjunction with scales and layouts, and in the future path
> generators).

It is good to know that what I am seeking is reasonable. It would be
better if there was a sample of how this works too. D3 is central to
my use of HTML5 technology, now I'm just hoping to learn how to use
it in a optimal way for the retained and immediate mode requirements
of the data I'm hoping to render.

Stephen Bannasch

unread,
Mar 26, 2012, 2:20:23 AM3/26/12
to d3...@googlegroups.com
I'm using D3 to render into a canvas overlay while I am plotting real-time data.

https://github.com/stepheneb/avalanche2d-js/blob/master/src/grapher.js

The performance is much faster than using SVG.

This is the specific commit where I switched to using a canvas overlay and when graphing 5000 points it sped up the graphing by
a factor of 4:

https://github.com/stepheneb/avalanche2d-js/commit/2f8ed4b52cba

You can run the demo here:

http://stepheneb.github.com/avalanche2d-js/avalanche2d.html

Stardrive

unread,
Mar 26, 2012, 2:37:46 PM3/26/12
to d3-js
Thanks Stephan, this is very helpful. The speed increase is
significant!

I will look at this in detail. From a quick look I understand that the
D3 flow is being intercepted and directed to a Canvas, which sits on
top of the SVG graph. The questions I have next is how much is D3
still doing in this layered scenario?

It would be nice to have an official D3 module that encapsulates this,
so that specific model data could be routed to a foreground SVG layer
and other model data coming through could be routed to a background
Canvas layer for rendering. How possible is it to do something like
the following layered approach?

http://svg-wow.org/blog/2010/09/06/graffitis/



On Mar 26, 1:20 am, Stephen Bannasch <stephen.banna...@deanbrook.org>
wrote:

Stephen Bannasch

unread,
Mar 26, 2012, 3:18:47 PM3/26/12
to d3...@googlegroups.com
At 11:37 AM -0700 3/26/12, Stardrive wrote:
>Thanks Stephan, this is very helpful. The speed increase is
>significant!
>
>I will look at this in detail.

One caveat -- the code is somewhat messy and written very quickly before I understood more about D3. So use it as inspiration, but don't necessarily follow the exact patterns.

I am re-writing it now for another project so it can graph data from multiple streams at the same time and plan to fix the UI issues. I also need to make the whole grapher performant with 50,000 or more data points. The Canvas graphing is definitely fast enough but I need to more intelligently prune the amount of data rendered into SVG Path objects becasue they slow down a great deal when rendering a Path with large numbers of points.

>From a quick look I understand that the
>D3 flow is being intercepted and directed to a Canvas, which sits on
>top of the SVG graph. The questions I have next is how much is D3
>still doing in this layered scenario?

Checkout the demo and repository and play with it.

For example the graph has the axis re-scaling UI I implemented here:

http://bl.ocks.org/1920939

If you are quick start the model running and then mousedown on a numeric label on the Y-axis and drag down while the model is running. The axis will re-scale (but you'll see some display bugs). You can slow the whole thing down by increasing the size ofthe "Desk Array" from 100x100 to 200x200. The UI for axis re-scaling is all D3.

I am using the same D3 scale objects for converting from data to screen coordinates.

Zooming and panning are NOT yet working while the real-time data are being plotted -- but this could be fixed by letting eventspass through the canvas to the underlying D3 SVG document.

When the plotting of real-time data is done the canvas is dropped under the SVG and the what you see is the D3 managed SVG document.

Reply all
Reply to author
Forward
0 new messages