D3.js dc.js是否删除饼图中的单击切片而不是灰显?

D3.js dc.js是否删除饼图中的单击切片而不是灰显?,d3.js,dc.js,D3.js,Dc.js,我想从饼图中删除选定的切片,而不是灰显。例如,“损益天数”或“季度”饼图,如果我单击该切片(如第4季度),我想从显示中删除该条目(包括切片+图例,如果我想恢复,我可以使用控件将其重置) 如何实现这种行为 我在单击处理程序中尝试了以下操作: let filter = chart.keyAccessor()(d); if (d3.event['shiftKey']) { if ('Others' === filter) {

我想从饼图中删除选定的切片,而不是灰显。例如,“损益天数”或“季度”饼图,如果我单击该切片(如第4季度),我想从显示中删除该条目(包括切片+图例,如果我想恢复,我可以使用控件将其重置)

如何实现这种行为

我在单击处理程序中尝试了以下操作:

let filter = chart.keyAccessor()(d);
            if (d3.event['shiftKey']) {
                if ('Others' === filter) {
                    chart['_invokeFilteredListener'](Array.isArray(filter)? filter : [filter], 'error');
                } else {
                    chart['__inclusive'] = true;
                    chart['replaceFilter'](filter);
                    //if (multivalued) {
                    dc.redrawAll(); //why renderAll()?
                    //}
                }
            } else {
                dc.events.trigger(() => {
                    chart.filter(filter);
                    dc.redrawAll();
                });
            }
过滤器手柄

.filterHandler((dim: Crossfilter2.Dimension<any, any>, filters: string[]) => {
                dim.filter(null);
                const data = this._chart.data();
                const filterObject = {};
                for (let f of filters) {
                    if ('Others' === f) {
                        let others: any[] = data[data.length - 1].others;
                        if (Array.isArray(others)) {
                            for (let o of others) {
                                filterObject[o] = true;
                            }
                        } else {
                            dim.group().all().forEach(g => {
                                let p = filters.indexOf(g.key);
                                if (p < 0) {
                                    filterObject[g.key] = p;
                                }
                            });
                        }
                    } else {
                        filterObject[f] = true;
                    }
                }
                dim.filterFunction(d => {
                    return filterObject[Array.isArray(d)? d[0] : d] !== void 0;
                });
                return filters;
            });
.filterHandler((尺寸:Crossfilter2.Dimension,过滤器:string[])=>{
dim.filter(空);
const data=这个。_chart.data();
常量filterObject={};
对于(让f为过滤器){
如果('Others'==f){
让其他人:any[]=data[data.length-1]。其他人;
if(Array.isArray(其他)){
为了(让其他人去吧){
filterObject[o]=真;
}
}否则{
dim.group().all().forEach(g=>{
设p=filters.indexOf(g.key);
if(p<0){
过滤器对象[g.key]=p;
}
});
}
}否则{
filterObject[f]=真;
}
}
dim.filterFunction(d=>{
返回filterObject[Array.isArray(d)→d[0]:d]!==void 0;
});
回流过滤器;
});

可能有很多方法可以做到这一点,但我想到的第一件事是,“听起来像一个”的行为就像一个普通的群体,但它确实观察到自己维度的过滤器:

function filter_self_group(chart, group) {
    return {
        all: function() {
            var filters = chart.filters();
            return group.all().filter(kv => !filters.includes(kv.key));
        }
    };
}
yearRingChart
    .group(filter_self_group(yearRingChart, spendPerYear))
只需从图表中抓取过滤器,并确保排除这些垃圾箱。这不涉及其他人,但这很简单,可以添加

接下来,我们要过滤掉值,而不是像dc.js通常那样过滤进去。我们可以通过修改默认的过滤器处理程序来实现这一点。我认为这与您上面所做的类似,但更简单:

function negate_filters(dimension, filters) {
    if (filters.length === 0)
        dimension.filter(null);
    else
        dimension.filterFunction(function(d) {
            return !filters.includes(d);
        })
    return filters;
}
此外,我认为如果在过滤掉最后一个片段时,重置过滤器,那将是一件好事:

function all_is_nothing(N, filterHandler) {
    return function(dimension, filters) {
        console.log(filters.length, N)
        if(filters.length === N)
            filters = [];
        return filterHandler(dimension, filters);
    }
}
把这些联系在一起:

yearRingChart
    .filterHandler(all_is_nothing(spendPerYear.all().length, negate_filters));
最后,“取消选择的灰色”对我们没有用处,我也不知道如何禁用CSS规则的效果,所以让我们在绘制图表之后,但在显示之前,从切片中删除该类:

yearRingChart.on('pretransition', function(chart) {
    chart.selectAll('g.deselected').classed('deselected', false);
});
我相信还有很多其他方法可以做到这一点,也许还有更干净的方法。这就是我想到的。我很乐意为其他人提供支持,但我想先介绍一下基本想法


是否要在删除饼图切片时将其过滤掉,以便其他图表也不会显示该数据?在我看来,更简单的方法可能是使用与图表组定义的维度不同的维度,以便图表不会影响自身。@Gordon,这是唯一的方法吗?创建维度的问题是性能。我正在使用的数据探索平台可以有12个图表和数据网格(自定义)。如果我们不得不走维度路线,将会出现巨大的性能问题。我们通常有200万到500万之间的数据。我想你已经有那么多行的性能问题了。我从不建议超过500K行。但当然,总有另一种方法。我的问题是:你想在饼图切片隐藏时过滤数据吗?是的,我想在饼图切片隐藏时过滤数据。-关于性能,是的,我们有一些挑战,但是我们已经实现了自定义交叉过滤器(相同的API),但是可以处理索引数据,例如
[{name:1,age:20},{name:2,age:40},{name:3,age:50},{name:5,age:60}]
我们将其转换为索引对象数组
{name:[1,L2,5],age:[20,40,s10l2]}
并且我们聚合数据并仅在存在网格的情况下进行扩展,因此总体性能不错:)。将开源时其稳定(我们也有java代码)。真棒!我很想看看。我在下面提出了一个可能的解决方案。有点骇人,它只是颠倒了dc.js所做的每一个假设。正如您所看到的,这个想法在很多方面与dc.js和crossfilter相反——尽管这仍然是一个好主意!非常感谢,您的答案最好的部分不只是抛出一些代码,而是解释在学习
dcjs
时哪个更重要。我衷心感谢。