|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>Margin Convention II with ReactiveModel</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> |
|
|
|
// Resizes the SVG container. |
|
function ReactiveSVG(my){ |
|
my("svg") |
|
("width", 100) |
|
("height", 100) |
|
|
|
("svg-width", function (svg, width){ |
|
svg.attr("width", width); |
|
}, "svg, width") |
|
|
|
("svg-height", function (svg, height){ |
|
svg.attr("height", height); |
|
}, "svg, height"); |
|
} |
|
|
|
// Encapsulates the margin convention. |
|
function ReactiveMargin(my){ |
|
|
|
my("marginTop", 50) |
|
("marginBottom", 50) |
|
("marginLeft", 50) |
|
("marginRight", 50) |
|
|
|
("innerWidth", function (width, marginLeft, marginRight){ |
|
return width - marginLeft - marginRight; |
|
}, "width, marginLeft, marginRight") |
|
|
|
("innerHeight", function (height, marginTop, marginBottom){ |
|
return height - marginTop - marginBottom; |
|
}, "height, marginTop, marginBottom") |
|
|
|
("g", function (svg){ |
|
return svg.append("g"); |
|
}, "svg") |
|
|
|
("g-transform", function (g, marginLeft, marginTop){ |
|
g.attr("transform", "translate(" + marginLeft + "," + marginTop + ")"); |
|
}, "g, marginLeft, marginTop"); |
|
|
|
} |
|
|
|
// Adds a gray rectangle inside the margin. |
|
function GrayRectangle(my){ |
|
|
|
my("rect", function (g){ |
|
return g.append("rect") |
|
.attr("fill", "lightgray") |
|
.attr("stroke", "gray"); |
|
}, "g") |
|
|
|
("rect-width", function (rect, innerWidth){ |
|
rect.attr("width", innerWidth); |
|
}, "rect, innerWidth") |
|
|
|
("rect-height", function (rect, innerHeight){ |
|
rect.attr("height", innerHeight); |
|
}, "rect, innerHeight"); |
|
} |
|
|
|
// The constructor for a "margin visualization" component. |
|
// Renders a gray rectangle to show the configured margin. |
|
function MarginVis(){ |
|
return ReactiveModel() |
|
.call(ReactiveSVG) |
|
.call(ReactiveMargin) |
|
.call(GrayRectangle); |
|
} |
|
|
|
// Respond to resize by setting width and height from DOM element. |
|
function Resize(my, el){ |
|
function resize(){ |
|
my.width(el.clientWidth) |
|
.height(el.clientHeight); |
|
} |
|
resize(); |
|
window.addEventListener("resize", resize); |
|
} |
|
|
|
// The main program that uses the MarginVis component. |
|
function main(){ |
|
|
|
// Set up the MarginVis instance. |
|
var container = d3.select("#chart-container"), |
|
marginVis = MarginVis() |
|
.svg(container.append("svg")) |
|
.call(Resize, container.node()); |
|
|
|
// Change the margins around in a funky way. |
|
d3.timer(function updateMargin(time){ |
|
time /= 2000; |
|
marginVis |
|
.marginLeft( (Math.sin(time ) + 1.2) * 100) |
|
.marginRight( (Math.sin(time * 2 ) + 1.2) * 100) |
|
.marginTop( (Math.sin(time * 3 ) + 1.5) * 50) |
|
.marginBottom((Math.sin(time * 4 ) + 1.5) * 50); |
|
}); |
|
} |
|
main(); |
|
</script> |
|
</body> |
|
</html> |