2016-11-21 57 views
6

我正在使用x和y轴工作d3.js .v4图形,我需要您的帮助。d3.js自定义曲线步骤

描述:

XAXIS是线性缩放的,像这样的图像在其上的路径。 round corner on d3.curveStep

我卡在这里,无法找到解决方案,以这样的形象path with rounded corner

的路径这是我行的功能代码

// 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);

我试着与基数,单调和catmull buth不能存档所需的路径。

是否可以在d3.curveStep上四舍五入?

回答

7

我终于发现有时会回到这个问题。这是实施custom curve的好机会。我基本上偷了源代码到d3.curveStepBefore和修改,以适应您的要求。

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="[email protected]" 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>

+0

谢谢你马克的时间!这是我需要的。现在我需要弄清楚如何编辑curveStep的这段代码。当前curveStepBefore(四舍五入)将我的线路路径与背景网格对齐,但路径需要在网格之间。 – stojkosd

+0

@djstojadin,查看更新的答案。我实现了'curveStep'和'curveStepAfter'。 – Mark

+0

杰出!对你很好。 –