Closest point on a line segment

HTML

<script src="https://rawgithub.com/soulwire/sketch.js/master/js/sketch.js"></script>

CSS

html, body {
    margin: 0;
}

JavaScript

var A, B;

function project( p, a, b ) {
    
    var atob = { x: b.x - a.x, y: b.y - a.y };
    var atop = { x: p.x - a.x, y: p.y - a.y };
    var len = atob.x * atob.x + atob.y * atob.y;
    var dot = atop.x * atob.x + atop.y * atob.y;
    var t = min( 1, max( 0, dot / len ) );

    dot = ( b.x - a.x ) * ( p.y - a.y ) - ( b.y - a.y ) * ( p.x - a.x );
    
    return {
        point: {
            x: a.x + atob.x * t,
            y: a.y + atob.y * t
        },
        left: dot < 1,
        dot: dot,
        t: t
    };
}

function makeLine( mx, my ) {
    A = { x: random( 20, mx - 40 ), y: random( 20, my - 40 ) };
    B = { x: random( 20, mx - 40 ), y: random( 20, my - 40 ) };
}

Sketch.create({
    setup: function() {
        makeLine( this.width, this.height );
    },
    draw: function() {
        
        // render line
        
        this.beginPath();
        this.moveTo( A.x, A.y );
        this.lineTo( B.x, B.y );
        this.stroke();
        
        this.fillText( 'A', A.x, A.y );
        this.fillText( 'B', B.x, B.y );
        
        // render point
        
        this.beginPath();
        this.arc( this.mouse.x, this.mouse.y, 5, 0, TWO_PI );
        this.stroke();
        
        // nearest point
        
        var data = project( this.mouse, A, B );

        this.beginPath();
        this.arc( data.point.x, data.point.y, 5, 0, TWO_PI );
        this.stroke();
        
        this.fillText( 'dot: ' + data.left, data.point.x + 10, data.point.y - 12 );
        this.fillText( 'data: ' + data.dot.toFixed(3), data.point.x + 10, data.point.y );
        this.fillText( 't: ' + data.t.toFixed(3), data.point.x + 10, data.point.y + 12 );
    },
    click: function() {
        makeLine( this.width, this.height );
    }
});