Skip to content

Instantly share code, notes, and snippets.

@ColinEberhardt
Last active May 28, 2019 14:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ColinEberhardt/de9c652b7e820bd7b51d2b966e796ff5 to your computer and use it in GitHub Desktop.
Save ColinEberhardt/de9c652b7e820bd7b51d2b966e796ff5 to your computer and use it in GitHub Desktop.
Canvas Chart Zoom
license: mit

This example demonstrates the rendering of 10,000 datapoints with pan / zoom via d3-zoom. As you manipulate the chart it is being re-rendered by invoking selection.call on the top level component. Rendering the data to Canvas is approximately x10 faster than SVG in this case.

The visual d3fc components support rendering to both Canvas and SVG. In this case the cartesianCanvasChart and seriesCanvasPoint are used to render the chart. You can swap then for SVG simply by changing the to cartesianSvgChart and seriesSvgPoint.

<!DOCTYPE html>
<!-- include polyfills for custom event, Symbol and Custom Elements -->
<script src="//unpkg.com/babel-polyfill@6.26.0/dist/polyfill.js"></script>
<script src="//unpkg.com/custom-event-polyfill@0.3.0/custom-event-polyfill.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/document-register-element/1.8.0/document-register-element.js"></script>
<!-- use babel so that we can use arrow functions and other goodness in this block! -->
<script src="//unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="//unpkg.com/d3@5.5.0"></script>
<script src="//unpkg.com/d3fc@14.0.41"></script>
<style>
body {
font: 16px sans-serif;
}
.chart {
height: 480px;
}
</style>
<div id='zoom-chart' class='chart'></div>
<script type='text/babel'>
// create some test data
var data = d3.range(10000).map((d) => ({
x: Math.random(),
y: Math.random()
}));
var x = d3.scaleLinear();
var y = d3.scaleLinear();
// secondary scales for the purposes of computing the zoom
var x2 = d3.scaleLinear();
var y2 = d3.scaleLinear();
var area = fc.seriesCanvasPoint()
.crossValue(d => d.x)
.mainValue(d => d.y)
.size(4);
// create a d3-zoom that handles the mouse / touch interactions
var zoom = d3.zoom()
.on('zoom', () => {
// update the scale used by the chart to use the udpated domain
x.domain(d3.event.transform.rescaleX(x2).domain());
y.domain(d3.event.transform.rescaleY(y2).domain());
render();
});
// the chart!
var chart = fc.chartCartesian(x, y)
.chartLabel('Canvas Zoom 10,000 Points')
.canvasPlotArea(area)
.decorate((sel) => {
// add the zoom interaction on the enter selection
// NOTE: there is a much better zoom integration being developed
// for d3fc!!!
sel.enter()
.select('.plot-area')
.on('measure.range', () => {
x2.range([0, d3.event.detail.width]);
y2.range([d3.event.detail.height, 0]);
})
.call(zoom);
});
function render() {
d3.select('#zoom-chart')
.datum(data)
.call(chart);
}
render();
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment