JSFiddle - React, Tailwind, and code Playground

by Matthew Vasallo

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
<canvas id="myCanvas" height="400px" width="600px" ></canvas>

JavaScript

$(document).ready(function() {

    var canvas = $("#myCanvas");
    var pos    = canvas.offset();
    var canvasLeft = pos.left;
    var canvasTop  = pos.top;
    var ctx = canvas.get(0).getContext("2d");
    var ballColor = "rgb(63,127,191)";
    var canvasWidth = canvas.width();
    var canvasHeight = canvas.height();

    var ballRadius = 20;

    var columns = [];
    var colDx   = Math.floor(canvasWidth / 6);
    var colOffset = 80;
    var colSlack = colDx/2;

    var drawGrid = function() {
        var dx = Math.floor((canvasHeight - 20) / 4);
        var ht = canvasHeight - 2;

        ctx.font = "14px Sans";
        ctx.lineWidth = 1;
        ctx.strokeStyle = "lightgray";
        var lineStart = 2 + ctx.measureText("100%").width;
        for (var i = 0; i < 5; i++) {
            ctx.fillText(String(i * 25).padStart(3, ' ') + "%", 2, ht);
            ctx.moveTo(lineStart, ht);
            ctx.lineTo(canvasWidth, ht);
            ctx.stroke();
            ht -= dx;
        }
    };

    var addCircles2Column = function(colNo, cnt, data) {
        var col = [];
        var score;
        if (data) {
            cnt = data.length;
        }
        for (var i = cnt - 1; i >= 0; i--) {
            if (data) {
                score = data[i];
            } else {
                score = Math.floor(Math.random()*100);
            }
            var item = _.find(col, function(x) {return x.score === score});
            if (!item) {
                item = {score: score, count: 0};
                col.push(item);
            }
            item.count++;
        }

        columns[colNo] = col;
    };

    function whichItem(evt) {
        var x = evt.pageX - canvasLeft;
        var y = evt.pageY - canvasTop;

        var colNo = Math.floor((x - colOffset + colSlack) / colDx);
        if (colNo < 0 || colNo >= columns.length) {
            return null;
        }

        var col  = columns[colNo];
        var best = null;
        var min  = 1000;
        var...