Dc.js将范围图应用于多个图形

Dc.js将范围图应用于多个图形,dc.js,crossfilter,Dc.js,Crossfilter,过去几周我一直在使用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

过去几周我一直在使用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(PriorityToChart)
,priority2Chart有
。rangeChart(priority1Chart)
等,但这种方法非常慢。所以我希望有更好的方法来达到同样的效果


提前谢谢

提问的另一种方式是,“如何将多个焦点图表附加到单个范围图表?”

(至少,如果您只关心范围图的刷取,请缩放焦点图,而不是相反。)

考虑到这个新问题,请看一下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;
};
我们还需要将RangeSqual helper函数从coordinateGridMixin中复制出来,以使其正常工作

我创建了一个示例并将其添加到dc.js示例中:

您可以在此处看到源代码:


这将很好地支持本机,包括相反的案例zoom->filter,这确实需要更改dc.js内部结构。我添加了一个问题来跟踪这个想法:

范围图在焦点图的.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).[...];

这是一个有趣的解决方案。不像下面我的解决方案那样安全,但在大多数情况下都应该有效。