JSFiddle - React, Tailwind, and code Playground

by jcubed111

HTML

<canvas id="main" width=500 height=500></canvas>

JavaScript

const Vec2 = (x, y) => [x, y];
function *getLinePixelsThin([x0, y0], [x1, y1]) {
    // get a smooth pixel line connecting start and end
    // https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

    const dx = Math.abs(x1 - x0);
    const sx = x0 < x1 ? 1 : -1;
    const dy = -Math.abs(y1 - y0);
    const sy = y0 < y1 ? 1 : -1;
    let error = dx + dy;
    
    const totalSteps = dx - dy;
    let steps = 0;

	console.log('start');
    while(true) {
        const e2 = 2 * error;
        const isHalf = steps >= (totalSteps >> 1);
        console.log(x0, y0, e2, dy, dx, steps, isHalf);
        
        yield Vec2(x0, y0);

        if(x0 == x1 && y0 == y1) break;

        if(e2 > dy || (isHalf && e2 == dy)) {
            if(x0 == x1) break;
            error += dy;
            x0 += sx;
            steps++;
        }
        if(e2 < dx || (!isHalf && e2 == dx)) {
            if(y0 == y1) break;
            error += dx;
            y0 += sy;
            steps++;
        }
    }
}


const canvas = document.getElementById('main');
const ctx = canvas.getContext('2d');

ctx.setTransform(20, 0, 0, -20, 0, 500);
ctx.lineWidth = 0.1;

function cb(e, debug=false) {
	ctx.clearRect(0, 0, 100, 100);
    
    ctx.strokeStyle = '#ddd';
    for(let i = 0; i < 30; i++) {
    	ctx.strokeRect(i, 0, 1, 30);
    	ctx.strokeRect(0, i, 30, 1);
    }
    
    const {top, left, height} = canvas.getBoundingClientRect();
    const mousePos = Vec2(
    	Math.floor((e.clientX - left) / 20),
        Math.floor((height - (e.clientY - top)) / 20),
    );
    
    if(debug) debugger;
    
    for(const pos of getLinePixelsThin([12, 12], mousePos)) {
    	ctx.fillRect(...pos, 1, 1);
    }
    
    ctx.strokeStyle = '#f00';
    ctx.strokeRect(...mousePos, 1, 1);
}

canvas.addEventListener('mousemove', cb);
canvas.addEventListener('click', e => cb(e, true));