Skip to content

Instantly share code, notes, and snippets.

@desandro
Created January 29, 2013 15:52
Show Gist options
  • Save desandro/4665262 to your computer and use it in GitHub Desktop.
Save desandro/4665262 to your computer and use it in GitHub Desktop.
<!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