Skip to content

Instantly share code, notes, and snippets.

@cawhitworth
Last active August 29, 2015 14:27
Show Gist options
  • Save cawhitworth/b8732dae942f9da2f3d8 to your computer and use it in GitHub Desktop.
Save cawhitworth/b8732dae942f9da2f3d8 to your computer and use it in GitHub Desktop.
Bezier curves (1st, 2nd and 3rd order) in JavaScript on an HTML canvas
<html>
<body>
<canvas id="screen" style="border:1px solid #000" width=640 height=480 />
</body>
<script type="text/javascript">
// Demonstration of bezier curves by recursive definition
// For the purposes of this, a point is an object with x and y members
var c = document.getElementById("screen");
var ctx = c.getContext("2d");
// Linearly interpolate between a and b
var lerp = function(a, b, t) {
return a + t * (b - a);
};
// Linearly interpolate between two points
var lerpPt = function(p0, p1, t) {
return {
x: lerp(p0.x, p1.x, t),
y: lerp(p0.y, p1.y, t)
};
};
// first-order - literally just lerping between two points
var firstOrder = function(p0, p1) {
return function(t) {
return lerpPt(p0, p1, t);
};
};
// second order - lerp between two first-order functions
var secondOrder = function(p0, p1, p2) {
var f1 = firstOrder(p0, p1);
var f2 = firstOrder(p1, p2);
return function(t) {
var pf1 = f1(t);
var pf2 = f2(t);
return lerpPt(pf1, pf2, t);
};
};
// third order - lerp between two second-order functions
var thirdOrder = function(p0, p1, p2, p3) {
var f1 = secondOrder(p0, p1, p2);
var f2 = secondOrder(p1, p2, p3);
return function(t) {
var pf1 = f1(t);
var pf2 = f2(t);
return lerpPt(pf1, pf2, t);
};
};
var drawCurve = function(ctx, bezier_function, origin) {
ctx.moveTo(origin.x, origin.y);
// If we go from 0 to 1 in 1/steps increments, we run into FP rounding
// errors; this ensures we always get a complete curve
var steps = 100;
for(t = 0; t <= steps; t += 1)
{
var pt = bezier_function(t / steps);
ctx.lineTo(pt.x, pt.y);
}
};
var p0 = { x: 100, y: 100 };
var p1 = { x: 400, y: 400 };
var p2 = { x: 500, y: 100 };
var p3 = { x: 100, y: 550 };
var first = firstOrder(p0, p1);
var second = secondOrder(p0, p2, p1)
var third = thirdOrder(p0, p2, p3, p1);
drawCurve(ctx, first, p0);
drawCurve(ctx, second, p0);
drawCurve(ctx, third, p0);
ctx.stroke();
</script>
</html>
@cawhitworth
Copy link
Author

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