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

标签 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.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)等,但这种方法很慢。所以我希望有更好的方法来达到同样的效果?

提前致谢!

最佳答案

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

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

鉴于这个新问题,看一下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 辅助函数以使其正常工作。

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

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

你可以在这里看到源:

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

这会很好地支持 native ,包括相反的情况缩放 -> 过滤器,这确实需要更改 dc.js 内部。我添加了一个问题来跟踪这个想法:https://github.com/dc-js/dc.js/issues/820

关于Dc.js 将范围图表应用于多个图表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27445259/

相关文章:

javascript - dc.js 响应式 geojson 美国 map

javascript - Crossfilter 是否需要平面数据结构?

javascript - 如何在jsfiddle中读取csv文件

javascript - DC.js X 轴小时标签显示为千分之一

javascript - 如何在 D3 中使用交叉过滤器进行过滤

javascript - d3/dc.js - 如何创建堆叠条形图,同时告诉 crossfilter 将数组中的元素视为单独的记录?

javascript - 使用 DC.JS/Crossfilter 进行部分求和

javascript - 我们如何使用 dc.js 和传单 map 通过 map 悬停来过滤图表

javascript - 获取交叉过滤器中的所有过滤值

d3.js - dc.js pieChart 设置特定的 x 轴值