更新时间:2022-12-20 07:53:07
另一个答案是真的很好,可能***的方式来实现你的目标,但是对于后代,这里是新的d3形状的n移动平均 curve factory 方法:
The other answer is really good and is probably the best way to achieve your aims. But for posterity's sake, here's a n-moving-average in the new d3-shape curve factory methodology:
<!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>
<script>
function NMoveAvg(context, N) {
this._context = context;
this._points = {
x: [],
y: []
};
this._N = N;
}
NMoveAvg.prototype = {
areaStart: function() {
this._line = 0;
},
areaEnd: function() {
this._line = NaN;
},
lineStart: function() {
this._point = 0;
},
lineEnd: function() {
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
this._line = 1 - this._line;
},
point: function(x, y) {
x = +x, y = +y;
this._points.x.push(x);
this._points.y.push(y);
if (this._points.x.length < this._N) return;
var aX = this._points.x.reduce(function(a, b) {
return a + b;
}, 0) / this._N,
aY = this._points.y.reduce(function(a, b) {
return a + b;
}, 0) / this._N;
this._points.x.shift();
this._points.y.shift();
switch (this._point) {
case 0:
this._point = 1;
this._line ? this._context.lineTo(aX, aY) : this._context.moveTo(aX, aY);
break;
case 1:
this._point = 2; // proceed
default:
this._context.lineTo(aX, aY);
break;
}
}
};
var curveNMoveAge = (function custom(N) {
function nMoveAge(context) {
return new NMoveAvg(context, N);
}
nMoveAge.N = function(N) {
return custom(+N);
};
return nMoveAge;
})(0);
</script>
</head>
<body>
<script>
var data = [3, 66, 2, 76, 5, 20, 1, 30, 50, 9, 80, 5, 7];
var w = 500,
h = 500;
var x = d3.scaleLinear()
.domain([0, 12])
.range([0, w]);
var y = d3.scaleLinear()
.domain([0, 100])
.range([0, h]);
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var line = d3.line()
.x(function(d, i) {
return x(i);
})
.y(function(d, i) {
return y(d);
});
svg.append("path")
.datum(data)
.attr("d", line.curve(curveNMoveAge.N(3)))
.style("fill", "none")
.style("stroke", "steelblue");
svg.append("path")
.datum(data)
.attr("d", line.curve(d3.curveLinear))
.style("fill", "none")
.style("stroke", "black");
</script>
</body>
</html>