d3.js custom curve step round

微笑、不失礼 提交于 2019-12-18 16:45:23

问题


I'm working on d3.js .v4 graph with x and y axis and I need your help.

Description:

xAxis is linear scaled with path on it like this image.

I'm stuck here and can't find solution to make path like on this image path with rounded corner

This is my code for line function

    // the path generator for the line chart
line = d3.line()
  .x(function(d, i) {
    return xScale(i);
  })
  .y(function(d, i) {
    return yScale(d);
  })
  .curve(d3.curveStep);

I tried with cardinal, monotone and catmull buth can't archive desired path.

Is it possible to round corners on d3.curveStep?


回答1:


I finally found sometime to comeback to this question. This is a great opportunity to implement a custom curve. I essentially stole the source code to d3.curveStepBefore and modified to fit your requirements.

function Step(context, t) {
  this._context = context;
  this._t = t;
}

Step.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x = this._y = NaN;
    this._point = 0;
  },
  lineEnd: function() {
    if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
    if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
  },
  point: function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0:
      case 0:
        this._point = 1;
        this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
        break;
      case 1:
        this._point = 2; // proceed
      default:
        {
          var xN, yN, mYb, mYa;
          if (this._t <= 0) {
            xN = Math.abs(x - this._x) * 0.25;
            yN = Math.abs(y - this._y) * 0.25;
            mYb = (this._y < y) ? this._y + yN : this._y - yN;
            mYa = (this._y > y) ? y + yN : y - yN;

            this._context.quadraticCurveTo(this._x, this._y, this._x, mYb);
            this._context.lineTo(this._x, mYa);
            this._context.quadraticCurveTo(this._x, y, this._x + xN, y);
            this._context.lineTo(x - xN, y);

          } else {
            var x1 = this._x * (1 - this._t) + x * this._t;

            xN = Math.abs(x - x1) * 0.25;
            yN = Math.abs(y - this._y) * 0.25;
            mYb = (this._y < y) ? this._y + yN : this._y - yN;
            mYa = (this._y > y) ? y + yN : y - yN;

            this._context.quadraticCurveTo(x1, this._y, x1, mYb);
            this._context.lineTo(x1, mYa);
            this._context.quadraticCurveTo(x1, y, x1 + xN, y);
            this._context.lineTo(x - xN, y);
          }
          break;
        }
    }
    this._x = x, this._y = y;
  }
};

stepRound = function(context) {
  return new Step(context, 0.5);
};

stepRoundBefore = function(context) {
  return new Step(context, 0);
};

stepRoundAfter = function(context) {
  return new Step(context, 1);
};
<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
  <script>
    document.addEventListener("DOMContentLoaded", function(event) {

      var width = 500,
        height = 500,
        N = 10;

      var svg = d3.select('body')
        .append('svg')
        .attr('width', width)
        .attr('height', height);

      var points = [];
      for (var i = 0; i < N; i++) {
        points.push({
          x: (width / N) * i + (width / N / 2),
          y: Math.random() * height
        });
      }

      var line1 = d3.line()
        .x(function(d) {
          return d.x;
        })
        .y(function(d) {
          return d.y;
        })
        .curve(stepRound);

      var line2 = d3.line()
        .x(function(d) {
          return d.x;
        })
        .y(function(d) {
          return d.y;
        })
        .curve(d3.curveStep);

      svg.append('path')
        .datum(points)
        .attr('d', line1)
        .attr('fill', 'none')
        .attr('stroke', 'orange')
        .attr('stroke-width', '3px');

      svg.append('path')
        .datum(points)
        .attr('d', line2)
        .attr('fill', 'none')
        .attr('stroke', 'steelblue')
        .attr('stroke-width', '1px');

    });
  </script>
</body>

</html>


来源:https://stackoverflow.com/questions/40729164/d3-js-custom-curve-step-round

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!