问题
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