An idea for encapsulating the margin convention, inspired by the React render prop pattern.
The goal is to find a pattern that can also encapsulate the notion of small multiples.
forked from curran's block: Margin Convention with Scatter Plot
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://d3js.org/d3.v4.min.js"></script>
<title>Basic Scatter Plot</title>
</head>
<body>
<svg width="960" height="500"></svg>
<script>
d3.margin = (selection, {width, height, margin, children}) => {
let g = selection.selectAll('margin-group').data([null]);
g = g.enter().append('g').attr('class', 'margin-group')
.merge(g)
.attr('transform', `translate(${margin.left}, ${margin.top})`);
children(g, {
innerWidth: width - margin.left - margin.right,
innerHeight: height - margin.top - margin.bottom
})
};
</script>
<script>
const xValue = d => d.sepalLength;
const yValue = d => d.petalLength;
const xScale = d3.scaleLinear();
const yScale = d3.scaleLinear();
const svg = d3.select('svg');
const row = d => {
d.petalLength = +d.petalLength;
d.petalWidth = +d.petalWidth;
d.sepalLength = +d.sepalLength;
d.sepalWidth = +d.sepalWidth;
return d;
};
d3.csv('iris.csv', row, data => {
xScale.domain(d3.extent(data, xValue));
yScale.domain(d3.extent(data, yValue));
d3.margin(svg, {
width: svg.attr('width'),
height: svg.attr('height'),
margin: { left: 20, right: 20, top: 20, bottom: 20 },
children: (g, {innerWidth, innerHeight}) => {
xScale.range([0, innerWidth]);
yScale.range([innerHeight, 0]);
g.selectAll('circle').data(data)
.enter().append('circle')
.attr('cx', d => xScale(xValue(d)))
.attr('cy', d => yScale(yValue(d)))
.attr('r', 8);
}
});
});
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js