|
<!DOCTYPE html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<meta name="viewport" content="width=device-width"> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<style> |
|
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } |
|
.div1, .div2 { position: absolute; margin-top: 20px; } |
|
.div2 { top: 50vh; } |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<div class='outer'> |
|
<div class="div1"></div> |
|
<div class="div2"></div> |
|
</div> |
|
<script> |
|
function ResponsiveComponent1(container,props) { |
|
const { width, height } = props; |
|
// trick: use the general update pattern |
|
// create a single element |
|
// need to assign it to new variable to make it be the merged enter-update selection (use let because 'svg' is reassigned in next line) |
|
let svg = container.selectAll('svg').data([null]) |
|
svg = svg.enter().append('svg') // will only append an svg element on first invocation of function |
|
.merge(svg) // update selection |
|
.attr('width', width) |
|
.attr('height', height); |
|
|
|
const rect = svg.selectAll('rect').data([null]); |
|
rect |
|
.enter().append('rect') |
|
.attr('rx', 100) // round rect corners to better check responsive accuracy. set 'rx' attribute before merge because it is constant and does not depend on props |
|
.merge(rect) |
|
.attr('width', width) |
|
.attr('height', height); |
|
} |
|
|
|
function ResponsiveComponent2(svg, rect, props) { |
|
const { width, height } = props; |
|
svg.attr('width', width) |
|
.attr('height', height); |
|
|
|
rect.attr('rx', 100) |
|
.attr('width', width) |
|
.attr('height', height); |
|
} |
|
|
|
function renderMethod1() { |
|
const body = d3.select('.div1'); |
|
ResponsiveComponent1(body, { |
|
width: document.body.clientWidth, |
|
height: document.body.clientHeight*0.4 |
|
}); |
|
} |
|
|
|
// create rect element once before function invocation |
|
const svg2 = d3.select('.div2').append('svg') |
|
const rect2 = svg2.append('rect') |
|
function renderMethod2() { |
|
ResponsiveComponent2(svg2, rect2, { |
|
width: document.body.clientWidth, |
|
height: document.body.clientHeight*0.4 |
|
}) |
|
} |
|
|
|
renderMethod1(); |
|
renderMethod2(); |
|
window.addEventListener('resize', renderMethod1); |
|
window.addEventListener('resize', renderMethod2); |
|
</script> |
|
</body> |