dc.js:dispose() 和 deregisterChart() 的问题
dc.js: Problems with dispose() and deregisterChart()
我正在创建一个可以动态添加和删除图表的应用程序。一切正常,但删除图表。
当我有一个折线图和一个条形图时,我遇到了这个问题,其中一个是复合图,我删除了其中一个(处理维度并取消注册图表)。在这一点上,我没有处理的图表停止对来自其他图表的过滤器做出反应,并且停止对它自己的事件做出反应,即使其他图表被它们过滤了。此外,正如您在 fiddle 中看到的,我从 dc 中删除的折线图仍在对其他图表过滤器做出反应。
我发现问题出在 deregisterChart dc 调用上,但由于我的应用程序可以创建和删除无穷大图表,我需要一种方法从 dc 中删除我不再需要的图表,同时不破坏留下的图表.
这是代码:
resetFilter = function() {
lineData.dispose()
dc.deregisterChart(linechart);
}
for (var j = 0; j < axis.length; j++) {
var dimData = __cfArray[dataId].dimension(function(d) {
return d[axis[j].xaxis];
});
var barGroup = getGroup(dimData, axis[j].xaxis, axis[j].yaxis, operation, isDate);
barCharts.push(dc.barChart(composite)
.valueAccessor(accesor)
.dimension(dimData)
.group(barGroup, xAxisTitle[j])
.transitionDuration(1000)
.gap(gap)
.colors(barColors[j])
.centerBar(function() {
if (axis.length > 1) return false;
else return true;
})
.title(function(d) {
if (operation === count) {
if (isDate) return format(d.key) + ": " + d.value.count;
else return d.key + ": " + d.value.count;
} else {
if (isDate) return format(d.key) + ": " + d.value.total;
else return d.key + ": " + d.value.total;
}
})
);
lineData = __cfArray[dataId].dimension(function(d) {
return d[axis[j].xaxis];
});
var lineGroup = getGroupLine(lineData, axis[j].xaxis, axis[j].yaxis, true, operation, isDate);
linechart = dc.lineChart(lineDom)
.dimension(lineData)
.group(lineGroup, xAxisTitle[j] + "/" + yAxisTitle)
.useRightYAxis(true)
.colors(lineColors[j])
.title(function(d) {
if (operation === count) {
if (isDate) return format(d.key) + ": " + d.valueCount;
else return d.key + ": " + d.valueCount;
} else {
if (isDate) return format(d.key) + ": " + d.valueTotal;
else return d.key + ": " + d.valueTotal;
}
})
.valueAccessor(function(p) {
if (operation === count) {
return p.valueCount;
} else {
return p.valueTotal;
}
});
}
var xMine;
var dom = [];
for (var i = 0; i < axis.length; i++) {
if (dom.length === 0) {
dom = __dataArray[dataId].map(function(d) {
return d[axis[i].xaxis]
});
} else {
dom = dom.concat(__dataArray[dataId].map(function(d) {
return d[axis[i].xaxis]
}));
}
}
if (isNaN(dom[0])) {
xMine = d3.scale.ordinal().domain(dom.sort());
} else {
xMine = d3.scale.ordinal().domain(dom.sort(function(a, b) {
return a - b;
}));
}
composite.xUnits(dc.units.ordinal)
linechart.xUnits(dc.units.ordinal)
linechart.width(width)
.height(height)
.margins(margin)
.x(xMine)
.elasticY(true)
.legend(dc.legend().x(80).y(10).itemHeight(13).gap(5))
._rangeBandPadding(1)
.brushOn(false);
composite.width(width)
.height(height)
.margins(margin)
.x(xMine)
.rightYAxisLabel(yAxisRightTitle)
.elasticY(true)
.legend(dc.legend().x(80).y(10).itemHeight(13).gap(5))
._rangeBandPadding(1)
.brushOn(false)
.shareTitle(false)
.mouseZoomable(true)
.yAxisPadding('10%')
.compose(barCharts)
.renderHorizontalGridLines(true);
composite.yAxis().tickFormat(d3.format('s'));
composite.rightYAxis().tickFormat(d3.format('s'));
composite.render();
linechart.render();
这是我用我的问题创建的 fiddle:
https://jsfiddle.net/nofknndf/9/
谢谢!
恭喜你,这是一个复杂而精密的系统。
我承认我没有深入了解为什么您会看到当前的 st运行ge 行为,但我确实找到了问题并且我想我已经解决了它。
在 getGroupLine
中,您实际上是在每次调用 fake-group .all()
方法时创建一个组:
function getGroupLine(dimension, xaxis, yaxis, isCum, operation, isDate){
return {
all:function () {
// ...
var _group = dimension.group().reduce(reduceAdd, reduceRemove, reduceInitial).orderNatural();
这很容易让人很快混淆!我通过在调试器中进入 dimension.dispose()
来发现这一点,看看它是否在工作 - 每次它 运行 时都有越来越多的组。
分组存储在维度中,可独立处置
您想在调用函数时创建 "base group" _group
,返回的假组将只获取 _group.all()
:
function getGroupLine(dimension, xaxis, yaxis, isCum, operation, isDate){
var reduceAdd = function(p, v) {
if (!(isDate && v[xaxis] === 0 )) {
++p.count;
p.total += v[yaxis];
}
return p;
}
var reduceRemove = function(p, v) {
if (!(isDate && v[xaxis] === 0 )) {
--p.count;
p.total -= v[yaxis];
}
return p;
}
var reduceInitial = function() {
return {
count: 0,
total: 0,
elements: []
};
}
var _group = dimension.group().reduce(reduceAdd, reduceRemove, reduceInitial).orderNatural();
return {
all:function () {
var totalCount = 0;
var total = 0;
var g = [];
_group.all().forEach(function(d,i) {
if(isCum){
totalCount += d.value.count;
total += d.value.total;
} else {
totalCount = d.value.count;
total = d.value.total;
}
g.push({key:d.key,valueTotal:total,valueCount:totalCount})
});
return g;
}
};
}
这似乎解释了折线图继续被过滤的原因。
另一个问题是注销了错误的图表。这是因为您的每个图表都需要有自己独特的锚点 (id
) - 在您的示例中,它们都被命名为 "composite"。 dc.js 在注销时依赖于比较锚名称,因此如果两个图表具有相同的 id
,则错误的将被删除。 HTML 要求 id
是唯一的,因此您可能会 运行 遇到其他问题。
将折线图的 id
重命名为 "line" 修复了注销问题。
在此处更新了您 fiddle 的分支:https://jsfiddle.net/dnrxxjyo/4/
我正在创建一个可以动态添加和删除图表的应用程序。一切正常,但删除图表。
当我有一个折线图和一个条形图时,我遇到了这个问题,其中一个是复合图,我删除了其中一个(处理维度并取消注册图表)。在这一点上,我没有处理的图表停止对来自其他图表的过滤器做出反应,并且停止对它自己的事件做出反应,即使其他图表被它们过滤了。此外,正如您在 fiddle 中看到的,我从 dc 中删除的折线图仍在对其他图表过滤器做出反应。
我发现问题出在 deregisterChart dc 调用上,但由于我的应用程序可以创建和删除无穷大图表,我需要一种方法从 dc 中删除我不再需要的图表,同时不破坏留下的图表.
这是代码:
resetFilter = function() {
lineData.dispose()
dc.deregisterChart(linechart);
}
for (var j = 0; j < axis.length; j++) {
var dimData = __cfArray[dataId].dimension(function(d) {
return d[axis[j].xaxis];
});
var barGroup = getGroup(dimData, axis[j].xaxis, axis[j].yaxis, operation, isDate);
barCharts.push(dc.barChart(composite)
.valueAccessor(accesor)
.dimension(dimData)
.group(barGroup, xAxisTitle[j])
.transitionDuration(1000)
.gap(gap)
.colors(barColors[j])
.centerBar(function() {
if (axis.length > 1) return false;
else return true;
})
.title(function(d) {
if (operation === count) {
if (isDate) return format(d.key) + ": " + d.value.count;
else return d.key + ": " + d.value.count;
} else {
if (isDate) return format(d.key) + ": " + d.value.total;
else return d.key + ": " + d.value.total;
}
})
);
lineData = __cfArray[dataId].dimension(function(d) {
return d[axis[j].xaxis];
});
var lineGroup = getGroupLine(lineData, axis[j].xaxis, axis[j].yaxis, true, operation, isDate);
linechart = dc.lineChart(lineDom)
.dimension(lineData)
.group(lineGroup, xAxisTitle[j] + "/" + yAxisTitle)
.useRightYAxis(true)
.colors(lineColors[j])
.title(function(d) {
if (operation === count) {
if (isDate) return format(d.key) + ": " + d.valueCount;
else return d.key + ": " + d.valueCount;
} else {
if (isDate) return format(d.key) + ": " + d.valueTotal;
else return d.key + ": " + d.valueTotal;
}
})
.valueAccessor(function(p) {
if (operation === count) {
return p.valueCount;
} else {
return p.valueTotal;
}
});
}
var xMine;
var dom = [];
for (var i = 0; i < axis.length; i++) {
if (dom.length === 0) {
dom = __dataArray[dataId].map(function(d) {
return d[axis[i].xaxis]
});
} else {
dom = dom.concat(__dataArray[dataId].map(function(d) {
return d[axis[i].xaxis]
}));
}
}
if (isNaN(dom[0])) {
xMine = d3.scale.ordinal().domain(dom.sort());
} else {
xMine = d3.scale.ordinal().domain(dom.sort(function(a, b) {
return a - b;
}));
}
composite.xUnits(dc.units.ordinal)
linechart.xUnits(dc.units.ordinal)
linechart.width(width)
.height(height)
.margins(margin)
.x(xMine)
.elasticY(true)
.legend(dc.legend().x(80).y(10).itemHeight(13).gap(5))
._rangeBandPadding(1)
.brushOn(false);
composite.width(width)
.height(height)
.margins(margin)
.x(xMine)
.rightYAxisLabel(yAxisRightTitle)
.elasticY(true)
.legend(dc.legend().x(80).y(10).itemHeight(13).gap(5))
._rangeBandPadding(1)
.brushOn(false)
.shareTitle(false)
.mouseZoomable(true)
.yAxisPadding('10%')
.compose(barCharts)
.renderHorizontalGridLines(true);
composite.yAxis().tickFormat(d3.format('s'));
composite.rightYAxis().tickFormat(d3.format('s'));
composite.render();
linechart.render();
这是我用我的问题创建的 fiddle: https://jsfiddle.net/nofknndf/9/
谢谢!
恭喜你,这是一个复杂而精密的系统。
我承认我没有深入了解为什么您会看到当前的 st运行ge 行为,但我确实找到了问题并且我想我已经解决了它。
在 getGroupLine
中,您实际上是在每次调用 fake-group .all()
方法时创建一个组:
function getGroupLine(dimension, xaxis, yaxis, isCum, operation, isDate){
return {
all:function () {
// ...
var _group = dimension.group().reduce(reduceAdd, reduceRemove, reduceInitial).orderNatural();
这很容易让人很快混淆!我通过在调试器中进入 dimension.dispose()
来发现这一点,看看它是否在工作 - 每次它 运行 时都有越来越多的组。
分组存储在维度中,可独立处置
您想在调用函数时创建 "base group" _group
,返回的假组将只获取 _group.all()
:
function getGroupLine(dimension, xaxis, yaxis, isCum, operation, isDate){
var reduceAdd = function(p, v) {
if (!(isDate && v[xaxis] === 0 )) {
++p.count;
p.total += v[yaxis];
}
return p;
}
var reduceRemove = function(p, v) {
if (!(isDate && v[xaxis] === 0 )) {
--p.count;
p.total -= v[yaxis];
}
return p;
}
var reduceInitial = function() {
return {
count: 0,
total: 0,
elements: []
};
}
var _group = dimension.group().reduce(reduceAdd, reduceRemove, reduceInitial).orderNatural();
return {
all:function () {
var totalCount = 0;
var total = 0;
var g = [];
_group.all().forEach(function(d,i) {
if(isCum){
totalCount += d.value.count;
total += d.value.total;
} else {
totalCount = d.value.count;
total = d.value.total;
}
g.push({key:d.key,valueTotal:total,valueCount:totalCount})
});
return g;
}
};
}
这似乎解释了折线图继续被过滤的原因。
另一个问题是注销了错误的图表。这是因为您的每个图表都需要有自己独特的锚点 (id
) - 在您的示例中,它们都被命名为 "composite"。 dc.js 在注销时依赖于比较锚名称,因此如果两个图表具有相同的 id
,则错误的将被删除。 HTML 要求 id
是唯一的,因此您可能会 运行 遇到其他问题。
将折线图的 id
重命名为 "line" 修复了注销问题。
在此处更新了您 fiddle 的分支:https://jsfiddle.net/dnrxxjyo/4/