Странный вопрос с арифметикой (?)

Фон: я работаю над библиотекой для создания экрана с низким разрешением.

Теперь я хотел протестировать его простой демонстрацией - он должен рисовать радиальный градиент вокруг курсора.

Я думаю, что я получил математику правильно, и она работает, за исключением случаев, когда вы перемещаете мышь в левый нижний угол.

Я пробовал печатать цифры, меняя порядок и все, но не могу найти причину.

Вот также скрипт: https://jsfiddle.net/to5qfk7o/

var size = 16; // number of pixels

var lo = new Lores('#board', size, size);

// DRAWING FUNCTION
setInterval(function () {
    // Mouse coords
    var m_x = lo.mouse.x;
    var m_y = lo.mouse.y;
    
    // print where is mouse - for debug
    console.log(m_x + "," + m_y);
    
    // for all pixels on screen
    for (var x = 0; x < size; x++) {
        for (var y = 0; y < size; y++) {
            
            // mouse distance from this pixel
            var distance = (Math.sqrt((m_x - x) * (m_x - x) + (m_y - y) * (m_y - y)));
            // convert: 0..255, "size"..0
            var color = 255 - Math.floor((255 / size) * distance);
            
            // set color
            if (color < 0) {
                lo.set(y, x, 'black');
            } else {
                lo.set(x, y, 'rgb(' + color + ', 0, 0)');
            }
        }
    }
    
}, 100);




// ---- LIBRARY CODE -----

function Lores(selector, width, height) {
	this.boardElem = document.querySelector(selector);
	this.boardElem.className += ' lores-screen';

	this.grid = [];

	this.mouse = {
		inside: false,
		x: 0,
		y: 0 // position rounded to nearest board "pixel"
	};

	this.width = width;
	this.height = height;

	if (this.boardElem === null) {
		console.error('No such element!');
		return;
	}

	if (width <= 0 || height <= 0) {
		console.error('Dimensions must be positive!');
		return;
	}

	// Inject a style block for the sizes
	var css = selector + ' > div {height:' + (100 / height) + '%}';
	css += selector + ' > div > div {width:' + (100 / width) + '%}';
	var style = document.createElement('style');
	style.type = 'text/css';
	if (style.styleSheet) {
		style.styleSheet.cssText = css;
	} else {
		style.appendChild(document.createTextNode(css));
	}
	document.head.appendChild(style);


	var frag = document.createDocumentFragment();

	// Create the grid
	for (var i = height; i > 0; i--) {
		var rowElem = document.createElement('div');
		rowElem.dataset.y = i;

		var row = [];

		for (var j = width; j > 0; j--) {
			var cellElem = document.createElement('div');
			cellElem.dataset.x = j;

			rowElem.appendChild(cellElem);
			row.push(cellElem);
		}

		frag.appendChild(rowElem);
		this.grid.push(row);
	}

	this.boardElem.appendChild(frag);

	console.log('yo');

	var self = this;

	// add mouse listener
	document.addEventListener('mousemove', function (e) {
		var rect = self.boardElem.getBoundingClientRect();

		var x = (self.width * (e.clientX - rect.left)) / rect.width;
		var y = (self.height * (e.clientY - rect.top)) / rect.height;

		self.mouse.x = Math.floor(x);
		self.mouse.y = Math.floor(y);

		self.mouse.inside = (x >= 0 && x < self.width && y >= 0 && y < self.height);
	}, false);
}

Lores.prototype.set = function (x, y, color) {
	if (x < 0 || x >= this.width || y < 0 || y >= this.height) return;
	this.grid[y][x].style.backgroundColor = color;
};
#board {    
    margin: 0 auto;    
    width: 128px;    
    height: 128px;    
    outline: 1px solid black;    
}

#board > div:nth-child(odd) > div:nth-child(odd) {
    background: #eee        
}

#board > div:nth-child(even) > div:nth-child(even) {
    background: #eee
}

.lores-screen {    
    display: block;    
    -webkit-touch-callout: none;    
    -webkit-user-select: none;    
    -khtml-user-select: none;    
    -moz-user-select: none;    
    -ms-user-select: none;    
    user-select: none;        
}

.lores-screen, .lores-screen * {    
    white-space: nowrap;    
    padding: 0;    
}

.lores-screen * {    
    margin: 0        
}

.lores-screen > div {    
    display: block;    
}

.lores-screen > div > div {    
    display: inline-block;    
    vertical-align: top;    
    height: 100%;    
}
<div id="board"></div>

Ответ 1

Проблема заключается в простой опечатке в вашем выражении if. У вас есть x и y, смешанные в set вашей первой ветки. Сказав это, мы можем полностью ликвидировать ветвь. Простой Math.max(0, ...) по умолчанию будет черным.

Измените следующее:

var color = 255 - Math.floor((255 / size) * distance);

// set color
if (color < 0) {
    lo.set(y, x, 'black');
} else {
    lo.set(x, y, 'rgb(' + color + ', 0, 0)');
}

к

var color = Math.max(0, 255-Math.floor((255 / size) * distance));

lo.set(x, y, 'rgb(' + color + ', 0, 0)');

jsfiddle

Ответ 2

изменить

// set color
if (color < 0) {
    lo.set(y, x, 'black');
} else {
    lo.set(x, y, 'rgb(' + color + ', 0, 0)');
}

к

// set color
lo.set(x, y, 'rgb(' + Math.max(color, 0) + ', 0, 0)');

https://jsfiddle.net/hrvqa457/