Dibuje el flujo direccional en cuadrícula de lona HTML5 / a cubierta de la caja con respecto al tamaño y los límites definidos por el usuario -- javascript campo con jquery campo con array campo con graphics campo con canvas camp codereview Relacionados El problema

Draw directional flow on html5 canvas grid/checkboard with respect to user defined size and limits


1
vote

problema

Español

En última instancia, quiero poder dibujar un tablero de ajedrez (pared) de tamaño definido por el usuario. Esta pared está formada por azulejos de un tamaño definido por el usuario. Esta pared principal se puede dividir en varias secciones (salidas) dependientes de los límites definidos por el usuario. El flujo de datos se dibuja luego en cada salida individual (consulte el Ejemplo 2), no solo para toda la pared (Ejemplo 1).

Se proporcionó una solución elegante por el usuario @ Blindman67 que itera a través de cada baldosa en el mapa y establece su flujo en el orden del flujo. Esto funciona maravillosamente hasta que lo cambie para establecer un azulejo para que sea el final del flujo una vez que alcance el límite de una sola salida.

Si consulta el Ejemplo 3 Empiezo a agregar algunos sentencias extremadamente crudas si / else, si no se registran para verificar todas las posibilidades en los 8 flujos diferentes, configurando los extremos y comienzos de flujos, así como las direcciones de flecha manualmente. Esto es extremadamente descuidado y preferiría algo más similar a lo que está sucediendo en el Ejemplo 1, pero con un flujo de datos de trabajo dibujado para cada salida individual.

Aquí hay dos imágenes de lo que puedo hacer hasta ahora. Mirando la 2da imagen, verá que quiero poder completar las 3 salidas vacías restantes con sus respectivos flujos de datos.

Ejemplo 1 - Sin límites de salida

Ejemplo 2: flujos de datos faltantes

