如何将 NVD3 线图置于所有其他区域/条形图之上?

How to position NVD3 line graph above all other area / bar graphs?

The Plunker example

在上面的示例中,您可以看到在橙色区域图下方呈现的线条:

正在阅读此 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