HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Navigating HTML5 canvas checkerboard with nested loops / multi-dimensional arrays

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
arraysmultiwithloopsnavigatingcheckerboardnestedhtml5dimensionalcanvas

Problem

I'm creating a web app to create pixel maps for large LED displays. The maps are basically large checkerboard patterns of various sizes with different constraints.

I'm running into snags trying to draw arrows pointing in certain directions dependent on their position within a) the entire grid, and b) within smaller sub-sections of the map.

Upon loading the jsfiddle, you can scroll down and see a correct example. The arrows snake through the red/blue area of the map from left to right, going down one row at a time.

Now if you select the second data flow option (the 2nd radio button from the left on the top row of radio buttons) you'll see the direction of the arrows change but the map doesn't draw correctly.

I need help getting this running efficiently. Nested loops within loops within loops seems slow. Plus I'm just in over my head and a bit confused. There's a working earlier version of the app at (http://www.blinkingthings.com) if you need a more complete picture of what I'm asking for.

I'd also appreciate any criticism of this javascript as it's not my expertise.

Javascript:

```
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

var width=128;
var height=128;
var columns=16;
var rows=9;

var color1="#d9534f";//redish
var color2="#428bca";//bluish
var color4="#00FF00";//greenish
var color3="#FFFF00";//yellowish

var textcolor="#FFFFFF";
var datacolor="#FFFFFF";
var bordercolor ="#5cb85c";
var dataStartColor ="#5cb85c";
var infoBackgroundColor = "rgba(255,255,255,.01)";
var infoForegroundColor = "rgba(0,0,255,.1)";

var upArr = '\u2191';
var downArr = '\u2193';
var leftArr = '\u2190';
var rightArr = '\u2192';
var stopSign = '\uD83D\uDEAB';
var omega = '\u03A9';

var oddOrEven = "odd";
var colOddEven = "odd";

var dataFlow = "1";
var drawCoords = true;
var drawData = true;
var drawInfo = true;
var

Solution

To do the flow you can define some simple directions and then just iterate following the instructions.

For example the human readable form. Start top left, move right until edge,turn down move one step, move left until edge,move down one step, and repeat. Stop when no more places to move.

And the machine readable form

right : 0,
down : 1,
left : 2,
up : 3,
dirs : [[1,0],[0,1],[-1,0],[0,-1]],
map1 : { // top left start rigth, down, left, down 
    x : 0, y : 0,
    directions : [[0,Infinity],[1,1],[2,Infinity],[1,1]],
},


See code for more details.

You put it in code of course with instructions as indexes into various arrays.

THe best way to explain is in code so take a look at the source of the demo. The flow function walks the leds following the instruction in flows.map1 (map1 - map4) You can add other maps but you must make sure that you do not create an endless path. Or you can add an additional check for each step. If the current led.flow !== flows.none then you must be repeating so break and exit. It should not happen so I did not include it, but you may make an error entering data and the page will be blocked.

Demo draws grid waits a second then draw flow. Waits 4 seconds and repeats using the next flow directions. Circle marks start of flow and cross the end.


Note code uses ES6 you must adapt it to ES5 if you want it to work on legacy browsers.



`/ 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 = cols || nx = rows || ny = 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 = rows || ny

Code Snippets

right : 0,
down : 1,
left : 2,
up : 3,
dirs : [[1,0],[0,1],[-1,0],[0,-1]],
map1 : { // top left start rigth, down, left, down 
    x : 0, y : 0,
    directions : [[0,Infinity],[1,1],[2,Infinity],[1,1]],
},

Context

StackExchange Code Review Q#153131, answer score: 2

Revisions (0)

No revisions yet.