使d3轴刻度线与图形点对齐

时间:2016-10-27 16:51:13

标签: javascript css d3.js

此处参考是图像。请注意,悬停日期与轴上的日期不完全对齐。如果我试图改变边距,我可以改变日期,但仍然有不均匀的间距。我正在寻找一种更灵活地控制轴上日期间距的方法。 enter image description here

以下是有问题的代码:



const dataGroup = [
        {
          key: props.lineChart.key,
          values: props.lineChart.values,
          startColor: '#E2FFE4',
          endColor: '#6FFCAF',
          area: false,
        }];
      const vis = d3.select(ReactDOM.findDOMNode(this));
      const bisectDate = d3.bisector(d => d.x).left;
      const WIDTH = 1000;
      const HEIGHT = 480;
      const MARGINS = {
        top: 20,
        right: 40,
        bottom: 20,
        left: 30,
      };
      const minYValue = 0;
      const maxYValue = d3.max(dataGroup.map(group =>
        d3.max(group.values, row => row.y)
      ));

      const format = d3.time.format('%m/%d');
      const xScale = d3.time.scale()
        .range([MARGINS.left, WIDTH - MARGINS.right])
        .domain(d3.extent(dataGroup[0].values, d => d.x));

      const customScale = d3.time.scale()
        .range([8, WIDTH - MARGINS.right])
        .domain(d3.extent(dataGroup[0].values, d => d.x));

      const yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom])
        .domain([minYValue, maxYValue + 200]);

      const xAxis = d3.svg.axis()
              .scale(customScale)
              .ticks(d3.time.days, 1)
              .tickFormat(format);

      const yAxis = d3.svg.axis()
              .scale(yScale)
              .ticks(5)
              .tickFormat(d => (d === 0 ? 0 : numeral(d).format('0a')))
              .orient('left');

              vis.append("g")
                  .attr("class", "grid")
                  .attr("transform", "translate(" + MARGINS.left + ",0)")
                  .call(makeXAxis(yScale)
                      .tickSize(-(WIDTH - MARGINS.right - MARGINS.left), 0, 0)
                      .tickFormat("")
                  )

              var lineGen = d3.svg.line()
                      .x(function(d) {
                          return xScale(new Date(d.x));
                      })
                      .y(function(d) {
                          return yScale(d.y);
                      })
              console.log('Data Group', dataGroup);

              dataGroup.forEach(function(d, i) {
                   vis.append("linearGradient")
                      .attr("id", "line-gradient")
                      .attr("gradientUnits", "userSpaceOnUse")
                      .attr("x1", 0).attr("y1", "0")
                      .attr("x2", "100%").attr("y2", "0")
                      .selectAll("stop")
                      .data([
                          {offset: "0%", color: "yellow"},
                          {offset: "100%", color: "orange"}
                      ])
                      .enter().append("stop")
                      .attr("offset", function(d) { return d.offset; })
                      .attr("stop-color", function(d) { return d.color; });

                      vis.append('svg:path')
                      .attr('class', "line clickable")
                      .attr('d', lineGen(d.values))
                      .attr('stroke', 'blue')
                      .attr('stroke-width', 2)
                      .attr('fill', 'none');

              });


              vis.append("svg:g")
                      .attr("class", "x axis")
                      .attr("transform", "translate(5," + (HEIGHT - MARGINS.bottom + 20) + ")")
                      .call(xAxis);
              vis.append("svg:g")
                      .attr("class", "y axis")
                      .attr("transform", "translate(" + (MARGINS.left) + ",0)")
                      .call(yAxis);

              var focus = vis.append("g")
                          .attr("class", "focus")
                          .style("display", "none")
                          .style("opacity", "1");

              focus.append("circle")
                  .attr("r", 8)
                  .attr("fill", 'orange')
                  .attr("stroke", 'white')
                  .attr("stroke-width", '2px')

              var tooltip = vis.append("g")
                              .attr("class", "tooltip")
                              .style("display", "none");


              tooltip.append("rect")
                  .attr("width", 90)
                  .attr("height", 20)
                  .attr("rx", 2.5)
                  .attr("ry", 2.5)
                  .attr("fill", 'lightgray');

              var tooltipText = tooltip.append("text")
                  .attr("dy", 15)
                  .attr("dx", 15);

              tooltipText.text(null).append("tspan")
                  .attr('class', 'date');

              tooltipText.append("tspan").text(' ');

              tooltipText.append("tspan")
                  .attr('class', 'volume');

              vis.on("mouseover", function() { focus.style("display", null); verticalLine.style("display", null); tooltip.style("display", null);})
                  .on("mouseout", function() {
                    focus.style("display", "none");
                    verticalLine.style("display", "none");
                    tooltip.style("display", "none");
                    updateInfluencerSample({
                    });
                  })
                  .on("mousemove", mousemove);

              function mousemove() {
                  if(dataGroup.length === 1) {
                      index = 0;
                  }
                  else {
                      var isPositive = (yScale.invert(d3.mouse(this)[1]) > 0),
                          index = isPositive ? 0 : 1;
                  }
                      var x0 = xScale.invert(d3.mouse(this)[0]),
                      i = bisectDate(dataGroup[index].values, x0, 1),
                      d0 = dataGroup[index].values[i - 1],
                      d1 = dataGroup[index].values[i];

                  if(d0 && d1) {
                      var d = x0 - d0.x > d1.x - x0 ? d1 : d0;
                      if(dataGroup.length === 1) d.y = Math.abs(d.y);
                      var criticalPointYPos = (d.y > 0) ? -0.6 : 1.2;
                      focus.attr("transform", "translate(" + xScale(d.x) + "," + yScale(d.y) + ")");
                      tooltip.attr("transform", "translate(" + (xScale(d.x) - 45) + "," + (HEIGHT - MARGINS.bottom) + ")");
                      tooltip.select(".date").text(format(new Date(d.x))).attr('fill', '#929292');
                      tooltip.select(".volume").text(numeral(d.y).format('0a')).attr('fill', '#929292');
                      d3.select(".verticalLine").attr({
                                  x1: 0,
                                  x2: 0,
                                  y1: MARGINS.top,
                                  y2: HEIGHT - MARGINS.bottom,
                              })
                      .style("stroke-dasharray", ("3, 3"))
                      .attr("stroke-width", 3)
                      .attr("transform", function () {
                          return "translate(" + xScale(d.x) + ",0)";
                      });
                      updateInfluencerSample({
                          author: new Date().getMilliseconds(),
                          date: d.x,
                      });
                  }
              }

              var verticalLine = vis.append('line')
                                  .attr({
                                      x1: 0,
                                      x2: 0,
                                      y1: yScale(maxYValue),
                                      y2: HEIGHT - MARGINS.bottom,
                                  })
                                  .attr('stroke', 'gray')
                                  .attr('class', 'verticalLine')
                                  .style('display', 'none');

              vis.transition().style("opacity", 1);
  }




1 个答案:

答案 0 :(得分:0)

将translate属性更改为0,这是偏移轴。

 vis.append("svg:g")
                      .attr("class", "x axis")
                      .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom + 20) + ")")
                      .call(xAxis);