Skip to content

Instantly share code, notes, and snippets.

@mingzhi22
Created July 14, 2015 02:43
Show Gist options
  • Save mingzhi22/be3324ffd9765687ea2f to your computer and use it in GitHub Desktop.
Save mingzhi22/be3324ffd9765687ea2f to your computer and use it in GitHub Desktop.
绘制光滑曲线
<div class="svg-container">
<svg width="100%" height="100%">
<path class="spline" d="" style="fill: none; stroke: red; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1px;"></path>
<g class="dots"></g>
</svg>
</div>
function getFirstControlPoints(rhs) {
var n = rhs.length,
x = [], // Solution vector.
tmp = [], // Temp workspace.
b = 2.0,
i;
x[0] = rhs[0] / b;
for (i = 1; i < n; i++) { // Decomposition and forward substitution.
tmp[i] = 1 / b;
b = (i < n - 1 ? 4.0 : 2.0) - tmp[i];
x[i] = (rhs[i] - x[i - 1]) / b;
}
for (i = 1; i < n; i++) {
x[n - i - 1] -= tmp[n - i] * x[n - i]; // Backsubstitution.
}
return x;
}
// 获取三次方贝塞尔曲线控制点坐标
function getCubicBezierCurvePoints(knots, firstControlPoints, secondControlPoints) {
var rhs = [],
n = knots.length - 1,
x, y, i;
if (n < 1) {
return;
}
// Set right hand side X values
for (i = 0; i < n - 1; ++i) {
rhs[i] = 4 * knots[i].x + 2 * knots[i + 1].x;
}
rhs[0] = knots[0].x + 2 * knots[1].x;
rhs[n - 1] = 3 * knots[n - 1].x;
// Get first control points X-values
x = getFirstControlPoints(rhs);
// Set right hand side Y values
for (i = 1; i < n - 1; ++i) {
rhs[i] = 4 * knots[i].y + 2 * knots[i + 1].y;
}
rhs[0] = knots[0].y + 2 * knots[1].y;
rhs[n - 1] = 3 * knots[n - 1].y;
// Get first control points Y-values
y = getFirstControlPoints(rhs);
for (i = 0; i < n; ++i) {
// First control point
firstControlPoints[i] = {
x: x[i],
y: y[i]
};
// Second control point
if (i < n - 1) {
secondControlPoints[i] = {
x: 2 * knots[i + 1].x - x[i + 1],
y: 2 * knots[i + 1].y - y[i + 1]
};
} else {
secondControlPoints[i] = {
x: (knots[n].x + x[n - 1]) / 2,
y: (knots[n].y + y[n - 1]) / 2
};
}
}
}
function getCubicBezierCurvePath(knots) {
var firstControlPoints = [],
secondControlPoints = [],
path = [];
getCubicBezierCurvePoints(knots, firstControlPoints, secondControlPoints);
for (var i = 0, len = knots.length; i < len; i++) {
if (i === 0) {
path.push(['M', knots[i].x, knots[i].y].join(' '));
} else {
var firstControlPoint = firstControlPoints[i - 1],
secondControlPoint = secondControlPoints[i - 1];
path.push([
'C', firstControlPoint.x, firstControlPoint.y, // 第一个控制点
secondControlPoint.x, secondControlPoint.y, // 第二个控制点
knots[i].x, knots[i].y // 实点
].join(' '));
}
}
return path.join(' ');
}
// 绘制节点
var points = [{
x: 0,
y: 20
}, {
x: 50,
y: 30
}, {
x: 100,
y: 100
}, {
x: 150,
y: 50
}, {
x: 200,
y: 70
}, {
x: 250,
y: 90
}, {
x: 300,
y: 120
}];
var dots = document.querySelector('.svg-container .dots');
for (var i = 0, len = points.length; i < len; i++) {
var xmlns = "http://www.w3.org/2000/svg",
circle = document.createElementNS(xmlns, 'circle');
var point = points[i];
circle.setAttribute('fill', 'green');
circle.setAttribute('r', '4');
circle.setAttribute('cx', point.x);
circle.setAttribute('cy', point.y);
dots.appendChild(circle);
}
var path = getCubicBezierCurvePath(points);
document.querySelector('.svg-container .spline').setAttribute('d', path);
.svg-container {
width: 300px;
height: 200px;
}

绘制光滑曲线

仅需给出若干关键点,即可绘制出一条「经过」这些关键点的光滑曲线

A Pen by Michael Zhou on CodePen.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment