Dynamic Quadratic Curve

HTML

<label for="fInput">Curve Factor</label>
<input id="fInput" type="text" value="0.5"/>
<label for="mInput">Midpoint Factor</label>
<input id="mInput" type="text" value="0.5"/>
<canvas id="canvas" width="500" height="500"></canvas>

JavaScript

var canvas = document.getElementById('canvas');
var fInput = document.getElementById('fInput');
var mInput = document.getElementById('mInput');
var ctx = canvas.getContext('2d');
var mouse = {
  x: 100,
  y: 100
};

function arc(x, y, radius, thickness, colour) {
  ctx.strokeStyle = colour || '#FF0000';
  ctx.lineWidth = thickness || 3;
  ctx.beginPath();
  ctx.arc(x, y, radius , 0, Math.PI * 2);
  ctx.closePath();
  ctx.stroke();
}

function curve(x1, y1, x2, y2, cx, cy, colour, thickness) {
  ctx.strokeStyle = colour || '#FF0000';
  ctx.lineWidth = thickness || 3;
  ctx.beginPath();
  ctx.moveTo(x1, y1);
  ctx.quadraticCurveTo(cx, cy, x2, y2);
  ctx.stroke();
}
    
function draw(x1, y1, x2, y2, radius) {
  
  var dx, dy, // delta
      cx, cy, // control point
      mx, my, // mid point
      x3, y3, // outer point
      length, // hypotenuse
      offset, // control offset
      theta;
  
  // Compute mid point
  dx = x2 - x1;
  dy = y2 - y1;
  
  mx = x1 + dx * parseFloat( mInput.value );
  my = y1 + dy * parseFloat( mInput.value );
  
  arc(x1, y1, 5, 1, '#00FF00');
  arc(mx, my, 5, 1, '#00FF00');
  
  // Compute control point as a function of length
  
  length = Math.sqrt(dx * dx + dy * dy);
  offset = length * parseFloat( fInput.value );
  theta = Math.atan2(dy, dx) - Math.PI / 2;
  
  cx = mx + Math.cos(theta) * offset;
  cy = my + Math.sin(theta) * offset;
  
  arc(cx, cy, 5, 1, '#00FFFF');
  
  // Angle between control & end point
  dx = x2 - cx;
  dy = y2 - cy;
  theta = Math.atan2(dy, dx);
  
  // Find arrow point
  offset = radius + 10;
  x3 = x2 - Math.cos(theta) * offset;
  y3 = y2 - Math.sin(theta) * offset;
  
  // Draw curve
  curve(x1, y1, x3, y3, cx, cy, '#0000FF', 2);
  
  // Draw circle
  arc(x2, y2, radius);
    
}

function refresh() {
  canvas.width = Math.max(window.innerWidth, 500);
  canvas.height = Math.max(window.innerHeight, 500);
  draw(10, 10, mouse.x, mouse.y, 20);
}

fInput.addEventListener('input', function(e){
 ...