2016-11-21 86 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

傑出!對你很好。 –