Skip to content

Instantly share code, notes, and snippets.

@curran
Last active June 13, 2016 15:44
Show Gist options
  • Save curran/974c9def890f8ac0172611921fb51b8a to your computer and use it in GitHub Desktop.
Save curran/974c9def890f8ac0172611921fb51b8a to your computer and use it in GitHub Desktop.
Responding to Resize with ReactiveModel
license: mit


The data flow graph for this example (made with graph-diagrams).

This example shows how to make a dynamic graphic using D3 4.0 and ReactiveModel that fills its containing element and responds to resize. This is useful when, for example, you want to be able to load your visualization "full screen" and give users the ability to size the window however they want to. It's also useful when you want to use CSS to define the size of a visualization container, then have the visualization automatically fit inside it.

To experience the resize behavior, run this example full-screen and resize the browser.

Part of a series of examples demonstrating ReactiveModel.

Notes:

  • This is using an alpha version of D3 4.0. The main difference in this example from D3 3.5 is the use of selection.merge, which merges enter with update.
  • The call to addProperties instantiates instances of reactive-property with the given defaults. These behave similarly to the getter-setter functions described in Towards Reusable Charts.
  • The function that takes (svg, width, height) as input becomes a reactive-function. This will be invoked once all inputs are defined, and when any inputs change. It is invoked at most once every animation frame, so there are no unnecessary DOM updates. In other words, even if there are many resize events fired per animation frame, the DOM will only be updated with the most recent width and height values each frame (at most 60 times per second, synchronized with the display).

forked from curran's block: Responding to Resize

Built with blockbuilder.org

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ReactiveModel Resize</title>
<script src="//d3js.org/d3.v4.0.0-alpha.49.min.js"></script>
<script src="//datavis-tech.github.io/reactive-model/reactive-model-v0.11.0.min.js"></script>
<style>
/* Make the chart container fill the page using CSS. */
#chart-container {
position: fixed;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
}
</style>
</head>
<body>
<!-- The SVG graphics will be injected into this div. -->
<div id="chart-container"></div>
<script>
// The constructor for a "dummy visualization" component.
// Renders a big X on the screen that responds to resize.
function DummyVis(){
return ReactiveModel()
("width", 100)
("height", 100)
("svg")
(function (svg, width, height){
svg
.attr("width", width)
.attr("height", height);
var lines = svg.selectAll("line").data([
{x1: 0, y1: 0, x2: width, y2: height},
{x1: 0, y1: height, x2: width, y2: 0}
]);
lines.enter().append("line")
.style("stroke-width", 50)
.style("stroke-opacity", 0.4)
.style("stroke", "black")
.merge(lines)
.attr("x1", function (d) { return d.x1; })
.attr("y1", function (d) { return d.y1; })
.attr("x2", function (d) { return d.x2; })
.attr("y2", function (d) { return d.y2; });
}, "svg, width, height");
}
// The main program that uses the DummyVis component.
function main(){
var container = d3.select("#chart-container"),
dummyVis = DummyVis()
.svg(container.append("svg"));
function resize(){
dummyVis
.width(container.node().clientWidth)
.height(container.node().clientHeight);
}
resize();
window.addEventListener("resize", resize);
}
main();
// Output the data flow graph as JSON for visualization.
console.log(JSON.stringify(ReactiveModel.serializeGraph(), null, 2));
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment