2014-12-12 5 views
4

지난 몇 주 동안 dc.js에서 작업했지만 한 가지 문제가 있습니다. 알아낼 수없는 것 같습니다.Dc.js 차트를 여러 그래프에 적용

브러시 필터가있는 단일 차트를 기반으로 네 가지 차트의 비율을 변경할 수 있기를 원합니다. 의 라인을 따라 뭔가 :

priorityTotChart 
    .width(2*w/3).height(h/3) 
    .margins({top: 10, right: 50, bottom: 20, left: 40}) 
    .dimension(dateDim) 
    .group(priorityTotal) 
    .centerBar(true) 
    .gap(1) 
    .x(d3.time.scale().domain([minDate,maxDate])) 
    .elasticY(true) 
    .brushOn(true); 

var translate = 3; 

priority1Chart.width(w/3) 
    .height(h/6) 
    .transitionDuration(300) 
    .margins({top: 10, right: 50, bottom: 25, left: 40}) 
    .dimension(dateDim) 
    .group(priority1) 
    .mouseZoomable(false) 
    .x(d3.time.scale().domain([minDate,maxDate])) 
    .xUnits(d3.time.months) 
    .elasticY(true) 
    .brushOn(false) 
    .ordinalColors(["red"]) 
    .rangeChart(priorityTotChart) 
    .yAxisLabel("Hits per day") 
    .renderArea(true) 
    .renderlet(function (chart) { 
    chart.selectAll("g._1").attr("transform", "translate(" + translate + ", 0)"); 
}); 

priority2Chart.width(w/3) 
    .height(h/6) 
    .transitionDuration(300) 
    .margins({top: 10, right: 50, bottom: 25, left: 40}) 
    .dimension(dateDim) 
    .group(priority2) 
    .mouseZoomable(false) 
    .x(d3.time.scale().domain([minDate,maxDate])) 
    .xUnits(d3.time.months) 
    .elasticY(true) 
    .brushOn(false) 
    .ordinalColors(["orange"]) 
    .rangeChart(priorityTotChart) 
    .yAxisLabel("Hits per day") 
    .renderArea(true) 
    .renderlet(function (chart) { 
    chart.selectAll("g._1").attr("transform", "translate(" + translate + ", 0)"); 
}); 

priority3Chart.width(w/3) 
    .height(h/6) 
    .transitionDuration(300) 
    .margins({top: 10, right: 50, bottom: 25, left: 40}) 
    .dimension(dateDim) 
    .group(priority3) 
    .mouseZoomable(false) 
    .x(d3.time.scale().domain([minDate,maxDate])) 
    .xUnits(d3.time.months) 
    .elasticY(true) 
    .brushOn(false) 
    .ordinalColors(["blue"]) 
    .rangeChart(priorityTotChart) 
    .yAxisLabel("Hits per day") 
    .renderArea(true) 
    .renderlet(function (chart) { 
    chart.selectAll("g._1").attr("transform", "translate(" + translate + ", 0)"); 
}); 

priority4Chart.width(w/3) 
    .height(h/6) 
    .transitionDuration(300) 
    .margins({top: 10, right: 50, bottom: 25, left: 40}) 
    .dimension(dateDim) 
    .group(priority4) 
    .mouseZoomable(false) 
    .x(d3.time.scale().domain([minDate,maxDate])) 
    .xUnits(d3.time.months) 
    .elasticY(true) 
    .brushOn(false) 
    .ordinalColors(["green"]) 
    .rangeChart(priorityTotChart) 
    .yAxisLabel("Hits per day") 
    .renderArea(true) 
    .renderlet(function (chart) { 
    chart.selectAll("g._1").attr("transform", "translate(" + translate + ", 0)"); 
}); 

그러나이 방법으로 만 .rangeChart(priorityTotChart)이 업데이트됩니다 사용 마지막 차트를 작동하지 않습니다.

각 그래프를 이전 그래프의 범위 (예 : priority1Chart가 .rangeChart(priorityTotChart)이고 priority2Chart가 .rangeChart(priority1Chart) 등)에 따라 다르게 설정하여이 문제를 해결할 수 있지만이 방법은 매우 느립니다. 그래서 같은 효과를 얻는 더 좋은 방법이 있기를 바랬습니다.

미리 감사드립니다.

답변

4

질문하는 또 다른 방법은 "하나의 범위 차트에 여러 개의 포커스 차트를 첨부 할 수 있습니까?"입니다.

(적어도, 당신은 단지 주위에 초점 차트를 확대 아닌 다른 방법으로 범위 차트를 닦고 걱정합니다.)

이 새로운 질문을 감안할 때, coordinateGridMixin.focusChart의 구현을 살펴 :

_chart.focusChart = function (c) { 
    if (!arguments.length) { 
     return _focusChart; 
    } 
    _focusChart = c; 
    _chart.on('filtered', function (chart) { 
     if (!chart.filter()) { 
      dc.events.trigger(function() { 
       _focusChart.x().domain(_focusChart.xOriginalDomain()); 
      }); 
     } else if (!rangesEqual(chart.filter(), _focusChart.filter())) { 
      dc.events.trigger(function() { 
       _focusChart.focus(chart.filter()); 
      }); 
     } 
    }); 
    return _chart; 
}; 

우리가해야 할 일은 다중 포커스 차트를 사용하는 새로운 버전의 기능을 만드는 것입니다. 이 함수는 내부 데이터에 액세스하지 않기 때문에, 우리는 "원숭이 패치는"어떤 기능을 추가 할 그리드 차트를 조정할 수 있습니다 :

chart1.focusCharts = function (chartlist) { 
    if (!arguments.length) { 
     return this._focusCharts; 
    } 
    this._focusCharts = chartlist; // only needed to support the getter above 
    this.on('filtered', function (range_chart) { 
     if (!range_chart.filter()) { 
      dc.events.trigger(function() { 
       chartlist.forEach(function(focus_chart) { 
        focus_chart.x().domain(focus_chart.xOriginalDomain()); 
       }); 
      }); 
     } else chartlist.forEach(function(focus_chart) { 
      if (!rangesEqual(range_chart.filter(), focus_chart.filter())) { 
       dc.events.trigger(function() { 
        focus_chart.focus(range_chart.filter()); 
       }); 
      } 
     }); 
    }); 
    return this; 
}; 
우리는이를 얻기 위해 coordinateGridMixin 밖으로 rangesEqual 도우미 함수를 복사해야

일.

https://github.com/dc-js/dc.js/blob/master/web/examples/multi-focus.html

이것은 기본적으로 지원하는 것이 좋을 것이다 : 당신은 여기에 소스를 볼 수 있습니다

http://dc-js.github.io/dc.js/examples/multi-focus.html

:

나는 예를 생성하고 dc.js를 예제에 추가 반대의 경우에는 줌 -> 필터를 포함하여 dc.js 내부를 변경해야합니다. 나는이 아이디어를 추적하기 위해 이슈를 추가했다 : https://github.com/dc-js/dc.js/issues/820

2

범위 차트는 포커스 차트의 .x() - 스케일에서 작동한다.

하나의 눈금을 전역으로 정의하고이를 범위 차트로 제어해야하는 모든 차트에 사용하는 것입니다. 포커스 차트 중 하나만 .rangeChart() 속성을 설정해야합니다.

이것은 정의되지 않은 동작입니다. 이것은 향후 변경 될 수 있음을 의미합니다.

의사 코드 :

var xScale = d3.scale.linear(); 
var xScaleRange = d3.scale.linear(); 

var rangeChart = dc.lineChart('#R').x(xScaleRange).[...]; 

var focusChartA = dc.barChart('#A').x(xScale).rangeChart(rangeChart).[...]; 
var focusChartB = dc.barChart('#B').x(xScale).[...]; 
+0

이 흥미로운 솔루션입니다. 아래의 내 솔루션만큼 안전하지는 않지만 대부분의 경우 작동합니다. – Gordon