2017-05-04 35 views
0

我有一个包含三个D3 JS v3图和一些表格数据的报告页面。该页面看起来很大,而窗口最大化,但是当用户改变浏览器窗口,它开始行为古怪,即每个小区溢出含divD3&Angular:调整窗口大小的多个图块的最佳方式是什么?

经过一些研究,我发现,我只是需要设置viewBox根SVG每个地块的属性,即

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控制器内做的,是没有问题的。不过,每次调整窗口大小时,我还需要更新全部三个图。有一个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

使用不随窗口si更改的viewBox泽。 –

回答

0

最后我做到了即注射如下将窗口组件插入到我的控制器中并定义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"); 
     }; 
    } 
} 
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"... 
+0

不幸的是,我没有包装d3代码的指令。我不能使用自动化工具来获取依赖关系等,而且很难手工匹配所有依赖关系的版本,所以我在打字稿中使用d3代码,并使用forward声明风格'declare var d3:any;' –