多线图表X轴刻度线与数据点不对齐

时间:2019-04-05 12:58:56

标签: javascript d3.js

我正在尝试使用D3.js绘制多线图。图表已正确绘制,但x轴刻度未正确与数据点圆对齐。 在此处找到示例代码:https://jsfiddle.net/gopal31795/qsLd7pc5/9/

我假设创建点的代码中存在一些错误。

// Creating Dots on line
segment.selectAll("dot")
  .data(function(d) {
    return d.linedata;
  })
  .enter().append("circle")
  .attr("r", 5)
  .attr("cx", function(d) {
    //return x(parseDate(new Date(d.mins))) + x.rangeBand() / 2;
    return x(d.mins);
  })
  .attr("cy", function(d) {
    return y(d.value);
  })
  .style("stroke", "white")
  .style("fill", function(d) {
    return color(this.parentNode.__data__.name);
  })

  .on("mouseenter", function(d) {
    d3.select(this).transition().style("opacity", "0.25");
    tooltip.html("<span style='color:" + color(this.parentNode.__data__.name) + ";'>" + this.parentNode.__data__.name + "</span>: " + (d.value + "s")).style("visibility", "visible").style("top", (event.pageY + 10) + "px").style("left", (event.pageX) + "px");
  })
  .on("mouseleave", function(d) {
    d3.select(this).transition().style("opacity", "1");
    tooltip.style("visibility", "hidden");
  });

1 个答案:

答案 0 :(得分:1)

您的代码(使用旧版v3)中的问题是您使用的是rangeRoundBands。例如,如果您有条形图,那将是正确的选择。

但是,由于您正在处理数据点,因此应使用rangePointsrangeRoundPoints,这将:

  

从指定的连续间隔设置输出范围。数组间隔包含两个元素,分别代表最小值和最大值。该间隔可细分为n个均匀分布的点,其中n是输入域中(唯一)值的数量。

因此,应该是:

var x = d3.scale.ordinal()
    .rangeRoundPoints([0, width]);

这是您所做的更改的代码:

var Data = [{
    "name": "R",
    "linedata": [{
        "mins": 0,
        "value": 1120
      },
      {
        "mins": 2,
        "value": 1040
      },
      {
        "mins": 4,
        "value": 1400
      },
      {
        "mins": 6,
        "value": 1500
      }
    ]
  },
  {
    "name": "E",
    "linedata": [{
        "mins": 0,
        "value": 1220
      },
      {
        "mins": 2,
        "value": 1500
      },
      {
        "mins": 4,
        "value": 1610
      },
      {
        "mins": 6,
        "value": 1700
      }
    ]
  }
];

var margin = {
    top: 20,
    right: 90,
    bottom: 35,
    left: 90
  },
  width = $("#lineChart").width() - margin.left - margin.right,
  height = $("#lineChart").width() * 0.3745 - margin.top - margin.bottom;

//var parseDate = d3.time.format("%d-%b");

var x = d3.scale.ordinal()
  .rangeRoundPoints([0, width]);

var y = d3.scale.linear()
  .range([height, 0]);

var color = d3.scale.category10();

var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom");

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left")
  .ticks(5);

var xData = Data[0].linedata.map(function(d) {
  return d.mins;
});


var line = d3.svg.line()
  .interpolate("linear")
  .x(function(d) {
    return x(d.mins);
  })
  .y(function(d) {
    return y(d.value);
  });

function transition(path) {
  path.transition()
    .duration(4000)
    .attrTween("stroke-dasharray", tweenDash);
}

function tweenDash() {
  var l = this.getTotalLength(),
    i = d3.interpolateString("0," + l, l + "," + l);
  return function(t) {
    return i(t);
  };
}
var svg = d3.select("#lineChart").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

color.domain(Data.map(function(d) {
  return d.name;
}));

x.domain(xData);

var valueMax = d3.max(Data, function(r) {
  return d3.max(r.linedata, function(d) {
    return d.value;
  })
});
var valueMin = d3.min(Data, function(r) {
  return d3.min(r.linedata, function(d) {
    return d.value;
  })
});
y.domain([valueMin, valueMax]);

//Drawing X Axis
svg.append("g")
  .attr("class", "x-axis")
  .attr("transform", "translate(0," + height + ")")

  .call(xAxis)
  .append("text")
  .attr("class", "xAxisText")
  .attr("x", width)
  .attr("dy", "-.41em")
  .style("text-anchor", "end")
  .style("fill", "white")
  .text("Time(m)");


svg.append("g")
  .attr("class", "y-axis")

  .call(yAxis)
  .append("text")
  .attr("transform", "rotate(-90)")
  .attr("y", 6)
  .attr("dy", ".71em")
  .style("text-anchor", "end")
  .style("fill", "none")
  .style("stroke", "white")
  .style("stroke-width", 0.8)
  .text("Duration(s)");

// Drawing Lines for each segments
var segment = svg.selectAll(".segment")
  .data(Data)
  .enter().append("g")
  .attr("class", "segment");

segment.append("path")
  .attr("class", "line")
  .attr("id", function(d) {
    return d.name;
  })
  .attr("visible", 1)
  .call(transition)
  //.delay(750)
  //.duration(1000)
  //.ease('linear')           
  .attr("d", function(d) {
    return line(d.linedata);
  })
  .style("stroke", function(d) {
    return color(d.name);
  });


// Creating Dots on line
segment.selectAll("dot")
  .data(function(d) {
    return d.linedata;
  })
  .enter().append("circle")
  .attr("r", 5)
  .attr("cx", function(d) {
    //return x(parseDate(new Date(d.mins))) + x.rangeBand() / 2;
    return x(d.mins);
  })
  .attr("cy", function(d) {
    return y(d.value);
  })
  .style("stroke", "white")
  .style("fill", function(d) {
    return color(this.parentNode.__data__.name);
  })

  .on("mouseenter", function(d) {
    d3.select(this).transition().style("opacity", "0.25");
    tooltip.html("<span style='color:" + color(this.parentNode.__data__.name) + ";'>" + this.parentNode.__data__.name + "</span>: " + (d.value + "s")).style("visibility", "visible").style("top", (event.pageY + 10) + "px").style("left", (event.pageX) + "px");
  })
  .on("mouseleave", function(d) {
    d3.select(this).transition().style("opacity", "1");
    tooltip.style("visibility", "hidden");
  });
path {
  fill: none;
  stroke: black;
}

line {
  stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<div class="card-body" id="lineChart">
</div>

最后,提示:不要混合使用D3和jQuery。