2017-05-04 36 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;' –