dc.js 删除 PIE 图中单击的切片而不是变灰?
dc.js Remove clicked slice in PIE chart instead of grey out?
我想从 PIE 图中删除选定的切片,而不是将其灰显。例如 DC page "Days by Gain/Loss" 或 "Quarters" PIE 图表,如果我单击切片(比如 Q4)我想从显示中删除该条目(包括切片 + 图例,如果我想恢复我可以使用控件来重置它)。
如何实现这种行为?
我在点击处理程序中尝试了以下操作:
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
:
.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;
});
可能有很多方法可以做到这一点,但我首先想到的是,"sounds like a fake group" 其行为类似于普通组,但它确实遵守其自身维度的过滤器:
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))
只需从图表中获取过滤器并确保排除了这些垃圾箱。这与 Others 无关,但添加起来很简单。
接下来,我们要过滤 out 值,而不是像 dc.js 通常那样过滤 in 值。我们可以通过修改默认的过滤器处理程序来做到这一点。我认为这与您在上面所做的类似,但更简单:
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));
最后,"deselected grey" 对我们没有用,我不知道如何禁用 CSS 规则的效果,所以让我们删除 class 在图表绘制之后但在显示之前的切片中:
yearRingChart.on('pretransition', function(chart) {
chart.selectAll('g.deselected').classed('deselected', false);
});
我相信还有很多其他方法可以做到这一点,也许还有更简洁的方法。这就是我想到的。我很乐意为其他人添加支持,但我想首先介绍基本思想。
我想从 PIE 图中删除选定的切片,而不是将其灰显。例如 DC page "Days by Gain/Loss" 或 "Quarters" PIE 图表,如果我单击切片(比如 Q4)我想从显示中删除该条目(包括切片 + 图例,如果我想恢复我可以使用控件来重置它)。
如何实现这种行为?
我在点击处理程序中尝试了以下操作:
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
:
.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;
});
可能有很多方法可以做到这一点,但我首先想到的是,"sounds like a fake group" 其行为类似于普通组,但它确实遵守其自身维度的过滤器:
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))
只需从图表中获取过滤器并确保排除了这些垃圾箱。这与 Others 无关,但添加起来很简单。
接下来,我们要过滤 out 值,而不是像 dc.js 通常那样过滤 in 值。我们可以通过修改默认的过滤器处理程序来做到这一点。我认为这与您在上面所做的类似,但更简单:
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));
最后,"deselected grey" 对我们没有用,我不知道如何禁用 CSS 规则的效果,所以让我们删除 class 在图表绘制之后但在显示之前的切片中:
yearRingChart.on('pretransition', function(chart) {
chart.selectAll('g.deselected').classed('deselected', false);
});
我相信还有很多其他方法可以做到这一点,也许还有更简洁的方法。这就是我想到的。我很乐意为其他人添加支持,但我想首先介绍基本思想。