Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consider canvas-based scatterplot #811

Closed
gordonwoodhull opened this issue Dec 24, 2014 · 7 comments
Closed

consider canvas-based scatterplot #811

gordonwoodhull opened this issue Dec 24, 2014 · 7 comments
Milestone

Comments

@gordonwoodhull
Copy link
Contributor

The DOM can't handle thousands of elements and usually this is okay because the eye can't perceive them. But one kind of chart where this is actually helpful is the scatterplot, especially if transparency is used.

Not making promises here but wanted to open a ticket to track the idea.

@gordonwoodhull gordonwoodhull added this to the v3.0 milestone Dec 24, 2014
@gordonwoodhull
Copy link
Contributor Author

One guide to d3 and canvas: http://bocoup.com/weblog/d3js-and-canvas/

@jefffriesen
Copy link

I've been thinking about canvas for dc.js for a while now. The problem I have with my implementations of dc.js is that it's slow while filtering. I know there are ways to speed it up, such as reducing the number of dimensions (or records). I've done some of that. But still often while brushing rendering hangs - both the brush and the filtering. Even the demo page is a little jerky (http://dc-js.github.io/dc.js/). I'm guessing what's happening is we are simultaneously:

  • Rendering the brush
  • Rerunning crossfilter with the new bounds
  • Re-rendering all charts
  • Relayout if a table exists on the page (which I've noticed really hurts performance. I suspect using requestAnimationFrame may help with this)

I've thought about trying to figure out a way to do the rerun crossfilter on a web worker. It may work, but then you have the overhead of passing serialized data back and forth. If you only had to pass to the web worker the ranges and pass back the reduced data this may be efficient strategy.

But this awesome article from Flipboard made a big impact and got me thinking more about using canvas for charts: http://engineering.flipboard.com/2015/02/mobile-web/

Here's a key quote:

In contrast to the DOM, most devices today have hardware accelerated canvas implementations which send drawing commands directly to the GPU. This means we could render elements incredibly fast; we’re talking sub-millisecond range in many cases.

Doing this, the main thread could be used for crossfilter and the rendering of the charts offloaded to the GPU. I read articles from a few years ago and they said GPU rendering for canvas was spotty, especially for mobile. But Flipboard is going all in with canvas because of rendering performance on mobile, so support seems like it's better.

Chart.js is doing it in canvas and is really popular, so that's a good reference point both in feasibility and implementation.

Thoughts?

@gordonwoodhull
Copy link
Contributor Author

It wouldn't be that hard to connect these external charts to dc.js using the (undocumented) chart registry. There should be enough to get you started in this SO question:

http://stackoverflow.com/a/25351686/676195

I'd figure out, though, which is really the bottleneck. If the problem is crossfilter, then canvas won't help, obviously.

The particular problem you mention about rendering hanging may just be that we throttle the wrong way, #630.

@jefffriesen
Copy link

I didn't know about the chart registry. That really opens up options.

I read the thread you posted on throttling. Seems like the ideal solution would be to throttle instead of debounce as you suggested, but also give an option to filter on brushend. On brushend would be great for larger datasets or a high number of dimensions, but if that was the default, you would lose some of the magic and intuitiveness of dc.js.

I'm still intrigued by the possibility of rendering all of the charts in canvas to the GPU can do that work, freeing up the main thread for crossfilter. But a lot of unknowns in implementation and performance.

But unfortunately right now I don't have time to contribute to it. But I wanted to bring up the possibility if others are interested.

@nreese
Copy link

nreese commented Jul 20, 2015

I am also greatly in need of a scatter plot rendered with canvas. I started a new project, dc.canvas.js that extends DC with a canvas scatter plot.

@HamsterHuey
Copy link

HamsterHuey commented Jan 28, 2018

I've implemented a cavas-based scatter plot that works as a drop-in replacement for dc.scatterPlot. It is considerably more efficient/responsive when plotting a few thousand points or more. I've submitted a PR for it here: #1361

Demo of it in action here:

For now, if you want to make use of it, the easiest way would be to get it from this repo and use it in your projects:
https://github.com/HamsterHuey/dcjs-canvas-scatterplot

@gordonwoodhull
Copy link
Contributor Author

Fixed by #1361

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants