如何将 NVD3 线图置于所有其他区域/条形图之上?
How to position NVD3 line graph above all other area / bar graphs?
在上面的示例中,您可以看到在橙色区域图下方呈现的线条:
正在阅读此 trend here,然后我尝试了此 d3.select('svg#chart .lines1Wrap').moveToFront();
,但收到错误 moveToFront
不是函数。
图表代码
var data = [{
"key": "Price",
"type": "line",
"yAxis": 2,
"values": [
[1443621600000, 71.89],
[1443619800000, 75.51],
[1443618000000, 12.49],
[1443616200000, 20.72],
[1443612600000, 70.39],
[1443610800000, 59.77],
]
}, {
"key": "Quantity1",
"type": "area",
"yAxis": 1,
"values": [
[1136005200000, 1],
[1138683600000, 5],
[1141102800000, 10],
[1143781200000, 0],
[1146369600000, 1],
[1149048000000, 0],
]
}];
data = data.map(function(series) {
series.values = series.values.map(function(d) {
return {
x: d[0],
y: d[1]
}
});
return series;
});
nv.addGraph(function() {
var chart = nv.models.multiChart()
.margin({
top: 20,
right: 40,
bottom: 50,
left: 40
})
.yDomain1([0, 10])
.yDomain2([0, 100]) // hard-coded :<
.interpolate("linear") // don't smooth out the lines
.color(d3.scale.category10().range());
chart.xAxis.tickFormat(function(d) {
return d3.time.format('%I:%M')(new Date(d));
});
chart.yAxis1.tickFormat(d3.format(',f'));
chart.yAxis2.tickFormat(function(d) {
return '$' + d3.format(',f')(d)
});
d3.select('svg#chart')
.datum(data)
.transition().duration(500).call(chart);
d3.selection.prototype.moveToFront = function() {
return this.each(function() {
this.parentNode.appendChild(this);
});
};
d3.select('svg#chart .lines1Wrap').moveToFront();
chart.update();
nv.utils.windowResize(chart.update);
return chart;
});
更新
找到this answer here,尝试使用解决方案:
d3.selection.prototype.moveToFront = function() {
return this.each(function() {
this.parentNode.appendChild(this);
});
};
d3.selection.prototype.moveToBack = function() {
return this.each(function() {
var firstChild = this.parentNode.firstChild;
if (firstChild) {
this.parentNode.insertBefore(this, firstChild);
}
});
};
d3.select('svg#chart .lines1Wrap').moveToFront();
d3.select('svg#chart .nv-areaWrap').moveToBack();
没有更多的错误,但是蓝线图仍然没有移动到所有其他人的前面。
我认为这只是在您的特定图形上,线系列在 lines2wrap 下,而不是 lines1wrap 下。 IIRC,这与 'first' 是哪个系列有关。在你的 plunker 中,我将 1 更改为 2,它起作用了。
这是一个 hacky 解决方法(这是我从 Github 得到的,感谢您通知我),可能需要一些修改才能更普遍地使用。
添加此以将线(折线图)DOM 元素移动到线(面积图)DOM 元素之后。
d3.select('.lines2Wrap').node().parentNode.insertBefore(d3.select('.stack1Wrap').node(), d3.select('.lines2Wrap').node());
完整的工作代码here
锄这有帮助! :)
由于我为类似问题苦苦挣扎了两天,所以我将 post 我的解决方案放在这里,以防对某人有所帮助。
在我的图表设置中,我有调度功能,它将一个矩形附加到图表,然后将其降低到底部:
dispatch: {
renderEnd: () => {
drawThresholds();
lowerThresholdAreas();
}
}
在 drawThresholds 中,我绘制了实际的矩形:
const drawThresholds = () => {
try {
let svgContainer = d3.select(`svg g`);
svgContainer.append('rect')
.attr('x', 0)
.attr('y', 2)
.attr('width', 200)
.attr('height', 200)
.attr('class', 'threshold_area')
.attr('fill', 'yellow');
}
catch (err) {
// Selector throws an error instead of returning empty list
// when element is not found.
// Ignore exceptions, they occur because page is not loaded yet.
}
};
最后在追加矩形之后,我需要通过调用 lowerFunction 将它们放在底部。使用 d3 selectAll 获取所有 .threshold_area 类 然后将它们插入到该行之前。
const lowerThresholdAreas = () => {
d3.selectAll('.threshold_area').each(function () {
this.parentNode.insertBefore(this, this.parentNode.firstChild);
});
};
现在发生的事情是,在 SVG canvas 上没有 z-index。这意味着追加的顺序定义了层,这意味着如果您将矩形追加为最后一项,它将在顶部。所以需要改变元素的顺序。
另外一个我犯了错误的步骤是我第一次使用 ES6 函数声明,它不能像我想象的那样与 "this" 一起工作。
阅读更多关于选择的信息:https://github.com/d3/d3-selection/blob/master/README.md#select
阅读更多关于降低或升高物品的信息:https://github.com/d3/d3-selection/blob/master/README.md#selection_lower
这是一个可以实际使用的 plunker:https://plnkr.co/edit/QI2HcxcJYRAv0FzXWihd?p=preview
在上面的示例中,您可以看到在橙色区域图下方呈现的线条:
正在阅读此 trend here,然后我尝试了此 d3.select('svg#chart .lines1Wrap').moveToFront();
,但收到错误 moveToFront
不是函数。
图表代码
var data = [{
"key": "Price",
"type": "line",
"yAxis": 2,
"values": [
[1443621600000, 71.89],
[1443619800000, 75.51],
[1443618000000, 12.49],
[1443616200000, 20.72],
[1443612600000, 70.39],
[1443610800000, 59.77],
]
}, {
"key": "Quantity1",
"type": "area",
"yAxis": 1,
"values": [
[1136005200000, 1],
[1138683600000, 5],
[1141102800000, 10],
[1143781200000, 0],
[1146369600000, 1],
[1149048000000, 0],
]
}];
data = data.map(function(series) {
series.values = series.values.map(function(d) {
return {
x: d[0],
y: d[1]
}
});
return series;
});
nv.addGraph(function() {
var chart = nv.models.multiChart()
.margin({
top: 20,
right: 40,
bottom: 50,
left: 40
})
.yDomain1([0, 10])
.yDomain2([0, 100]) // hard-coded :<
.interpolate("linear") // don't smooth out the lines
.color(d3.scale.category10().range());
chart.xAxis.tickFormat(function(d) {
return d3.time.format('%I:%M')(new Date(d));
});
chart.yAxis1.tickFormat(d3.format(',f'));
chart.yAxis2.tickFormat(function(d) {
return '$' + d3.format(',f')(d)
});
d3.select('svg#chart')
.datum(data)
.transition().duration(500).call(chart);
d3.selection.prototype.moveToFront = function() {
return this.each(function() {
this.parentNode.appendChild(this);
});
};
d3.select('svg#chart .lines1Wrap').moveToFront();
chart.update();
nv.utils.windowResize(chart.update);
return chart;
});
更新 找到this answer here,尝试使用解决方案:
d3.selection.prototype.moveToFront = function() {
return this.each(function() {
this.parentNode.appendChild(this);
});
};
d3.selection.prototype.moveToBack = function() {
return this.each(function() {
var firstChild = this.parentNode.firstChild;
if (firstChild) {
this.parentNode.insertBefore(this, firstChild);
}
});
};
d3.select('svg#chart .lines1Wrap').moveToFront();
d3.select('svg#chart .nv-areaWrap').moveToBack();
没有更多的错误,但是蓝线图仍然没有移动到所有其他人的前面。
我认为这只是在您的特定图形上,线系列在 lines2wrap 下,而不是 lines1wrap 下。 IIRC,这与 'first' 是哪个系列有关。在你的 plunker 中,我将 1 更改为 2,它起作用了。
这是一个 hacky 解决方法(这是我从 Github 得到的,感谢您通知我),可能需要一些修改才能更普遍地使用。
添加此以将线(折线图)DOM 元素移动到线(面积图)DOM 元素之后。
d3.select('.lines2Wrap').node().parentNode.insertBefore(d3.select('.stack1Wrap').node(), d3.select('.lines2Wrap').node());
完整的工作代码here
锄这有帮助! :)
由于我为类似问题苦苦挣扎了两天,所以我将 post 我的解决方案放在这里,以防对某人有所帮助。
在我的图表设置中,我有调度功能,它将一个矩形附加到图表,然后将其降低到底部:
dispatch: {
renderEnd: () => {
drawThresholds();
lowerThresholdAreas();
}
}
在 drawThresholds 中,我绘制了实际的矩形:
const drawThresholds = () => {
try {
let svgContainer = d3.select(`svg g`);
svgContainer.append('rect')
.attr('x', 0)
.attr('y', 2)
.attr('width', 200)
.attr('height', 200)
.attr('class', 'threshold_area')
.attr('fill', 'yellow');
}
catch (err) {
// Selector throws an error instead of returning empty list
// when element is not found.
// Ignore exceptions, they occur because page is not loaded yet.
}
};
最后在追加矩形之后,我需要通过调用 lowerFunction 将它们放在底部。使用 d3 selectAll 获取所有 .threshold_area 类 然后将它们插入到该行之前。
const lowerThresholdAreas = () => {
d3.selectAll('.threshold_area').each(function () {
this.parentNode.insertBefore(this, this.parentNode.firstChild);
});
};
现在发生的事情是,在 SVG canvas 上没有 z-index。这意味着追加的顺序定义了层,这意味着如果您将矩形追加为最后一项,它将在顶部。所以需要改变元素的顺序。
另外一个我犯了错误的步骤是我第一次使用 ES6 函数声明,它不能像我想象的那样与 "this" 一起工作。
阅读更多关于选择的信息:https://github.com/d3/d3-selection/blob/master/README.md#select
阅读更多关于降低或升高物品的信息:https://github.com/d3/d3-selection/blob/master/README.md#selection_lower
这是一个可以实际使用的 plunker:https://plnkr.co/edit/QI2HcxcJYRAv0FzXWihd?p=preview