2015-06-15 16 views
12

Sfondo: sto lavorando su una libreria per la creazione di una visualizzazione "a bassa risoluzione".Strano problema con aritmetica (?)

Ora volevo testarlo con una semplice demo: dovrebbe disegnare un gradiente radiale attorno al cursore.

Penso di aver ragione e funziona correttamente, tranne quando si sposta il mouse nell'angolo in basso a sinistra.

Ho provato a stampare i numeri, cambiando l'ordine e tutto, ma non riesco a trovare la causa.

Ecco anche un violino: 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) { 
 
\t this.boardElem = document.querySelector(selector); 
 
\t this.boardElem.className += ' lores-screen'; 
 

 
\t this.grid = []; 
 

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

 
\t this.width = width; 
 
\t this.height = height; 
 

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

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

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

 

 
\t var frag = document.createDocumentFragment(); 
 

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

 
\t \t var row = []; 
 

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

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

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

 
\t this.boardElem.appendChild(frag); 
 

 
\t console.log('yo'); 
 

 
\t var self = this; 
 

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

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

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

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

 
Lores.prototype.set = function (x, y, color) { 
 
\t if (x < 0 || x >= this.width || y < 0 || y >= this.height) return; 
 
\t 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>

Potrebbe essere qualcosa di banale, davvero non lo so. Grazie!

+0

considerare l'utilizzo di [ 'requestAnimationFrame'] (http://creativejs.com/resources/requestanimationframe/) invece di' setInterval' per una maggiore efficienza. – Blazemonger

+0

Lo so, questo era solo per il test. – MightyPork

risposta

10

Il problema è un semplice errore di battitura nell'istruzione if. Hai mescolato x e y nel set del tuo primo ramo. Detto questo, possiamo eliminare completamente il ramo. Un semplice Math.max(0, ...) lo imposterà in nero.

cambiare la seguente:

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)'); 
} 

a

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

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

jsfiddle

+1

In realtà, funziona in modo opposto a quello che ci si aspetta ... – Blazemonger

+1

Sì, invertirà l'effetto .. – EJTH

+2

Ma sei sulla strada giusta. Suggerirei: 'var color = Math.max (0, 255-Math.floor ((255/size) * distance));' – Blazemonger

5

cambiamento

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

a

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

https://jsfiddle.net/hrvqa457/

Problemi correlati