我有一个包含三个D3 JS v3图和一些表格数据的报告页面。当窗口最大化时页面看起来很棒,但是当用户调整浏览器窗口大小时,它开始表现得很奇怪,即每个绘图溢出包含div
等。
经过一番研究后,我发现我只需要为每个情节设置根svg的viewBox
属性,即
var margin = {top: 40, right: 20, bottom: 20, left: 20},
width = 450 - margin.left - margin.right,
height = 370 - margin.top - margin.bottom;
var chartSvg = d3.select("#myPlotDivId")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom))
.attr("preserveAspectRatio", "xMidYMid meet")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
这可以在特定的AngularJS控制器中完成,没问题。但是,每次调整窗口大小时,我还需要更新所有三个绘图svg
。有nice JSFiddle demonstrating this:
var aspect = chartSvg.width() / chartSvg.height(),
container = chartSvg.parent();
$(window).on("resize", function() {
var targetWidth = container.width();
chartSvg.attr("width", targetWidth);
chartSvg.attr("height", Math.round(targetWidth / aspect));
}).trigger("resize");
但是,我更喜欢在控制器和我创建图表的功能中执行此操作...我该怎么做?我不希望在调用我的控制器的页面中挂起一个Window事件,或者为此创建一个全局指令。有什么想法吗?
答案 0 :(得分:2)
首先,我希望你有一些角度组件/指令包装d3代码,如果没有 - 这是你应该做的。 然后这个组件应该接受宽度和高度:
app.component('myd3Plot', ...
width: '<',
height: '<'
在父控制器/组件中,您可以监听窗口大小并调整子图大小:
window.on('resize', function() {
vm.child1.height = ...
vm.child2.height = ...
})
<myd3-plot height="$ctrl.child1.height"...
<myd3-plot height="$ctrl.child2.height"...
答案 1 :(得分:1)
最后我按如下方式做了,即将窗口组件注入我的控制器并定义onresize
事件处理程序:
class ReportCtrl {
// 1) inject the window into my controller
constructor(private $window: IWindowService, ...) {
// etc ...
// 2) reusable function to resize a d3 js plot
var resizePlot = function (divId: string) {
var container = d3.select(divId);
var svg = container.select("svg");
var aspect = svg.attr("width") / svg.attr("height");
var targetWidth = container.node().getBoundingClientRect().width;
svg.attr("width", targetWidth);
svg.attr("height", Math.round(targetWidth / aspect));
};
// 3) hook on the window onresize event
$window.onresize = function (ev: UIEvent) {
resizePlot("#hist");
resizePlot("#scatter1");
resizePlot("#scatter2");
};
}
}