Last active
August 29, 2015 14:27
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Also, https://jsfiddle.net/6pze455n/