如何将NVD3折线图定位在所有其他区域/条形图上方?

时间:2015-10-07 19:22:07

标签: javascript angularjs d3.js charts nvd3.js

The Plunker example

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

enter image description here

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

不再有错误,但是蓝线图仍未在所有其他图像前面移动。

3 个答案:

答案 0 :(得分:2)

添加此项以在线(Area Chart)DOM元素之后移动您的线(折线图)DOM元素。

d3.select('.lines2Wrap').node().parentNode.insertBefore(d3.select('.stack1Wrap').node(), d3.select('.lines2Wrap').node());

完整的工作代码here

锄头有帮助! :)

答案 1 :(得分:1)

当我在两天内遇到类似的问题时,我会在这里发布我的解决方案以防万一。

在我的图表设置中,我有调度功能,它会在图表中附加一个矩形,然后将其降低到底部:

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画布上没有z-index。这意味着追加顺序定义了图层,这意味着如果您将矩形作为最后一项附加,它将位于顶部。因此需要改变元素的顺序。

我犯了错误的一步是我第一次使用ES6函数声明,它不能像我想的那样使用“this”。

详细了解选择:replay-kit

了解有关降低或提升项目的更多信息:https://github.com/d3/d3-selection/blob/master/README.md#select

以下是一个工作人员,可以看到它的实际效果:https://github.com/d3/d3-selection/blob/master/README.md#selection_lower

答案 2 :(得分:0)

我认为只是在你的特定图表上,行系列在lines2wrap下,而不是lines1wrap。 IIRC,这与哪个系列是“第一个”有关。在你的plunker中,我将1改为2并且它有效。

这是一个hacky解决方法(这是我的Github,感谢通知我),并且可能需要一些修补才能更普遍有用。