No sé si debería cambiar el límite de 'infinito' para ser los límites de las salidas aquí:

  const flows = {         none : -1,         right : 0,         down : 1,         left : 2,         up : 3,         end : 4,  // for end of flow         start : 5,  // for start         dirs : [[1,0],[0,1],[-1,0],[0,-1]], // x,y step for each direction         // Maps are used to workout the flow layout         // x,y is the starting position with 0 as top or left and 1 as bottom or right         // directions has an array for each direction. the first item is the travel         // direction and the second item is the max number of steps befor turning         map1 : { // top left start rigth, down, left, down              x : 0, y : 0,             directions : [[0,Infinity],[1,1],[2,Infinity],[1,1]],         },         map2 : {  // top right start, left, down, right, down              x : 1, y : 0,             directions : [[2,Infinity],[1,1],[0,Infinity],[1,1]],         },         map3 : {             x : 0, y : 1, // bottom left start, up, right, down, right             directions : [[3,Infinity],[0,1],[1,Infinity],[0,1]],         },         map4 : {             x : 1, y : 1, // bottom right start, up, left, down, left             directions : [[3,Infinity],[2,1],[1,Infinity],[2,1]],         },     }   

o si necesito editar el createflow (); Función para agregar un cheque para cada salida individual:

  // Creates flow map for tiles. flow maps are in flows as flow.map1, map2... etc function createFlow(tiles,flowMap){     var i = 0;     var prevtile, tile;     var count = 0;     var x = flowMap.x * (cols-1);     var y = flowMap.y * (rows-1);     var moving = true;     while(moving){         var ind = x + y * cols;         prevtile = tile;         var tile = tiles[ind];         var dir = flowMap.directions[i % flowMap.directions.length];         var nx = x + flows.dirs[dir[0]][0];         var ny = y + flows.dirs[dir[0]][1];         if(nx >= cols || nx >= outCols || nx < 0 || ny >= rows || ny >= outRows || ny < 0 || count >= dir[1]){//determine what tiles stop changing nx/ny/dir             i += 1;             dir = flowMap.directions[i % flowMap.directions.length];             nx = x + flows.dirs[dir[0]][0];             ny = y + flows.dirs[dir[0]][1];             if(nx >= cols || nx >= outCols || nx < 0 || ny >= rows || ny >= outRows || ny < 0){//determine where flow stops                 tile.flow = flows.end;                 break;             }             count = 0;         }         if(tile === undefined){             prevtile.flow = flows.end;             break;         }         if(prevtile === undefined){             tile.flow = flows.start;            }else{             tile.flow = dir[0];         }         count += 1;         x = nx;         y = ny;     } }   

Ejemplo 1 - Funciones de flujo correctamente, pero no hay límites de salida:

  9988776655544332  

Ejemplo 2: Funciones de flujo correctamente dentro de los límites de una sola salida.

  /** CreateImage.js begin **/  //wall size     var wallx = 500;     var wally = 500;          //output size     var outputx = 250;     var outputy = 250;          // tile size     var tilex = 25;     var tiley = 25;          // vars for output limits evenly divisible by tile size         var LCDoutputx = outputx;     var LCDoutputy = outputy;          //round down LCDoutputy to the next coordinate evenly divisible by a tile's y value.     if ((outputy % tiley) != 0){      LCDoutputy = (Math.floor(outputy/tiley))*tiley;        }     //round down LCDoutputx to the next coordinate evenly divisible by a tile's x value.     if ((outputx % tilex) != 0){      LCDoutputx = (Math.floor(outputx/tilex))*tilex;        }          // creates a blank image with 2d context     var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}          /** CreateImage.js end **/     var canvas = createImage(wallx, wally);     var ctx = canvas.ctx;     document.body.appendChild(canvas);          // constants for directions     const flows = {         none : -1,         right : 0,         down : 1,         left : 2,         up : 3,         end : 4,  // for end of flow         start : 5,  // for start         dirs : [[1,0],[0,1],[-1,0],[0,-1]], // x,y step for each direction         // Maps are used to workout the flow laoutputy         // x,y is the starting position with 0 as top or left and 1 as bottom or right         // directions has an array for each direction. the first item is the travel         // direction and the second item is the max number of steps befor turning         map1 : { // top left start rigth, down, left, down              x : 0, y : 0,             directions : [[0,Infinity],[1,1],[2,Infinity],[1,1]],         },         map2 : {  // top right start, left, down, right, down              x : 1, y : 0,             directions : [[2,Infinity],[1,1],[0,Infinity],[1,1]],         },         map3 : {             x : 0, y : 1, // bottom left start, up, right, down, right             directions : [[3,Infinity],[0,1],[1,Infinity],[0,1]],         },         map4 : {             x : 1, y : 1, // bottom right start, up, left, down, left             directions : [[3,Infinity],[2,1],[1,Infinity],[2,1]],         },     }     // colours     const col1 = "#FA6" //orng     const col2 = "#6AF" //l. blue     const col3 = "#03CEA4" //green     const col4 = "#FB4D3D" //red     const col5 = "#345995" //d.blue     var colA;     var colB;     // array of tiles     var tiles = [];     // number columns and rows     var rows;     var cols;     // number of outputs     var outputsW = Math.ceil(wallx/outputx);     var outputsH = Math.ceil(wally/outputy);     // number of cols/rows in each output     var outCols = Math.floor(outputx/tilex);     var outRows = Math.floor(outputy/tiley);     // reset or setup tiles     function reset(tiles){         tiles.length = 0;         rows = Math.floor(canvas.height / tiley);         cols = Math.floor(canvas.width / tilex);         for(var y = 0; y <= canvas.height-tiley; y+= tiley){ //changed < to <=              for(var x = 0; x <= canvas.width-tilex; x += tilex){ //changed < to <=            var d = (Math.floor(y / LCDoutputy) % 2 + Math.floor(x / LCDoutputx) % 2) % 2; //added LCDoutputt for output background color to work. Was outputy. The entire map's output background colors were off by one row, showing an extra row beyond what the limits should be.      //console.log("Y : "+y+" divided by Out Y Limit : "+outputy);            //console.log("Y result : "+Math.floor(y/outputy) % 2);            //console.log("X : "+x+" divided by Out X Limit : "+outputx);            //console.log("X result : "+Math.floor(x/outputx) % 2);            //console.log(d);                 var c = (Math.floor(y / tiley) % 2 + Math.floor(x / tilex) % 2) % 2;                 tiles.push({                     x,y,tilex,tiley,                     flow : flows.none,                     output : d ? (colA = col3, colB = col4) : (colA = col1, colB = col2),                     col : c ? colA : colB,                                      })             }             }     }     // Creates flow map for tiles. flow maps are in flows as flow.map1, map2... etc     function createFlow(tiles,flowMap){         var i = 0;         var prevtile, tile;         var count = 0;         var x = flowMap.x * (cols-1);         var y = flowMap.y * (rows-1);         var moving = true;         while(moving){             var ind = x + y * cols;             prevtile = tile;             var tile = tiles[ind];             var dir = flowMap.directions[i % flowMap.directions.length];             var nx = x + flows.dirs[dir[0]][0];             var ny = y + flows.dirs[dir[0]][1];             //console.log(count);             //console.log("I : "+i+" X , Y : "+x+" , "+y);             //console.log("IND : "+ind+" NX , NY : "+nx+" , "+ny);             //console.log("DIR : "+dir);             //console.log("Columns : "+cols+" Out Columns : "+outCols);             //console.log("Rows : "+rows+" Out Rows : "+outRows);             if(nx >= cols || nx >= outCols || nx < 0 || ny >= rows || ny >= outRows || ny < 0 || count >= dir[1]){//determine what tiles stop changing nx/ny/dir                 i += 1;                 dir = flowMap.directions[i % flowMap.directions.length];                 nx = x + flows.dirs[dir[0]][0];                 ny = y + flows.dirs[dir[0]][1];                 if(nx >= cols || nx >= outCols || nx < 0 || ny >= rows || ny >= outRows || ny < 0){//determine where flow stops                     tile.flow = flows.end;                     break;                 }                 count = 0;             }             if(tile === undefined){                 prevtile.flow = flows.end;                 break;             }             if(prevtile === undefined){                 tile.flow = flows.start;                }else{                 tile.flow = dir[0];             }             count += 1;             x = nx;             y = ny;         }     }          // draws the tiles     function draw(tiles){         function arrow(tile){             if(tile.flow === flows.none){                 return;             }             if (tilex<tiley) {              var step = tile.tilex * (1/4);             } else {           var step = tile.tiley * (1/4);                }             //var step = tile.tilex * (1/4);             var x = tile.x + tile.tilex -step;             var y = tile.y + step             ctx.strokeStyle = "white";             ctx.lineWidth = 2;             ctx.beginPath();             if(tile.flow === flows.end){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(-step / 2, -step / 2);                 ctx.lineTo(step / 2, step / 2);                 ctx.moveTo(step / 2, -step / 2);                 ctx.lineTo(-step / 2, step / 2);                                  ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(tile.flow === flows.start){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(step / 2, 0);                 ctx.arc(0,0, step / 2,0,Math.PI * 2);                 ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(tile.flow === flows.right){                 ctx.setTransform(1,0,0,1,x,y);             } else if(tile.flow === flows.left){                 ctx.setTransform(-1,0,0,1,x,y);             } else if(tile.flow === flows.down){                 ctx.setTransform(0,1,1,0,x,y);             } else if(tile.flow === flows.up){                 ctx.setTransform(0,-1,1,0,x,y);                 //ctx.setTransform(0,1,-1,0,0,0);             }             ctx.moveTo(-step / 2, 0);             ctx.lineTo(step / 2, 0);             ctx.moveTo(step / 4, -step / 4);             ctx.lineTo(step / 2, 0);             ctx.lineTo(step / 4, step / 4);             ctx.stroke();             ctx.setTransform(1,0,0,1,0,0);         }         ctx.clearRect(0,0,canvas.width,canvas.height)         var i = 0;         while(i < tiles.length){             var l = tiles[i++];             ctx.fillStyle = l.col             ctx.fillRect(l.x,l.y,l.tilex,l.tiley);             arrow(l);         }              }          var flowMaps = [flows.map1,flows.map2,flows.map3,flows.map4];     var currentFlow = 4;     function drawAll(){         reset(tiles);         draw(tiles);         //setTimeout(setFlow,1000);         setFlow();     }     function setFlow(){         createFlow(tiles,flowMaps[(currentFlow++) % flowMaps.length]);         draw(tiles);         //setTimeout(drawAll,4000); //comment out this line to stop map change cycle     }     drawAll();  

Ejemplo 3: Función de flujo totalmente faltada, pero da una idea de la flexibilidad que quiero con los campos definidos por el usuario

  /** CreateImage.js begin **/  //output size     var outputx = 256;     var outputy = 256;          // tile size     var tilex = 64;     var tiley = 64;          // rows & columns     var rows = 8;     var cols = 8;          // wall/map size dictated by rows/cols     wallx = tilex*cols;  wally = tiley*rows;                   // creates a blank image with 2d context     var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}          /** CreateImage.js end **/     var canvas = createImage(wallx, wally);     var ctx = canvas.ctx;     document.body.appendChild(canvas);          // constants for directions     const flows = {         none : -1,         right : 0,         down : 1,         left : 2,         up : 3,         end : 4,  // for end of flow         start : 5,  // for start         dirs : [[1,0],[0,1],[-1,0],[0,-1]], // x,y step for each direction         // Maps are used to workout the flow laoutputy         // x,y is the starting position with 0 as top or left and 1 as bottom or right         // directions has an array for each direction. the first item is the travel         // direction and the second item is the max number of steps befor turning         map1 : { // top left start rigth, down, left, down              x : 0, y : 0,             directions : [[0,Infinity],[1,1],[2,Infinity],[1,1]],         },         map2 : {  // top right start, left, down, right, down              x : 1, y : 0,             directions : [[2,Infinity],[1,1],[0,Infinity],[1,1]],         },         map3 : {             x : 0, y : 1, // bottom left start, right, up, left, up             directions : [[0,Infinity],[3,1],[2,Infinity],[3,1]],         },         map4 : {             x : 1, y : 1, // bottom right start, left, up, right, up             directions : [[2,Infinity],[3,1],[0,Infinity],[3,1]],         },         map5 : {             x : 0, y : 0, // top left start, down, right, up, right             directions : [[1,Infinity],[0,1],[3,Infinity],[0,1]],         },         map5 : {             x : 1, y : 0, // top right start, down, left, down, left             directions : [[1,Infinity],[2,1],[1,Infinity],[2,1]],         },         map7 : {             x : 0, y : 1, // bottom left start, up, right, down, right             directions : [[3,Infinity],[0,1],[1,Infinity],[0,1]],         },         map8 : {             x : 1, y : 1, // bottom right start, up, left, down, left             directions : [[3,Infinity],[2,1],[1,Infinity],[2,1]],         },              }     // colours     const col1 = "#FA6" //orng     const col2 = "#6AF" //l. blue     const col3 = "#03CEA4" //green     const col4 = "#FB4D3D" //red     const col5 = "#345995" //d.blue     var colA;     var colB;     // array of tiles     var tiles = [];     // number of outputs     var outputsW = Math.ceil(wallx/outputx);     var outputsH = Math.ceil(wally/outputy);     // number of cols/rows in each output     var outCols = Math.floor(outputx/tilex);     var outRows = Math.floor(outputy/tiley);     // reset or setup tiles     function reset(tiles){            console.log("**Begin Reset***");      report();      wallx = tilex*cols;   wally = tiley*rows;   ctx.canvas.width = wallx;   ctx.canvas.height = wally;   ctx.clearRect(0,0,canvas.width,canvas.height);      canvas = createImage(wallx, wally);      //document.body.appendChild(canvas);            // vars for output limits evenly divisible by tile size          var LCDoutputx = outputx;      var LCDoutputy = outputy;            //round down LCDoutputy to the next coordinate evenly divisible by a tile's y value.      if ((outputy % tiley) != 0){       LCDoutputy = (Math.floor(outputy/tiley))*tiley;         }      //round down LCDoutputx to the next coordinate evenly divisible by a tile's x value.      if ((outputx % tilex) != 0){       LCDoutputx = (Math.floor(outputx/tilex))*tilex;         }            outCols = Math.floor(outputx/tilex);   outRows = Math.floor(outputy/tiley);          //ctx = canvas.ctx;   //document.body.appendChild(canvas);         tiles.length = 0;         //rows = Math.floor(wally / tiley);         //cols = Math.floor(wallx / tilex);                  for(var y = 0; y <= wally-tiley; y+= tiley){ //changed < to <=             for(var x = 0; x <= wallx-tilex; x+= tilex){ //changed < to <=              console.log("x,y = "+x+", "+y);               console.log("wallx = "+wallx);              console.log("tilex = "+tilex);            var d = (Math.floor(y / LCDoutputy) % 2 + Math.floor(x / LCDoutputx) % 2) % 2; //added LCDoutputt for output background color to work. Was outputy. The entire map's output background colors were off by one row, showing an extra row beyond what the limits should be.      //console.log("Y : "+y+" divided by Out Y Limit : "+outputy);            //console.log("Y result : "+Math.floor(y/outputy) % 2);            //console.log("X : "+x+" divided by Out X Limit : "+outputx);            //console.log("X result : "+Math.floor(x/outputx) % 2);            //console.log(d);                 var c = (Math.floor(y / tiley) % 2 + Math.floor(x / tilex) % 2) % 2;                 tiles.push({                     x,y,tilex,tiley,                     flow : flows.none,                     output : d ? (colA = col3, colB = col4) : (colA = col1, colB = col2),                     col : c ? colA : colB,                 })             }             }         console.log("___End Reset;");         report();     }     // Creates flow map for tiles. flow maps are in flows as flow.map1, map2... etc     function createFlow(tiles,flowMap){         var i = 0;         var prevtile, tile;         var count = 0;         var x = flowMap.x * (cols-1);         //console.log(x);         var y = flowMap.y * (rows-1);         //console.log(y);         var moving = true;         while(moving){          //console.log("***   Moving   ***");          //console.log("x = "+x+" y = "+y);          //console.log("nx = "+nx+" ny = "+ny);             var ind = x + y * cols;             //console.log(tiles[ind]);             /*console.log("ind = x + y * cols");             console.log("ind = "+x+" + "+y+" * "+cols);             console.log(ind);*/             prevtile = tile;             var tile = tiles[ind];             var dir = flowMap.directions[i % flowMap.directions.length];             //console.log(dir);             var nx = x + flows.dirs[dir[0]][0];             var ny = y + flows.dirs[dir[0]][1];             //console.log("nx/ny change");             //console.log("x ("+x+") + flows.dirs[dir[0]][0]("+flows.dirs[dir[0]][0]+") = nx = "+nx);             //console.log("y ("+y+") + flows.dirs[dir[0]][1]("+flows.dirs[dir[0]][1]+") = ny = "+ny);             //console.log("Count = "+count);                          //console.log("I : "+i+" X , Y : "+x+" , "+y);             //console.log("IND : "+ind+" NX , NY : "+nx+" , "+ny);             //console.log("DIR : "+dir);             //console.log("Columns : "+cols+" Out Columns : "+outCols);             //console.log("Rows : "+rows+" Out Rows : "+outRows);                          if(nx >= cols ||  nx < 0 || ny >= rows || ny < 0 || count >= dir[1]){//if next x or y is less than 0 or out of map bounds                 i += 1; //increase i by 1                 dir = flowMap.directions[i % flowMap.directions.length]; //update dir to match i                 nx = x + flows.dirs[dir[0]][0]; //update nx                 //console.log("nx add : "+flows.dirs[dir[0]][0]);                 ny = y + flows.dirs[dir[0]][1]; //update ny                 //console.log("ny add : "+flows.dirs[dir[0]][1]);                                 if(nx >= outCols || ny >= outRows){                  //console.log("nx = "+nx+" > outCols = "+outCols);                  //console.log("ny = "+ny+" > outRows = "+outRows);                   /*if(nx === outCols){                   prevtile.flow = flows.end;                  } */                 }                                 if(nx >= cols || nx < 0 || ny >= rows || ny < 0){//determine where flow stops                     tile.flow = flows.end;                     break;                 }                 count = 0;             }                          if(tile === undefined){                 prevtile.flow = flows.end;                 break;             }             if(prevtile === undefined){                 tile.flow = flows.start;                }else{                 tile.flow = dir[0];             }             //data case checks for additional flows.starts/ends             //flow 1             if(currentFlow === 0){               //arrows              if(!((tile.y/tile.tiley) % 2) && (tile.x/tile.tilex+1) % outCols === 0){               tile.flow = flows.down;           } else if(((tile.y/tile.tiley) % 2) && (tile.x/tile.tilex) % outCols === 0){               tile.flow = flows.down;           }              //end            if((tile.x/tile.tilex) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.end;              //start              } else if ((tile.x/tile.tilex) % outCols === 0 && (tile.y/tile.tiley) % outRows == 0){               tile.flow =  flows.start;              }          //flow 2             } else if (currentFlow === 1){              //arrows              if(!((tile.y/tile.tiley) % 2) && (tile.x/tile.tilex) % outCols === 0){               tile.flow = flows.down;           } else if(((tile.y/tile.tiley) % 2) && (tile.x/tile.tilex+1) % outCols === 0){               tile.flow = flows.down;           }           //end              if((((tile.x/tile.tilex+1) % outCols === 0) || ((tile.x/tile.tilex+1) % cols === 0)) && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.end;              //start              } else if ((((tile.x/tile.tilex+1) % outCols === 0) || ((tile.x/tile.tilex+1) % cols === 0)) && (tile.y/tile.tiley) % outRows == 0){               tile.flow =  flows.start;              }          //flow 3             } else if (currentFlow === 2){              //arrows              if(!((tile.x/tile.tilex) % 2) && (tile.y/tile.tiley) % outCols === 0){               tile.flow = flows.right;           } else if(((tile.x/tile.tilex) % 2) && (tile.y/tile.tiley+1) % outCols === 0){               tile.flow = flows.right;           }           //end              if((tile.x/tile.tilex+1) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.end;              //start              } else if ((tile.x/tile.tilex) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.start;              }              //if odd # of columns              if(!(cols % 2 === 0)){            //end               if((tile.x/tile.tilex+1) % cols === 0 && (tile.y/tile.tiley) % outRows == 0){                tile.flow =  flows.end;               }                  }              //if odd # of output columns              if(!(outCols % 2 === 0)){            //end               if((tile.x/tile.tilex+1) % outCols === 0 && (tile.y/tile.tiley) % outRows == 0){                tile.flow =  flows.end;               }               }          //flow 4             } else if(currentFlow === 3){              //arrows              if(((tile.x/tile.tilex) % 2) && (tile.y/tile.tiley) % outCols === 0){               tile.flow = flows.left;           } else if(!((tile.x/tile.tilex) % 2) && (tile.y/tile.tiley+1) % outCols === 0){               tile.flow = flows.left;           }           //end            if((tile.x/tile.tilex) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.end;              //start              } else if ((tile.x/tile.tilex+1) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.start;              }                           }              count += 1;             x = nx;             y = ny;         }     }          // draws the tiles     function draw(tiles){         function arrow(tile){             if(tile.flow === flows.none){              console.log("no flow");                 return;             }             if (tilex<tiley) {              var step = tile.tilex * (1/4);             } else {           var step = tile.tiley * (1/4);                }             //var step = tile.tilex * (1/4);             var x = tile.x + tile.tilex -step;             var y = tile.y + step             ctx.strokeStyle = "white";             ctx.lineWidth = 2;             ctx.beginPath();             if(tile.flow === flows.end){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(-step / 2, -step / 2);                 ctx.lineTo(step / 2, step / 2);                 ctx.moveTo(step / 2, -step / 2);                 ctx.lineTo(-step / 2, step / 2);                                  ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(tile.flow === flows.start){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(step / 2, 0);                 ctx.arc(0,0, step / 2,0,Math.PI * 2);                 ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(tile.flow === flows.right){                 ctx.setTransform(1,0,0,1,x,y);             } else if(tile.flow === flows.left){                 ctx.setTransform(-1,0,0,1,x,y);             } else if(tile.flow === flows.down){                 ctx.setTransform(0,1,1,0,x,y);             } else if(tile.flow === flows.up){                 ctx.setTransform(0,-1,1,0,x,y);                 //ctx.setTransform(0,1,-1,0,0,0);             }             ctx.moveTo(-step / 2, 0);             ctx.lineTo(step / 2, 0);             ctx.moveTo(step / 4, -step / 4);             ctx.lineTo(step / 2, 0);             ctx.lineTo(step / 4, step / 4);             ctx.stroke();             ctx.setTransform(1,0,0,1,0,0);         }         ctx.clearRect(0,0,canvas.width,canvas.height)         var i = 0;         while(i < tiles.length){             var l = tiles[i++];             console.log("i = "+i+", tiles.length = "+tiles.length);              ctx.fillStyle = l.col             ctx.fillRect(l.x,l.y,l.tilex,l.tiley);             arrow(l);             ctx.fillStyle = '#FFF';             //ctx.font = "10 Arial";    ctx.fillText("#"+i,l.x+l.tilex*1/8,l.y+l.tiley*5/16); //toggle individual tile ID's    ctx.fillText("pix: "+l.x+", "+l.y,l.x+l.tilex*1/8,l.y+l.tiley*8/16);    ctx.fillText("flow: "+l.flow,l.x+l.tilex*1/8,l.y+l.tiley*11/16);    //ctx.fillText("d: "+l.output,l.x+l.tilex*1/8,l.y+l.tiley*14/16);    ctx.fillText("tile : "+l.x/l.tilex+", "+l.y/l.tiley,l.x+l.tilex*1/8,l.y+l.tiley*14/16);         }             }          var flowMaps = [flows.map1,flows.map2,flows.map3,flows.map4,flows.map5,flows.map6,flows.map7,flows.map8];     var currentFlow = 0;     function drawAll(){      reset(tiles);      createFlow(tiles,flowMaps[currentFlow]);         draw(tiles);         //setTimeout(setFlow,1000);     }     /*function setFlow(){         createFlow(tiles,flowMaps[(currentFlow++) % flowMaps.length]);         draw(tiles);         //setTimeout(drawAll,4000); //comment out this line to stop map change cycle     }*/     function report(){       console.log("Canvas Width : "+canvas.width);             console.log("Canvas Height : "+canvas.height);          console.log("Wall Width : "+wallx);             console.log("Wall Height : "+wally);             console.log("Tiles Wide : "+cols);             console.log("Tiles Hight : "+rows);             console.log("Tile Width : "+tilex);             console.log("Tile Height : "+tiley);             console.log("Output Width : "+outputx);             console.log("Output Height : "+outputy);    console.log("Output Columns : "+outCols);             console.log("Output Rows : "+outRows);             console.log("currentFlow = "+currentFlow);      }     drawAll();  
  <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> </head> <body>  <div id="inputs">   <span id="wall">   Wall Width : <input id="wallx" type="text" placeholder="in pixels">   Wall Height : <input id="wally" type="text" placeholder="in pixels">   <hr>   Tiles Wide : <input id="cols" type="text" placeholder="in tiles">   Tiles High : <input id="rows" type="text" placeholder="in tiles">   <hr>   Tile Width : <input id="tilex" type="text" placeholder="in pixels">   Tile Height : <input id="tiley" type="text" placeholder="in pixels">   <hr>   Output Width Limit : <input id="outputx" type="text" placeholder="in pixels">   Output Height Limit : <input id="outputy" type="text" placeholder="in pixels">   <hr>   <form id="dataFlow">    Flow 1 : <input id="flow1" type="radio" name="flow" value="0" checked="checked">    Flow 2 : <input id="flow2" type="radio" name="flow" value="1">    Flow 3 : <input id="flow3" type="radio" name="flow" value="2">    Flow 4 : <input id="flow4" type="radio" name="flow" value="3">    Flow 5 : <input id="flow5" type="radio" name="flow" value="4">    Flow 6 : <input id="flow6" type="radio" name="flow" value="5">    Flow 7 : <input id="flow7" type="radio" name="flow" value="6">    Flow 8 : <input id="flow8" type="radio" name="flow" value="7">   </form>   </span>  </div>       <script type="text/javascript" src="createImage.js">  </script>   <script>   $(function(){         var $wallx=document.getElementById('wallx');    var $wally=document.getElementById('wally');    var $cols=document.getElementById('cols');    var $rows=document.getElementById('rows');    var $tilex=document.getElementById('tilex');    var $tiley=document.getElementById('tiley');    var $outputx=document.getElementById('outputx');    var $outputy=document.getElementById('outputy');        var $flow1=document.getElementById('flow1');    var $flow2=document.getElementById('flow2');    var $flow3=document.getElementById('flow3');    var $flow4=document.getElementById('flow4');    var $flow5=document.getElementById('flow5');    var $flow6=document.getElementById('flow6');    var $flow7=document.getElementById('flow7');    var $flow8=document.getElementById('flow8');        $wallx.value=wallx;    $wally.value=wally;    $cols.value=cols;    $rows.value=rows;    $tilex.value=tilex;    $tiley.value=tiley;    $outputx.value=outputx;    $outputy.value=outputy;        $wallx.addEventListener("change", function(){     wallx=this.value; //.value converts input field int to string***     console.log(" wallx changed to : "+wallx);     drawAll();    }, false);        $wally.addEventListener("change", function(){     wally=this.value; //.value converts input field int to string***     console.log(" wally changed to : "+wally);     drawAll();    }, false);        $cols.addEventListener("change", function(){     cols=parseInt(this.value); //.value converts input field int to string***     console.log(" cols changed to : "+cols);     drawAll();     $wallx.value=wallx;     $wally.value=wally;    }, false);        $rows.addEventListener("change", function(){     rows=parseInt(this.value); //.value converts input field int to string***     console.log(" rows changed to : "+rows);     drawAll();     $wallx.value=wallx;     $wally.value=wally;    }, false);        $tilex.addEventListener("change", function(){     tilex=parseInt(this.value); //.value converts input field int to string***     console.log(" tilex changed to : "+tilex);     drawAll();     $wallx.value=wallx;     $wally.value=wally;     $outputx.value=outputx;     $outputy.value=outputy;              }, false);        $tiley.addEventListener("change", function(){     tiley=parseInt(this.value); //.value converts input field int to string***     console.log(" tiley changed to : "+tiley);     drawAll();     $wallx.value=wallx;     $wally.value=wally;     $outputx.value=outputx;     $outputy.value=outputy;         }, false);        $outputx.addEventListener("change", function(){     outputx=parseInt(this.value); //.value converts input field int to string***     console.log(" outputx changed to : "+outputx);     drawAll();    }, false);        $outputy.addEventListener("change", function(){     outputy=parseInt(this.value); //.value converts input field int to string***     console.log(" outputy changed to : "+outputy);     drawAll();    }, false);        $flow1.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow2.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow3.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow4.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow5.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow6.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow7.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow8.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);   });  </script> </body>  
Original en ingles

Ultimately I want to be able to draw a checkerboard (wall) of user-defined size. This wall is made up of tiles of a user-defined size. This main wall can then be split up into multiple sections (outputs) dependent on user defined limits. The data-flow is then drawn in each individual output(see Example 2), not just for the entire wall(Example 1).

I was provided an elegant solution by user @Blindman67 that iterates through each tile in the map and sets it's flow in the order of the flow. This works wonderfully until I change it to set a tile to be the end of the flow once it reaches the limit of a single output.

If you check out example 3 I start to add in some extremely crude if/else if statements to check for every possibility in the 8 different flows, setting the ends and beginnings of flows as well as arrow directions manually. This is extremely sloppy and I'd much prefer something more akin to what's going on in example 1, but with a working data flow drawn for each individual output.

Here are two pictures of what I can do thus far. Looking at the 2nd picture, you'll see I want to be able to fill in the remaining 3 empty outputs with their respective data flows.

Example 1 - no output limits

Example 2 - missing data flows

I don't know if I should change the 'Infinity' limit to be the limits of the outputs here:

const flows = {         none : -1,         right : 0,         down : 1,         left : 2,         up : 3,         end : 4,  // for end of flow         start : 5,  // for start         dirs : [[1,0],[0,1],[-1,0],[0,-1]], // x,y step for each direction         // Maps are used to workout the flow layout         // x,y is the starting position with 0 as top or left and 1 as bottom or right         // directions has an array for each direction. the first item is the travel         // direction and the second item is the max number of steps befor turning         map1 : { // top left start rigth, down, left, down              x : 0, y : 0,             directions : [[0,Infinity],[1,1],[2,Infinity],[1,1]],         },         map2 : {  // top right start, left, down, right, down              x : 1, y : 0,             directions : [[2,Infinity],[1,1],[0,Infinity],[1,1]],         },         map3 : {             x : 0, y : 1, // bottom left start, up, right, down, right             directions : [[3,Infinity],[0,1],[1,Infinity],[0,1]],         },         map4 : {             x : 1, y : 1, // bottom right start, up, left, down, left             directions : [[3,Infinity],[2,1],[1,Infinity],[2,1]],         },     } 

Or if I need to edit the createFlow(); function to add a check for each individual output:

// Creates flow map for tiles. flow maps are in flows as flow.map1, map2... etc function createFlow(tiles,flowMap){     var i = 0;     var prevtile, tile;     var count = 0;     var x = flowMap.x * (cols-1);     var y = flowMap.y * (rows-1);     var moving = true;     while(moving){         var ind = x + y * cols;         prevtile = tile;         var tile = tiles[ind];         var dir = flowMap.directions[i % flowMap.directions.length];         var nx = x + flows.dirs[dir[0]][0];         var ny = y + flows.dirs[dir[0]][1];         if(nx >= cols || nx >= outCols || nx < 0 || ny >= rows || ny >= outRows || ny < 0 || count >= dir[1]){//determine what tiles stop changing nx/ny/dir             i += 1;             dir = flowMap.directions[i % flowMap.directions.length];             nx = x + flows.dirs[dir[0]][0];             ny = y + flows.dirs[dir[0]][1];             if(nx >= cols || nx >= outCols || nx < 0 || ny >= rows || ny >= outRows || ny < 0){//determine where flow stops                 tile.flow = flows.end;                 break;             }             count = 0;         }         if(tile === undefined){             prevtile.flow = flows.end;             break;         }         if(prevtile === undefined){             tile.flow = flows.start;            }else{             tile.flow = dir[0];         }         count += 1;         x = nx;         y = ny;     } } 

Example 1 - Flow functions correctly, but no output limits:

/** CreateImage.js begin **/     // creates a blank image with 2d context     var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}          /** CreateImage.js end **/     var canvas = createImage(512,512);     var ctx = canvas.ctx;     document.body.appendChild(canvas);          // cell size     var size = 40;          // constants for directions     const flows = {         none : -1,         right : 0,         down : 1,         left : 2,         up : 3,         end : 4,  // for end of flow         start : 5,  // for start         dirs : [[1,0],[0,1],[-1,0],[0,-1]], // x,y step for each direction         // Maps are used to workout the flow layout         // x,y is the starting position with 0 as top or left and 1 as bottom or right         // directions has an array for each direction. the first item is the travel         // direction and the second item is the max number of steps befor turning         map1 : { // top left start rigth, down, left, down              x : 0, y : 0,             directions : [[0,Infinity],[1,1],[2,Infinity],[1,1]],         },         map2 : {  // top right start, left, down, right, down              x : 1, y : 0,             directions : [[2,Infinity],[1,1],[0,Infinity],[1,1]],         },         map3 : {             x : 0, y : 1, // bottom left start, up, right, down, right             directions : [[3,Infinity],[0,1],[1,Infinity],[0,1]],         },         map4 : {             x : 1, y : 1, // bottom right start, up, left, down, left             directions : [[3,Infinity],[2,1],[1,Infinity],[2,1]],         },     }     // colours     const col1 = "#FA6"     const col2 = "#6AF"     // array of leds     var leds = [];     // number columns and rows     var rows;     var cols;     // reset or setup leds     function reset(leds){         leds.length = 0;         cols = Math.floor(canvas.height / size);         rows = Math.floor(canvas.width / size);         for(var y = 0; y < canvas.height-size; y+= size){             for(var x = 0; x < canvas.width-size; x += size){                 var c = (Math.floor(y / size) % 2 + Math.floor(x / size) % 2) % 2;                 leds.push({                     x,y,size,                     flow : flows.none,                     col : c ? col1 : col2,                 })                  }             }     }     // Creates flow map for leds. flow maps are in flows as flow.map1, map2... etc     function createFlow(leds,flowMap){         var i = 0;         var prevLed, led;         var count = 0;         var x = flowMap.x * (cols-1);         var y = flowMap.y * (rows-1);         var moving = true;         while(moving){             var ind = x + y * cols;             prevLed = led;             var led = leds[ind];             var dir = flowMap.directions[i % flowMap.directions.length];             var nx = x + flows.dirs[dir[0]][0];             var ny = y + flows.dirs[dir[0]][1];             if(nx >= cols || nx < 0 || ny >= rows || ny < 0 || count >= dir[1]){                 i += 1;                 dir = flowMap.directions[i % flowMap.directions.length];                 nx = x + flows.dirs[dir[0]][0];                 ny = y + flows.dirs[dir[0]][1];                 if(nx >= cols || nx < 0 || ny >= rows || ny < 0){                     led.flow = flows.end;                     break;                 }                 count = 0;             }             if(led === undefined){                 prevLed.flow = flows.end;                 break;             }             if(prevLed === undefined){                 led.flow = flows.start;                }else{                 led.flow = dir[0];             }             count += 1;             x = nx;             y = ny;         }     }          // draws the leds     function draw(leds){         function arrow(led){             if(led.flow === flows.none){                 return;             }             var step = led.size * (1/4);             var x = led.x + led.size -step;             var y = led.y + step             ctx.strokeStyle = "white";             ctx.lineWidth = 2;             ctx.beginPath();             if(led.flow === flows.end){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(-step / 2, -step / 2);                 ctx.lineTo(step / 2, step / 2);                 ctx.moveTo(step / 2, -step / 2);                 ctx.lineTo(-step / 2, step / 2);                                  ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(led.flow === flows.start){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(step / 2, 0);                 ctx.arc(0,0, step / 2,0,Math.PI * 2);                 ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(led.flow === flows.right){                 ctx.setTransform(1,0,0,1,x,y);             } else if(led.flow === flows.left){                 ctx.setTransform(-1,0,0,1,x,y);             } else if(led.flow === flows.down){                 ctx.setTransform(0,1,1,0,x,y);             } else if(led.flow === flows.up){                 ctx.setTransform(0,-1,1,0,x,y);                 //ctx.setTransform(0,1,-1,0,0,0);             }             ctx.moveTo(-step / 2, 0);             ctx.lineTo(step / 2, 0);             ctx.moveTo(step / 4, -step / 4);             ctx.lineTo(step / 2, 0);             ctx.lineTo(step / 4, step / 4);             ctx.stroke();             ctx.setTransform(1,0,0,1,0,0);         }         ctx.clearRect(0,0,canvas.width,canvas.height)         var i = 0;         while(i < leds.length){             var l = leds[i++];             ctx.fillStyle = l.col             ctx.fillRect(l.x,l.y,l.size,l.size);             arrow(l);         }     }          var flowMaps = [flows.map1,flows.map2,flows.map3,flows.map4];     var currentFlow = 3;     function drawAll(){         reset(leds);         draw(leds);         setTimeout(setFlow,1000);     }     function setFlow(){         createFlow(leds,flowMaps[(currentFlow++) % flowMaps.length]);         draw(leds);         setTimeout(drawAll,4000);     }     drawAll();

Example 2 - Flow functions correctly within the limits of one single output.

/** CreateImage.js begin **/  //wall size     var wallx = 500;     var wally = 500;          //output size     var outputx = 250;     var outputy = 250;          // tile size     var tilex = 25;     var tiley = 25;          // vars for output limits evenly divisible by tile size         var LCDoutputx = outputx;     var LCDoutputy = outputy;          //round down LCDoutputy to the next coordinate evenly divisible by a tile's y value.     if ((outputy % tiley) != 0){      LCDoutputy = (Math.floor(outputy/tiley))*tiley;        }     //round down LCDoutputx to the next coordinate evenly divisible by a tile's x value.     if ((outputx % tilex) != 0){      LCDoutputx = (Math.floor(outputx/tilex))*tilex;        }          // creates a blank image with 2d context     var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}          /** CreateImage.js end **/     var canvas = createImage(wallx, wally);     var ctx = canvas.ctx;     document.body.appendChild(canvas);          // constants for directions     const flows = {         none : -1,         right : 0,         down : 1,         left : 2,         up : 3,         end : 4,  // for end of flow         start : 5,  // for start         dirs : [[1,0],[0,1],[-1,0],[0,-1]], // x,y step for each direction         // Maps are used to workout the flow laoutputy         // x,y is the starting position with 0 as top or left and 1 as bottom or right         // directions has an array for each direction. the first item is the travel         // direction and the second item is the max number of steps befor turning         map1 : { // top left start rigth, down, left, down              x : 0, y : 0,             directions : [[0,Infinity],[1,1],[2,Infinity],[1,1]],         },         map2 : {  // top right start, left, down, right, down              x : 1, y : 0,             directions : [[2,Infinity],[1,1],[0,Infinity],[1,1]],         },         map3 : {             x : 0, y : 1, // bottom left start, up, right, down, right             directions : [[3,Infinity],[0,1],[1,Infinity],[0,1]],         },         map4 : {             x : 1, y : 1, // bottom right start, up, left, down, left             directions : [[3,Infinity],[2,1],[1,Infinity],[2,1]],         },     }     // colours     const col1 = "#FA6" //orng     const col2 = "#6AF" //l. blue     const col3 = "#03CEA4" //green     const col4 = "#FB4D3D" //red     const col5 = "#345995" //d.blue     var colA;     var colB;     // array of tiles     var tiles = [];     // number columns and rows     var rows;     var cols;     // number of outputs     var outputsW = Math.ceil(wallx/outputx);     var outputsH = Math.ceil(wally/outputy);     // number of cols/rows in each output     var outCols = Math.floor(outputx/tilex);     var outRows = Math.floor(outputy/tiley);     // reset or setup tiles     function reset(tiles){         tiles.length = 0;         rows = Math.floor(canvas.height / tiley);         cols = Math.floor(canvas.width / tilex);         for(var y = 0; y <= canvas.height-tiley; y+= tiley){ //changed < to <=              for(var x = 0; x <= canvas.width-tilex; x += tilex){ //changed < to <=            var d = (Math.floor(y / LCDoutputy) % 2 + Math.floor(x / LCDoutputx) % 2) % 2; //added LCDoutputt for output background color to work. Was outputy. The entire map's output background colors were off by one row, showing an extra row beyond what the limits should be.      //console.log("Y : "+y+" divided by Out Y Limit : "+outputy);            //console.log("Y result : "+Math.floor(y/outputy) % 2);            //console.log("X : "+x+" divided by Out X Limit : "+outputx);            //console.log("X result : "+Math.floor(x/outputx) % 2);            //console.log(d);                 var c = (Math.floor(y / tiley) % 2 + Math.floor(x / tilex) % 2) % 2;                 tiles.push({                     x,y,tilex,tiley,                     flow : flows.none,                     output : d ? (colA = col3, colB = col4) : (colA = col1, colB = col2),                     col : c ? colA : colB,                                      })             }             }     }     // Creates flow map for tiles. flow maps are in flows as flow.map1, map2... etc     function createFlow(tiles,flowMap){         var i = 0;         var prevtile, tile;         var count = 0;         var x = flowMap.x * (cols-1);         var y = flowMap.y * (rows-1);         var moving = true;         while(moving){             var ind = x + y * cols;             prevtile = tile;             var tile = tiles[ind];             var dir = flowMap.directions[i % flowMap.directions.length];             var nx = x + flows.dirs[dir[0]][0];             var ny = y + flows.dirs[dir[0]][1];             //console.log(count);             //console.log("I : "+i+" X , Y : "+x+" , "+y);             //console.log("IND : "+ind+" NX , NY : "+nx+" , "+ny);             //console.log("DIR : "+dir);             //console.log("Columns : "+cols+" Out Columns : "+outCols);             //console.log("Rows : "+rows+" Out Rows : "+outRows);             if(nx >= cols || nx >= outCols || nx < 0 || ny >= rows || ny >= outRows || ny < 0 || count >= dir[1]){//determine what tiles stop changing nx/ny/dir                 i += 1;                 dir = flowMap.directions[i % flowMap.directions.length];                 nx = x + flows.dirs[dir[0]][0];                 ny = y + flows.dirs[dir[0]][1];                 if(nx >= cols || nx >= outCols || nx < 0 || ny >= rows || ny >= outRows || ny < 0){//determine where flow stops                     tile.flow = flows.end;                     break;                 }                 count = 0;             }             if(tile === undefined){                 prevtile.flow = flows.end;                 break;             }             if(prevtile === undefined){                 tile.flow = flows.start;                }else{                 tile.flow = dir[0];             }             count += 1;             x = nx;             y = ny;         }     }          // draws the tiles     function draw(tiles){         function arrow(tile){             if(tile.flow === flows.none){                 return;             }             if (tilex<tiley) {              var step = tile.tilex * (1/4);             } else {           var step = tile.tiley * (1/4);                }             //var step = tile.tilex * (1/4);             var x = tile.x + tile.tilex -step;             var y = tile.y + step             ctx.strokeStyle = "white";             ctx.lineWidth = 2;             ctx.beginPath();             if(tile.flow === flows.end){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(-step / 2, -step / 2);                 ctx.lineTo(step / 2, step / 2);                 ctx.moveTo(step / 2, -step / 2);                 ctx.lineTo(-step / 2, step / 2);                                  ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(tile.flow === flows.start){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(step / 2, 0);                 ctx.arc(0,0, step / 2,0,Math.PI * 2);                 ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(tile.flow === flows.right){                 ctx.setTransform(1,0,0,1,x,y);             } else if(tile.flow === flows.left){                 ctx.setTransform(-1,0,0,1,x,y);             } else if(tile.flow === flows.down){                 ctx.setTransform(0,1,1,0,x,y);             } else if(tile.flow === flows.up){                 ctx.setTransform(0,-1,1,0,x,y);                 //ctx.setTransform(0,1,-1,0,0,0);             }             ctx.moveTo(-step / 2, 0);             ctx.lineTo(step / 2, 0);             ctx.moveTo(step / 4, -step / 4);             ctx.lineTo(step / 2, 0);             ctx.lineTo(step / 4, step / 4);             ctx.stroke();             ctx.setTransform(1,0,0,1,0,0);         }         ctx.clearRect(0,0,canvas.width,canvas.height)         var i = 0;         while(i < tiles.length){             var l = tiles[i++];             ctx.fillStyle = l.col             ctx.fillRect(l.x,l.y,l.tilex,l.tiley);             arrow(l);         }              }          var flowMaps = [flows.map1,flows.map2,flows.map3,flows.map4];     var currentFlow = 4;     function drawAll(){         reset(tiles);         draw(tiles);         //setTimeout(setFlow,1000);         setFlow();     }     function setFlow(){         createFlow(tiles,flowMaps[(currentFlow++) % flowMaps.length]);         draw(tiles);         //setTimeout(drawAll,4000); //comment out this line to stop map change cycle     }     drawAll();

Example 3 - Flow function totally botched but gives an idea of the flexibility I want with user defined fields

/** CreateImage.js begin **/  //output size     var outputx = 256;     var outputy = 256;          // tile size     var tilex = 64;     var tiley = 64;          // rows & columns     var rows = 8;     var cols = 8;          // wall/map size dictated by rows/cols     wallx = tilex*cols;  wally = tiley*rows;                   // creates a blank image with 2d context     var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}          /** CreateImage.js end **/     var canvas = createImage(wallx, wally);     var ctx = canvas.ctx;     document.body.appendChild(canvas);          // constants for directions     const flows = {         none : -1,         right : 0,         down : 1,         left : 2,         up : 3,         end : 4,  // for end of flow         start : 5,  // for start         dirs : [[1,0],[0,1],[-1,0],[0,-1]], // x,y step for each direction         // Maps are used to workout the flow laoutputy         // x,y is the starting position with 0 as top or left and 1 as bottom or right         // directions has an array for each direction. the first item is the travel         // direction and the second item is the max number of steps befor turning         map1 : { // top left start rigth, down, left, down              x : 0, y : 0,             directions : [[0,Infinity],[1,1],[2,Infinity],[1,1]],         },         map2 : {  // top right start, left, down, right, down              x : 1, y : 0,             directions : [[2,Infinity],[1,1],[0,Infinity],[1,1]],         },         map3 : {             x : 0, y : 1, // bottom left start, right, up, left, up             directions : [[0,Infinity],[3,1],[2,Infinity],[3,1]],         },         map4 : {             x : 1, y : 1, // bottom right start, left, up, right, up             directions : [[2,Infinity],[3,1],[0,Infinity],[3,1]],         },         map5 : {             x : 0, y : 0, // top left start, down, right, up, right             directions : [[1,Infinity],[0,1],[3,Infinity],[0,1]],         },         map5 : {             x : 1, y : 0, // top right start, down, left, down, left             directions : [[1,Infinity],[2,1],[1,Infinity],[2,1]],         },         map7 : {             x : 0, y : 1, // bottom left start, up, right, down, right             directions : [[3,Infinity],[0,1],[1,Infinity],[0,1]],         },         map8 : {             x : 1, y : 1, // bottom right start, up, left, down, left             directions : [[3,Infinity],[2,1],[1,Infinity],[2,1]],         },              }     // colours     const col1 = "#FA6" //orng     const col2 = "#6AF" //l. blue     const col3 = "#03CEA4" //green     const col4 = "#FB4D3D" //red     const col5 = "#345995" //d.blue     var colA;     var colB;     // array of tiles     var tiles = [];     // number of outputs     var outputsW = Math.ceil(wallx/outputx);     var outputsH = Math.ceil(wally/outputy);     // number of cols/rows in each output     var outCols = Math.floor(outputx/tilex);     var outRows = Math.floor(outputy/tiley);     // reset or setup tiles     function reset(tiles){            console.log("**Begin Reset***");      report();      wallx = tilex*cols;   wally = tiley*rows;   ctx.canvas.width = wallx;   ctx.canvas.height = wally;   ctx.clearRect(0,0,canvas.width,canvas.height);      canvas = createImage(wallx, wally);      //document.body.appendChild(canvas);            // vars for output limits evenly divisible by tile size          var LCDoutputx = outputx;      var LCDoutputy = outputy;            //round down LCDoutputy to the next coordinate evenly divisible by a tile's y value.      if ((outputy % tiley) != 0){       LCDoutputy = (Math.floor(outputy/tiley))*tiley;         }      //round down LCDoutputx to the next coordinate evenly divisible by a tile's x value.      if ((outputx % tilex) != 0){       LCDoutputx = (Math.floor(outputx/tilex))*tilex;         }            outCols = Math.floor(outputx/tilex);   outRows = Math.floor(outputy/tiley);          //ctx = canvas.ctx;   //document.body.appendChild(canvas);         tiles.length = 0;         //rows = Math.floor(wally / tiley);         //cols = Math.floor(wallx / tilex);                  for(var y = 0; y <= wally-tiley; y+= tiley){ //changed < to <=             for(var x = 0; x <= wallx-tilex; x+= tilex){ //changed < to <=              console.log("x,y = "+x+", "+y);               console.log("wallx = "+wallx);              console.log("tilex = "+tilex);            var d = (Math.floor(y / LCDoutputy) % 2 + Math.floor(x / LCDoutputx) % 2) % 2; //added LCDoutputt for output background color to work. Was outputy. The entire map's output background colors were off by one row, showing an extra row beyond what the limits should be.      //console.log("Y : "+y+" divided by Out Y Limit : "+outputy);            //console.log("Y result : "+Math.floor(y/outputy) % 2);            //console.log("X : "+x+" divided by Out X Limit : "+outputx);            //console.log("X result : "+Math.floor(x/outputx) % 2);            //console.log(d);                 var c = (Math.floor(y / tiley) % 2 + Math.floor(x / tilex) % 2) % 2;                 tiles.push({                     x,y,tilex,tiley,                     flow : flows.none,                     output : d ? (colA = col3, colB = col4) : (colA = col1, colB = col2),                     col : c ? colA : colB,                 })             }             }         console.log("___End Reset;");         report();     }     // Creates flow map for tiles. flow maps are in flows as flow.map1, map2... etc     function createFlow(tiles,flowMap){         var i = 0;         var prevtile, tile;         var count = 0;         var x = flowMap.x * (cols-1);         //console.log(x);         var y = flowMap.y * (rows-1);         //console.log(y);         var moving = true;         while(moving){          //console.log("***   Moving   ***");          //console.log("x = "+x+" y = "+y);          //console.log("nx = "+nx+" ny = "+ny);             var ind = x + y * cols;             //console.log(tiles[ind]);             /*console.log("ind = x + y * cols");             console.log("ind = "+x+" + "+y+" * "+cols);             console.log(ind);*/             prevtile = tile;             var tile = tiles[ind];             var dir = flowMap.directions[i % flowMap.directions.length];             //console.log(dir);             var nx = x + flows.dirs[dir[0]][0];             var ny = y + flows.dirs[dir[0]][1];             //console.log("nx/ny change");             //console.log("x ("+x+") + flows.dirs[dir[0]][0]("+flows.dirs[dir[0]][0]+") = nx = "+nx);             //console.log("y ("+y+") + flows.dirs[dir[0]][1]("+flows.dirs[dir[0]][1]+") = ny = "+ny);             //console.log("Count = "+count);                          //console.log("I : "+i+" X , Y : "+x+" , "+y);             //console.log("IND : "+ind+" NX , NY : "+nx+" , "+ny);             //console.log("DIR : "+dir);             //console.log("Columns : "+cols+" Out Columns : "+outCols);             //console.log("Rows : "+rows+" Out Rows : "+outRows);                          if(nx >= cols ||  nx < 0 || ny >= rows || ny < 0 || count >= dir[1]){//if next x or y is less than 0 or out of map bounds                 i += 1; //increase i by 1                 dir = flowMap.directions[i % flowMap.directions.length]; //update dir to match i                 nx = x + flows.dirs[dir[0]][0]; //update nx                 //console.log("nx add : "+flows.dirs[dir[0]][0]);                 ny = y + flows.dirs[dir[0]][1]; //update ny                 //console.log("ny add : "+flows.dirs[dir[0]][1]);                                 if(nx >= outCols || ny >= outRows){                  //console.log("nx = "+nx+" > outCols = "+outCols);                  //console.log("ny = "+ny+" > outRows = "+outRows);                   /*if(nx === outCols){                   prevtile.flow = flows.end;                  } */                 }                                 if(nx >= cols || nx < 0 || ny >= rows || ny < 0){//determine where flow stops                     tile.flow = flows.end;                     break;                 }                 count = 0;             }                          if(tile === undefined){                 prevtile.flow = flows.end;                 break;             }             if(prevtile === undefined){                 tile.flow = flows.start;                }else{                 tile.flow = dir[0];             }             //data case checks for additional flows.starts/ends             //flow 1             if(currentFlow === 0){               //arrows              if(!((tile.y/tile.tiley) % 2) && (tile.x/tile.tilex+1) % outCols === 0){               tile.flow = flows.down;           } else if(((tile.y/tile.tiley) % 2) && (tile.x/tile.tilex) % outCols === 0){               tile.flow = flows.down;           }              //end            if((tile.x/tile.tilex) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.end;              //start              } else if ((tile.x/tile.tilex) % outCols === 0 && (tile.y/tile.tiley) % outRows == 0){               tile.flow =  flows.start;              }          //flow 2             } else if (currentFlow === 1){              //arrows              if(!((tile.y/tile.tiley) % 2) && (tile.x/tile.tilex) % outCols === 0){               tile.flow = flows.down;           } else if(((tile.y/tile.tiley) % 2) && (tile.x/tile.tilex+1) % outCols === 0){               tile.flow = flows.down;           }           //end              if((((tile.x/tile.tilex+1) % outCols === 0) || ((tile.x/tile.tilex+1) % cols === 0)) && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.end;              //start              } else if ((((tile.x/tile.tilex+1) % outCols === 0) || ((tile.x/tile.tilex+1) % cols === 0)) && (tile.y/tile.tiley) % outRows == 0){               tile.flow =  flows.start;              }          //flow 3             } else if (currentFlow === 2){              //arrows              if(!((tile.x/tile.tilex) % 2) && (tile.y/tile.tiley) % outCols === 0){               tile.flow = flows.right;           } else if(((tile.x/tile.tilex) % 2) && (tile.y/tile.tiley+1) % outCols === 0){               tile.flow = flows.right;           }           //end              if((tile.x/tile.tilex+1) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.end;              //start              } else if ((tile.x/tile.tilex) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.start;              }              //if odd # of columns              if(!(cols % 2 === 0)){            //end               if((tile.x/tile.tilex+1) % cols === 0 && (tile.y/tile.tiley) % outRows == 0){                tile.flow =  flows.end;               }                  }              //if odd # of output columns              if(!(outCols % 2 === 0)){            //end               if((tile.x/tile.tilex+1) % outCols === 0 && (tile.y/tile.tiley) % outRows == 0){                tile.flow =  flows.end;               }               }          //flow 4             } else if(currentFlow === 3){              //arrows              if(((tile.x/tile.tilex) % 2) && (tile.y/tile.tiley) % outCols === 0){               tile.flow = flows.left;           } else if(!((tile.x/tile.tilex) % 2) && (tile.y/tile.tiley+1) % outCols === 0){               tile.flow = flows.left;           }           //end            if((tile.x/tile.tilex) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.end;              //start              } else if ((tile.x/tile.tilex+1) % outCols === 0 && (tile.y/tile.tiley+1) % outRows == 0){               tile.flow =  flows.start;              }                           }              count += 1;             x = nx;             y = ny;         }     }          // draws the tiles     function draw(tiles){         function arrow(tile){             if(tile.flow === flows.none){              console.log("no flow");                 return;             }             if (tilex<tiley) {              var step = tile.tilex * (1/4);             } else {           var step = tile.tiley * (1/4);                }             //var step = tile.tilex * (1/4);             var x = tile.x + tile.tilex -step;             var y = tile.y + step             ctx.strokeStyle = "white";             ctx.lineWidth = 2;             ctx.beginPath();             if(tile.flow === flows.end){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(-step / 2, -step / 2);                 ctx.lineTo(step / 2, step / 2);                 ctx.moveTo(step / 2, -step / 2);                 ctx.lineTo(-step / 2, step / 2);                                  ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(tile.flow === flows.start){                 ctx.setTransform(1,0,0,1,x,y);                 ctx.moveTo(step / 2, 0);                 ctx.arc(0,0, step / 2,0,Math.PI * 2);                 ctx.stroke();                 ctx.setTransform(1,0,0,1,0,0);                 return;             }else if(tile.flow === flows.right){                 ctx.setTransform(1,0,0,1,x,y);             } else if(tile.flow === flows.left){                 ctx.setTransform(-1,0,0,1,x,y);             } else if(tile.flow === flows.down){                 ctx.setTransform(0,1,1,0,x,y);             } else if(tile.flow === flows.up){                 ctx.setTransform(0,-1,1,0,x,y);                 //ctx.setTransform(0,1,-1,0,0,0);             }             ctx.moveTo(-step / 2, 0);             ctx.lineTo(step / 2, 0);             ctx.moveTo(step / 4, -step / 4);             ctx.lineTo(step / 2, 0);             ctx.lineTo(step / 4, step / 4);             ctx.stroke();             ctx.setTransform(1,0,0,1,0,0);         }         ctx.clearRect(0,0,canvas.width,canvas.height)         var i = 0;         while(i < tiles.length){             var l = tiles[i++];             console.log("i = "+i+", tiles.length = "+tiles.length);              ctx.fillStyle = l.col             ctx.fillRect(l.x,l.y,l.tilex,l.tiley);             arrow(l);             ctx.fillStyle = '#FFF';             //ctx.font = "10 Arial";    ctx.fillText("#"+i,l.x+l.tilex*1/8,l.y+l.tiley*5/16); //toggle individual tile ID's    ctx.fillText("pix: "+l.x+", "+l.y,l.x+l.tilex*1/8,l.y+l.tiley*8/16);    ctx.fillText("flow: "+l.flow,l.x+l.tilex*1/8,l.y+l.tiley*11/16);    //ctx.fillText("d: "+l.output,l.x+l.tilex*1/8,l.y+l.tiley*14/16);    ctx.fillText("tile : "+l.x/l.tilex+", "+l.y/l.tiley,l.x+l.tilex*1/8,l.y+l.tiley*14/16);         }             }          var flowMaps = [flows.map1,flows.map2,flows.map3,flows.map4,flows.map5,flows.map6,flows.map7,flows.map8];     var currentFlow = 0;     function drawAll(){      reset(tiles);      createFlow(tiles,flowMaps[currentFlow]);         draw(tiles);         //setTimeout(setFlow,1000);     }     /*function setFlow(){         createFlow(tiles,flowMaps[(currentFlow++) % flowMaps.length]);         draw(tiles);         //setTimeout(drawAll,4000); //comment out this line to stop map change cycle     }*/     function report(){       console.log("Canvas Width : "+canvas.width);             console.log("Canvas Height : "+canvas.height);          console.log("Wall Width : "+wallx);             console.log("Wall Height : "+wally);             console.log("Tiles Wide : "+cols);             console.log("Tiles Hight : "+rows);             console.log("Tile Width : "+tilex);             console.log("Tile Height : "+tiley);             console.log("Output Width : "+outputx);             console.log("Output Height : "+outputy);    console.log("Output Columns : "+outCols);             console.log("Output Rows : "+outRows);             console.log("currentFlow = "+currentFlow);      }     drawAll();
<head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> </head> <body>  <div id="inputs">   <span id="wall">   Wall Width : <input id="wallx" type="text" placeholder="in pixels">   Wall Height : <input id="wally" type="text" placeholder="in pixels">   <hr>   Tiles Wide : <input id="cols" type="text" placeholder="in tiles">   Tiles High : <input id="rows" type="text" placeholder="in tiles">   <hr>   Tile Width : <input id="tilex" type="text" placeholder="in pixels">   Tile Height : <input id="tiley" type="text" placeholder="in pixels">   <hr>   Output Width Limit : <input id="outputx" type="text" placeholder="in pixels">   Output Height Limit : <input id="outputy" type="text" placeholder="in pixels">   <hr>   <form id="dataFlow">    Flow 1 : <input id="flow1" type="radio" name="flow" value="0" checked="checked">    Flow 2 : <input id="flow2" type="radio" name="flow" value="1">    Flow 3 : <input id="flow3" type="radio" name="flow" value="2">    Flow 4 : <input id="flow4" type="radio" name="flow" value="3">    Flow 5 : <input id="flow5" type="radio" name="flow" value="4">    Flow 6 : <input id="flow6" type="radio" name="flow" value="5">    Flow 7 : <input id="flow7" type="radio" name="flow" value="6">    Flow 8 : <input id="flow8" type="radio" name="flow" value="7">   </form>   </span>  </div>       <script type="text/javascript" src="createImage.js">  </script>   <script>   $(function(){         var $wallx=document.getElementById('wallx');    var $wally=document.getElementById('wally');    var $cols=document.getElementById('cols');    var $rows=document.getElementById('rows');    var $tilex=document.getElementById('tilex');    var $tiley=document.getElementById('tiley');    var $outputx=document.getElementById('outputx');    var $outputy=document.getElementById('outputy');        var $flow1=document.getElementById('flow1');    var $flow2=document.getElementById('flow2');    var $flow3=document.getElementById('flow3');    var $flow4=document.getElementById('flow4');    var $flow5=document.getElementById('flow5');    var $flow6=document.getElementById('flow6');    var $flow7=document.getElementById('flow7');    var $flow8=document.getElementById('flow8');        $wallx.value=wallx;    $wally.value=wally;    $cols.value=cols;    $rows.value=rows;    $tilex.value=tilex;    $tiley.value=tiley;    $outputx.value=outputx;    $outputy.value=outputy;        $wallx.addEventListener("change", function(){     wallx=this.value; //.value converts input field int to string***     console.log(" wallx changed to : "+wallx);     drawAll();    }, false);        $wally.addEventListener("change", function(){     wally=this.value; //.value converts input field int to string***     console.log(" wally changed to : "+wally);     drawAll();    }, false);        $cols.addEventListener("change", function(){     cols=parseInt(this.value); //.value converts input field int to string***     console.log(" cols changed to : "+cols);     drawAll();     $wallx.value=wallx;     $wally.value=wally;    }, false);        $rows.addEventListener("change", function(){     rows=parseInt(this.value); //.value converts input field int to string***     console.log(" rows changed to : "+rows);     drawAll();     $wallx.value=wallx;     $wally.value=wally;    }, false);        $tilex.addEventListener("change", function(){     tilex=parseInt(this.value); //.value converts input field int to string***     console.log(" tilex changed to : "+tilex);     drawAll();     $wallx.value=wallx;     $wally.value=wally;     $outputx.value=outputx;     $outputy.value=outputy;              }, false);        $tiley.addEventListener("change", function(){     tiley=parseInt(this.value); //.value converts input field int to string***     console.log(" tiley changed to : "+tiley);     drawAll();     $wallx.value=wallx;     $wally.value=wally;     $outputx.value=outputx;     $outputy.value=outputy;         }, false);        $outputx.addEventListener("change", function(){     outputx=parseInt(this.value); //.value converts input field int to string***     console.log(" outputx changed to : "+outputx);     drawAll();    }, false);        $outputy.addEventListener("change", function(){     outputy=parseInt(this.value); //.value converts input field int to string***     console.log(" outputy changed to : "+outputy);     drawAll();    }, false);        $flow1.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow2.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow3.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow4.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow5.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow6.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow7.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);              $flow8.addEventListener("click", function(){           currentFlow=parseInt(this.value); //.value converts input field int to string***           drawAll();       }, false);   });  </script> </body>
              
   
   

Lista de respuestas


Relacionados problema

10  "Stardust" Simulador 2D Gravity - Seguimiento 1: Los planetas  ( Stardust 2d gravity simulator follow up 1 the planets ) 
Este es un seguimiento para el juego de gravedad del simulador 2D pregunta. Desde entonces, he desarrollado mis habilidades de JavaScript, y ahora esto...

5  Utilizando lienzo HTML5 para aplicar el tema de color a .png iconos  ( Utilizing html5 canvas to apply color theme to png icons ) 
Porque tenemos una mezcla de ambos iconos para los elementos principales y los iconos .png para artículos personalizados, he desarrollado una manera fácil de ...

5  Clasificación de juego de pong  ( Classing pong game ) 
Acabo de empezar a codificar. ¿Algo para ayudar a simplemente o mejorar el código? Esto está completamente terminado y listo para jugar, aunque la pelota re...

1  Mapas de mapas en un lienzo que aparece cajas cuando se hace clic en  ( Map markers on a canvas that pop up boxes when clicked ) 
Aquí hay una versión de trabajo de mi código: http://jsfiddle.net/sambenson/g3qsa/# base ¿Cómo se puede mejorar esto? <?php //class sql //{ class Re...

6  Mejora del rendimiento de las partículas en p5.js  ( Improving particle performance in p5 js ) 
He modificado un sistema de partículas para crear un efecto similar al que quiero. Sin embargo, con cualquier cantidad sustancial de partículas que realiza mu...

2  D3.js Rendimiento de lienzo  ( D3 js canvas performance ) 
Acabo de reescribir este código (una simple simulación de N-cuerpo restringido gravitacional ) Para mostrar utilizando lienzo, en lugar de SVG. La razón es ...

7  Dividir el texto en líneas de un valor máximo de ancho para lienzo  ( Splitting text into lines from a max width value for canvas ) 
OK, así que esto funciona como está, y en realidad no es lento en absoluto (por lo que puedo ver), sin embargo, no me gusta el sabor de lo anidado mientras qu...

3  Reacciona el componente de la imagen que carga y difumina una imagen en un lienzo  ( React image component that loads and blurs an image onto a canvas ) 
Mi componente de imagen React.js Cargará una imagen de una cuerda URL o BASE64, haga un procesamiento en él y lo ponga en un lienzo. La punta de "precarga" es...

2  Dos fragmentos de JavaScript para permitir el dibujo en un lienzo  ( Two javascript snippets to allow drawing on a canvas ) 
Me senté para escribir una página de demostración HTML5-ISH que permite a un usuario realizar las siguientes operaciones en una línea de lienzo, dibuje un rec...

1  JavaScript Canvas rebotar objetos  ( Javascript canvas bouncing objects ) 
He estado jugando con JavaScript durante algún tiempo y hice una simple animación de lienzo. Intenté que mi código limpio, pero me gustaría escuchar tus opini...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos