Created
January 29, 2013 15:52
-
-
Save desandro/4665262 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>quad limit</title> | |
<style> | |
body { | |
font-family: sans-serif; | |
background: #DDD; | |
} | |
canvas { | |
background: white; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>quad limit</h1> | |
<canvas></canvas> | |
<script> | |
var w = 600; | |
var h = 600; | |
var canvas, ctx; | |
const PI = Math.PI; | |
const TWO_PI = PI * 2; | |
var max = 550; | |
// where the value will cap off, [ 0 - 1 ] | |
var limit = 400; | |
// where the curve will start, relative to the length of the angle, [ 0 - 1 ] | |
var startCurve = 220; | |
var startCurvePoint = { | |
x: startCurve, | |
y: startCurve | |
}; | |
var cornerPoint = { | |
x: limit, | |
y: limit | |
}; | |
var endCurvePoint = { | |
x: max, | |
y: limit | |
}; | |
function circle( point, color ) { | |
ctx.strokeStyle = color || 'black'; | |
ctx.beginPath(); | |
ctx.arc( point.x, point.y, 5, 0, Math.PI * 2 ); | |
ctx.stroke(); | |
} | |
function line( pA, pB, color ) { | |
ctx.strokeStyle = color || 'black'; | |
ctx.beginPath(); | |
ctx.moveTo( pA.x, pA.y ) | |
ctx.lineTo( pB.x, pB.y ) | |
ctx.stroke(); | |
} | |
// get point between pointA & pointB, i | |
function getLerpPoint( pA, pB, i ) { | |
return { | |
x: ( pB.x - pA.x ) * i + pA.x, | |
y: ( pB.y - pA.y ) * i + pA.y | |
}; | |
} | |
function lerp( a, b, i ) { | |
return ( b - a ) * i + a; | |
} | |
function render( x ) { | |
ctx.clearRect( 0, 0, w, h ); | |
ctx.lineWidth = 1; | |
// circle for event | |
ctx.lineWidth = 1; | |
circle( { x: x, y: x }, '#0F0') | |
// line to the point where the curve begins | |
line( { x: 0, y: 0 }, startCurvePoint, '#AAF' ); | |
// line from the point where the curve begins, to the max | |
line( startCurvePoint, cornerPoint, '#AAF' ); | |
// line to the max, to the end | |
line( cornerPoint, { x: w, y: limit }, '#AAF' ); | |
// draw circle at where curve begins and ends | |
circle( startCurvePoint, '#FAA'); | |
circle( endCurvePoint, '#FAA'); | |
// var x = 0.5; | |
var y; | |
// var i = Math.max( 0, (x - startCurve) / (limit - startCurve) ); | |
// | |
// console.log( i ); | |
// | |
// // point on first line segment | |
// var sp1 = getLerpPoint( startCurvePoint, cornerPoint, i ); | |
// | |
// circle( sp1, '#F90' ); | |
// // point on second line segment | |
// var sp2 = getLerpPoint( cornerPoint, endCurvePoint, i ); | |
// circle( sp2, '#F90' ); | |
// // draw a tangent line on the curve | |
// line( sp1, sp2, '#F90' ); | |
// | |
// | |
// // render quad curve | |
ctx.lineWidth = 1; | |
ctx.strokeStyle = 'hsla( 0, 100%, 50%, 0.5 )'; | |
ctx.beginPath(); | |
ctx.moveTo( startCurvePoint.x, startCurvePoint.y ); | |
ctx.quadraticCurveTo( cornerPoint.x, cornerPoint.y, endCurvePoint.x, endCurvePoint.y ) | |
ctx.stroke(); | |
// y value with quadracticCurve limited | |
var ay = x; | |
if ( x > max ) { | |
// if value is more than max, cap it at the limit | |
ay = limit; | |
} else if ( x > startCurve ) { | |
// within curve, let's get y value | |
// thx to Wes Dimiceli for figuring the math all out | |
var denom = max - limit * 2 + startCurve; | |
// prevent divide by 0 | |
denom = denom === 0 ? 1 : denom; | |
var a = ( limit - startCurve ) / denom; | |
var b = Math.sqrt( ( x - startCurve ) / denom + a * a ); | |
var i1 = b - a; | |
var i2 = -b - a; | |
// since sqrt can be +/-, use value that is less than 1 | |
var i = i1 <= 1 ? i1 : i2; | |
// position | |
var sp1y = lerp( startCurve, limit, i ); | |
circle( | |
{ x: sp1y, y: sp1y }, | |
'#FA0' | |
); | |
// lerp it again to get the actual y value | |
ay = lerp( sp1y, limit, i ); | |
ctx.strokeStyle = '#FA0'; | |
circle( | |
{ x: lerp( limit, max, i ), y: limit }, | |
'#FA0' | |
); | |
} | |
// console.log( ~~(ay), ~~(y)) | |
// line( { x: 0, y: ay }, { x: w, y: ay }, 'hsla( 240, 100%, 50%, 0.2 )') | |
// vertical line | |
line( { x: x, y: 0 }, { x: x, y: h }, 'hsla( 240, 100%, 50%, 0.2 )') | |
// circle( { x: x * w, y: y }, 'hsla( 240, 100%, 50%, 0.5 )' ); | |
// point on the quad curve | |
ctx.lineWidth = 2; | |
circle( { x: x, y: ay }, '#D00' ); | |
// circle({ x: x * w, y: ay } ); | |
} | |
console.log( max - limit * 2 + startCurve, max, limit, startCurve ); | |
function handleMousemove( event ) { | |
var x = event.pageX - event.target.offsetLeft; | |
// console.log( x ); | |
render( x ) | |
} | |
function init() { | |
canvas = document.getElementsByTagName('canvas')[0]; | |
canvas.width = w; | |
canvas.height = h; | |
ctx = canvas.getContext('2d'); | |
render( 0.5 ); | |
canvas.addEventListener( 'mousemove', handleMousemove, false ) | |
} | |
document.addEventListener( 'DOMContentLoaded', init, false); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment