<html> <canvas id="bezier" width="336" height="336"> </canvas> <form> <label for="x1">x1 = </label><input onchange="updateCanvas();" type="text" maxlength=6 id="x1" value="0.79" class='field'> <label for="y1">y1 = </label><input onchange="updateCanvas();return true;" type="text" maxlength=6 id="y1" value="0.33" class='field'> <label for="x2">x2 = </label><input onchange="updateCanvas();return true;" type="text" maxlength=6 id="x2" value="0.14" class='field'> <label for="y2">y2 = </label><input onchange="updateCanvas();return true;" type="text" maxlength=6 id="y2" value="0.53" class='field'> <br> <output id="output">Log</output> </form> </html>
.field { width: 40px; }
function updateCanvas() { var x1 = document.getElementById('x1').value; var y1 = document.getElementById('y1').value; var x2 = document.getElementById('x2').value; var y2 = document.getElementById('y2').value; drawBezierCurve(x1, y1, x2, y2); } const radius = 4; // Place needed to draw the rulers const rulers = 30.5; const margin = 10.5; const basic_scale_size = 5; // Size of 0.1 tick on the rulers var scaling; //LIMITATION: scaling is computed once: if canvas.height/canvas.width change it won't be recalculated var dragSM = 0; // Drag state machine: 0 = nodrag, others = object being dragged function initCanvas() { // get the canvas element using the DOM var canvas = document.getElementById('bezier'); // Make sure we don't execute when canvas isn't supported if (canvas.getContext) { // use getContext to use the canvas for drawing var ctx = canvas.getContext('2d'); scaling = Math.min(canvas.height - rulers - margin, canvas.width - rulers - margin); canvas.onmousedown = mouseDown; canvas.onmouseup = mouseUp; } else { alert('You need Safari or Firefox 1.5+ to see this demo.'); } } function cX(x) { return x * scaling + rulers; } function reverseX(x) { return (x - rulers) / scaling; } function lX(x) { //Used when drawing vertical lines to prevent subpixel blur var result = cX(x); return Math.round(result) == result ? result + 0.5 : result; } function cY(y) { return (1 - y) * scaling + margin; } function reverseY(y) { return (margin - y) / scaling + 1; } function lY(y) { // Used when drawing horizontal lines to prevent subpixel blur var result = cY(y); return Math.round(result) == result ? result + 0.5 : result; } function drawBezierCurve(x1, y1, x2, y2) { // get the canvas element using the DOM var canvas = document.getElementById('bezier'); // Make sure we don't execute when canvas isn't supported if (canvas.getContext) { // use getContext to use the canvas for drawing var ctx = canvas.getContext('2d'); // Clear canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Draw the rulers ctx.beginPath(); ctx.strokeStyle = "black"; // Draw the Y axis ctx.moveTo(cX(0), cY(0)); ctx.lineTo(cX(1), cY(0)); ctx.textAlign = "right"; for (var i = 0.1; i <= 1; i = i + 0.1) { ctx.moveTo(-basic_scale_size + cX(0), lY(i)); if ((i == 0.5) || (i > 0.9)) { ctx.moveTo(-2 * basic_scale_size + cX(0), lY(i)); ctx.fillText(Math.round(i * 10) / 10, -3 * basic_scale_size + cX(0), cY(i) + 4); // Limitation the constant 4 should be font size dependant } ctx.lineTo(cX(0), lY(i)); } ctx.stroke(); ctx.closePath(); ctx.beginPath(); // Draw the Y axis label ctx.save(); ctx.rotate(-Math.PI / 2); ctx.textAlign = "left"; ctx.fillText("Output (Value Ratio)", -cY(0), -3 * basic_scale_size + cX(0)); ctx.restore(); // Draw the X axis ctx.moveTo(cX(0), cY(0)); ctx.lineTo(cX(0), cY(1)); ctx.textAlign = "center"; for (i = 0.1; i <= 1; i = i + 0.1) { ctx.moveTo(lX(i), basic_scale_size + cY(0)); if ((i == 0.5) || (i > 0.9)) { ctx.moveTo(lX(i), 2 * basic_scale_size + cY(0)); ctx.fillText(Math.round(i * 10) / 10, cX(i), 4 * basic_scale_size + cY(0)); // Limitation the constant 4 should be dependant of the font size } ctx.lineTo(lX(i), cY(0)); } // Draw the X axis label ctx.textAlign = "left"; ctx.fillText("Input (Time Duration Ratio)", cX(0), 4 * basic_scale_size + cY(0)); // Limitation the constant 4 should be dependant of the font size ctx.stroke(); ctx.closePath(); // Draw the Bézier Curve ctx.beginPath(); ctx.moveTo(cX(0), cY(0)); ctx.strokeStyle = 'blue'; ctx.bezierCurveTo(cX(x1), cY(y1), cX(x2), cY(y2), cX(1), cY(1)); ctx.stroke(); ctx.closePath(); // Draw the P2 point (with a line to P0) ctx.beginPath(); ctx.strokeStyle = 'red'; ctx.moveTo(cX(x1), cY(y1)); ctx.lineTo(cX(0), cY(0)); ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(cX(x1), cY(y1)); ctx.arc(cX(x1), cY(y1), radius, 0, 2 * Math.PI); ctx.stroke(); ctx.fillStyle = 'white'; ctx.fill(); ctx.closePath(); // Draw the P3 point (with a line to P1) ctx.beginPath(); ctx.strokeStyle = 'red'; ctx.moveTo(cX(x2), cY(y2)); ctx.lineTo(cX(1), cY(1)); ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(cX(x2), cY(y2)); ctx.arc(cX(x2), cY(y2), radius, 0, 2 * Math.PI); ctx.stroke(); ctx.fill(); ctx.closePath(); // Draw the P1(1,1) point (with dashed hints) ctx.beginPath(); ctx.moveTo(cX(1), cY(1)); ctx.strokeStyle = 'lightgrey'; ctx.lineTo(cX(0), cY(1)); ctx.moveTo(cX(1), cY(1)); ctx.lineTo(cX(1), cY(0)); ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.strokeStyle = "black"; ctx.fillStyle = "black"; ctx.arc(cX(1), cY(1), radius, 0, 2 * Math.PI); ctx.fill(); ctx.stroke(); ctx.closePath(); // Draw the P0(0,0) point ctx.beginPath(); ctx.arc(cX(0), cY(0), radius, 0, 2 * Math.PI); ctx.fill(); ctx.stroke(); ctx.closePath(); } else { alert('You need Safari or Firefox 1.5+ to see this demo.'); } } function mouseDown(e) { var canvas = document.getElementById('bezier'); var x1 = cX(document.getElementById('x1').value); var y1 = cY(document.getElementById('y1').value); var x = e.pageX - canvas.offsetLeft; var y = e.pageY - canvas.offsetTop; var output = document.getElementById('output'); output.value = "(" + x + "," + y + ") should be (" + x1 + "," + y1 + ")"; if ((x1 + radius >= x) && (x1 - radius <= x) && (y1 + radius >= y) && (y1 - radius <= y)) { var output = document.getElementById('output'); output.value = "P1!"; dragSM = 1; } var x2 = cX(document.getElementById('x2').value); var y2 = cY(document.getElementById('y2').value); if ((x2 + radius >= x) && (x2 - radius <= x) && (y2 + radius >= y) && (y2 - radius <= y)) { var output = document.getElementById('output'); output.value = "P2!"; dragSM = 2; } // If we are starting a drag if (dragSM != 0) { canvas.onmousemove = mouseMove; } } function mouseUp(e) { var output = document.getElementById('output'); output.value = "Mouse up!"; dragSM = 0; canvas.onmousemove = null; } function mouseMove(e) { if (dragSM != 0) { var canvas = document.getElementById('bezier'); var x = e.pageX - canvas.offsetLeft; var y = e.pageY - canvas.offsetTop; var output = document.getElementById('output'); output.value = "Drag!"; if (dragSM == 1) { var x1 = document.getElementById('x1'); var y1 = document.getElementById('y1'); x1.value = reverseX(x); x1.value = Math.round(x1.value * 10000) / 10000; y1.value = reverseY(y); y1.value = Math.round(y1.value * 10000) / 10000; if (x1.value < 0) { x1.value = 0; } if (x1.value > 1) { x1.value = 1; } } else if (dragSM == 2) { var x2 = document.getElementById('x2'); var y2 = document.getElementById('y2'); x2.value = reverseX(x); x2.value = Math.round(x2.value * 10000) / 10000; y2.value = reverseY(y); y2.value = Math.round(y2.value * 10000) / 10000; if (x2.value < 0) { x2.value = 0; } if (x2.value > 1) { x2.value = 1; } } updateCanvas(); } } initCanvas(); updateCanvas();
Draft
This page is not complete.
This is a sample tool; it lets you edit Bezier curves. This is not really yet a useful tool, but will be!