问题
The Plunker example
In the example above you can see that the line is rendered under the orange area graph:
Was reading this trend here, then I tried this d3.select('svg#chart .lines1Wrap').moveToFront();
, but got the error moveToFront
is not a function.
Chart code
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;
});
UPDATE Found this answer here, tried to use the solution:
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();
No more error, however the blue line graph still is not moved in front of all the others.
回答1:
Add this to move your line(line chart) DOM element after the line(Area Chart) DOM element.
d3.select('.lines2Wrap').node().parentNode.insertBefore(d3.select('.stack1Wrap').node(), d3.select('.lines2Wrap').node());
Full working code here
Hoe this helps! :)
回答2:
As I struggled with a similar problem for two days I will post my solution here in case it helps someone.
In my chart settings I have dispatch function which will append a rectangle to the chart and then lower it to the bottom:
dispatch: {
renderEnd: () => {
drawThresholds();
lowerThresholdAreas();
}
}
In the drawThresholds I draw the actual rectangle:
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.
}
};
And finally after rectangles are appended, I need to place them to the bottom by calling lowerFunction. use d3 selectAll to get all .threshold_area classes and then insert them before the line.
const lowerThresholdAreas = () => {
d3.selectAll('.threshold_area').each(function () {
this.parentNode.insertBefore(this, this.parentNode.firstChild);
});
};
And what is happening, is that on SVG canvas there is no z-index. It means the order of appends defines the layers, meaning if you append the rectangle as last item, it will be on top. So the order of elements needs to be changed.
Also a step where I did mistake was that I first used ES6 function declaration and it doesn't work with "this" as I supposed it would.
Read more about selection: https://github.com/d3/d3-selection/blob/master/README.md#select
Read more about lowering or raising items: https://github.com/d3/d3-selection/blob/master/README.md#selection_lower
Here is a working plunker for seeing it in action: https://plnkr.co/edit/QI2HcxcJYRAv0FzXWihd?p=preview
回答3:
I think it's just that on your particular graph, the line series is under lines2wrap, not lines1wrap. IIRC, this has to do with which series is 'first'. In your plunker, I changed the 1 to a 2 and it worked.
It's a hacky workaround (that's mine from Github, thanks for notifying me), and probably requires some tinkering to be more generally useful.
来源:https://stackoverflow.com/questions/33000725/how-to-position-nvd3-line-graph-above-all-other-area-bar-graphs