Fabric.js Images in a pyramid - javascript

I have some very wet code with coordinates for to make a pyramid with a wide base, out of images in frabric.js
I have tried all day to succeed in writing a loop to dry up the code. I'm somewhat of a beginner, so I cannot get it into my head how to do this.
Please can someone help. I've looked around and found how to do something similar with circles in fabric.js, but I can't seem to translate it into images.
The loop also needs to increment a row number, so fabric knows when to add the next row.
This is the terrible code I have.
var canvasWidth = 1000;
var imageWidth = 20;
var row1 = 1;
var a = canvasWidth/2-(imageWidth)*1/2+imageWidth*0;
var row2 = 11;
var b = canvasWidth/2-(imageWidth)*2/2+imageWidth*0;
var c = canvasWidth/2-(imageWidth)*2/2+imageWidth*1;
var row3 = 21
var d = canvasWidth/2-(imageWidth)*3/2+imageWidth*0;
var e = canvasWidth/2-(imageWidth)*3/2+imageWidth*1;
var f = canvasWidth/2-(imageWidth)*3/2+imageWidth*2;
var row4 = 31
var g = canvasWidth/2-(imageWidth)*4/2+imageWidth*0;
var h = canvasWidth/2-(imageWidth)*4/2+imageWidth*1;
var i = canvasWidth/2-(imageWidth)*4/2+imageWidth*2;
var j = canvasWidth/2-(imageWidth)*4/2+imageWidth*3;
var row5 = 41
var k = canvasWidth/2-(imageWidth)*5/2+imageWidth*0;
var m = canvasWidth/2-(imageWidth)*5/2+imageWidth*1;
var n = canvasWidth/2-(imageWidth)*5/2+imageWidth*2;
var o = canvasWidth/2-(imageWidth)*5/2+imageWidth*3;
var p = canvasWidth/2-(imageWidth)*5/2+imageWidth*4;
console.log("Row1: "+a +
" Row2: "+ b + "," + c+
" Row3: "+ d + "," + e+ ","+ f +
" Row4: "+ g + "," + h +","+ i + "," + j +
" Row5: "+ k + "," + m +","+ n + "," + o + "," + p);

To make correct loop you should understand what you Iterate, here, you are iterating rows and cells (bricks may be correct name), so to make a loop you should just make loop in loop, like in table:
var canvasWidth = 1000;
var imageWidth = 20;
var rows = [];
for (var row = 1; row <= 5; row++) { // use let in es6
var cells = []; // use let in es6
rows[row - 1] = cells;
for (var cell = 0; cell <= row - 1; cell++) { // use let in es6
cells[cell] = canvasWidth / 2 - (imageWidth) * row / 2 + imageWidth * cell;
}
}
console.log(rows);

Related

How to draw 2d plane on canvas from a Typed array?

I am drawing a 2D image from the values of a transverse plane in a Uint8ClampedArray onto a canvas like this:
Code:
// Cols and Rows are always 512 in my case
var cols = 512;
var rows = 512;
// offset to specified slice
var sliceSize = cols * rows;
var sliceOffset = sliceSize * slice;
var thisSliceData = typedArray.slice(sliceOffset, sliceOffset + sliceSize);
for (var row = 0; row < rows; row++) {
var rowOffset = row * cols;
for (var col = 0; col < cols; col++) {
var offset = sliceOffset + rowOffset + col;
var value = typedArray[offset]; //
canvasImage.data[(rowOffset + col) * 4] = value;
canvasImage.data[(rowOffset + col) * 4 + 1] = value;
canvasImage.data[(rowOffset + col) * 4 + 2] = value;
canvasImage.data[(rowOffset + col) * 4 + 3] = 255;
}
}
I would like to be able to get the sagittal and coronal planes as well. I'm having a hard time wrapping my head around it. How do I tweak the code to get those?

Uncaught TypeError: Cannot set property 'background' of undefined at colorguessinggame.js:13

I created an array that creates an x amount of RGB colors randomly. I want to take this information and assign each element in the array to a square button. So the idea is when the code is ran each instance, the square buttons will get a new RGB color to it.
var generateColors = generateArray(6);
var generateColorOptions = document.querySelectorAll(".colorSquare");
// giving each button a color value from the array
for(var i = 0; i < generateColorOptions.length; i++) {
generateColors[i].style.background = generateColors[i];
}
//want to make one of the RGB values created the solution RGB that prints in the beiggining
function generateArray(num) {
var colorArray = [num];
for(var i = 0; i < num.length; i++) {
//random color generated
colorArray.push(generateRGBNumber());
//want to always push an array element to be the given RGB value
}
return colorArray;
}
function generateRGBNumber() {
var num = Math.round(0xffffff * Math.random());
var r = num >> 16;
var g = num >> 8 & 255;
var b = num & 255;
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}
You are changin background of generateColors function change it to generateColorOptions.
Also decalre colorArray is [] and iterate for loop with num only. not num.length because number is a function. Use below code.
var generateColors = generateArray(6);
var generateColorOptions = document.querySelectorAll(".colorSquare");
// giving each button a color value from the array
for (var i = 0; i < generateColorOptions.length; i++) {
generateColorOptions[i].style.background = generateColors[i];
}
//want to make one of the RGB values created the solution RGB that prints in the beiggining
function generateArray(num) {
var colorArray = [];
for (var i = 0; i < num; i++) {
//random color generated
colorArray.push(generateRGBNumber());
//want to always push an array element to be the given RGB value
}
return colorArray;
}
function generateRGBNumber() {
var num = Math.round(0xffffff * Math.random());
var r = num >> 16;
var g = num >> 8 & 255;
var b = num & 255;
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}

Trying to call a hasChildNodes method but getting cannot read property of Null

I'm attempting to make a simple turn-based two player game (like FE) as practice for an upcoming project. In trying to ensure that no characters overlap on the same grid tile, I tried to make a validator function that I can call for each character on generation (randomly generated locations), so that I wouldn't have the same script with minor changes in each character gen section. My original code (without the function) is above, the most recent attempt (with some context) is below:
function bTeamCharGen() {
var a = 10;
var b = 15;
var c = 0;
var d = 5;
var bTeamLead = document.createElement("img");
bTeamLead.src = "images/transp_img.gif";
bTeamLead.height = "38";
bTeamLead.width = "38";
bTeamLead.className = "lead";
bTeamLead.id = "bLead";
genStartPos();
var curr = document.getElementById("gridBlock_" + i + "_" + j);
if (curr.hasChildNodes()) {
while (curr.hasChildNodes()) {
genStartPos(a, b, c, d);
}
}
document.getElementById("gridBlock_" + i + "_" + j).appendChild(bTeamLead);
document.getElementById("bLead").style.background = "url('images/eirika_1_1.gif') 0 0";
document.getElementById("bLead").style.backgroundRepeat = "no-repeat";
//commented out basic structure for further characters here
}
This is the original code for one of the characters. The following is what I've currently arrived at (and still with the Uncaught TypeError):
var i, j;
//functions to generate grid and background
function genStartPos(minX, maxX, minY, maxY) {
i = Math.floor(Math.random() * (maxX - minX + 1) + minX);
j = Math.floor(Math.random() * (maxY - minY + 1) + minY);
}
function validStartPos() {
genStartPos();
var curr = document.getElementById("gridBlock_" + i + "_" + j);
if (curr.hasChildNodes()) {
while (curr.hasChildNodes()) {
genStartPos(a, b, c, d);
}
}
}
function bTeamCharGen() {
var a = 10;
var b = 15;
var c = 0;
var d = 5;
var bTeamLead = document.createElement("img");
bTeamLead.src = "images/transp_img.gif";
bTeamLead.height = "38";
bTeamLead.width = "38";
bTeamLead.className = "lead";
bTeamLead.id = "bLead";
validStartPos();
document.getElementById("gridBlock_" + i + "_" + j).appendChild(bTeamLead);
document.getElementById("bLead").style.background = "url('images/eirika_1_1.gif') 0 0";
document.getElementById("bLead").style.backgroundRepeat = "no-repeat";
//commented out basic structure for further characters here
}
function initialise() {
makeGrid();
setBackground();
bTeamCharGen();
rTeamCharGen();
}
It's a bit long and unwieldy, as I'm still trying to neaten it up quite a bit, but everything else worked until I did this. I'm calling the initialise function as an onload for the body, and the <script> is within the <head>, since I had problems earlier on when having it within <body>.
I'm not sure, but... I think you trying get element when "gridBlock_" + i + "_" + j is undefined
You calling genStartPos() without any parameter. So your i and j are undefined, so you string with element id.
If you cant pass variables to genStartPos(), you need to make some default value for maxX, maxY...
PS you also calling genStartPos(a, b, c, d) when a, b, c, d are undefined. Or maybe this just not all code you show

Using for loops to define global variables

I am defining some global arrays at the top of my JS file. There are for loops to populate the arrays. I have done very similar things that have worked but for some reason, this is having issues. The first for loop runs through only one time and the code below that never gets ran.
var group = 'a';
var RoofVar = 1;
var TrimVar = 1;
var BBVar = 1;
var imageArrayGroup0 = [];
var floatingButtonArrayGroup0 = [];
var labelArrayGroup0 = [];
for (a = 1; a < 3; a++) {
labelArrayGroup0[a] = document.createElement("Label");
labelArrayGroup0[a].type = "Label";
floatingButtonArrayGroup0[a] = document.getElementById('floatingButton0' + (100 + a));
floatingButtonArrayGroup0[a].style.textAlign = "center";
floatingButtonArrayGroup0[a].style.paddingTop = "5px";
labelArrayGroup0[a] = document.getElementById('floatingButton0' + (100 + x));
}
var imageArray0 = [];
var floatingButtonArray0 = [];
var labelArray0 = [];
for (b = 1; b < 5; b++) {
imageArray0[b] = document.createElement("img");
imageArray0[b].type = "image";
floatingButtonArray0[b] = document.getElementById('floatingButton0' + (b));
floatingButtonArray0[b].style.paddingLeft = "15px";
floatingButtonArray0[b].style.paddingTop = "5px";
labelArray0[b] = document.getElementById('floatingButton0' + b);
}
var imageArray1 = [];
var floatingButtonArray1 = [];
var labelArray1 = [];
for (c = 1; c < 3; c++) {
imageArray1[c] = document.createElement("img");
imageArray1[c].type = "image";
floatingButtonArray1[c] = document.getElementById('floatingButton1' + (c));
floatingButtonArray1[c].style.paddingLeft = "15px";
floatingButtonArray1[c].style.paddingTop = "5px";
labelArray1[c] = document.getElementById('floatingButton1' + c);
}
You have other issues than just "(100 + x) instead of (100 + a).
First, arrays in JavaScript are "zero-based" but your loops start at 1.
This means you're putting things in but leaving spot '0' undefined, which will probably break things later.
Next. at the beginning of the loop you set labelArrayGroup0[a] to a new blank label, but you never do anything to put it on the page. At the end the loop, you overwrite labelArrayGroup0[a] to a floatingButton element you pull from the page.
In fact, you do this in every loop - the last line resets the value of the 1st line.
It's not clear what you're trying to accomplish. Presumably you intend to append labelArrayGroup0[a] to the page instead?
Also, in the middle, you set floatingButtonArrayGroup0[a] = document.getElementById('floatingButton0' + (100 + a)); which is the same element you grab in the last line of the loop...
Paul had my answer. I forgot to switch out the "x" for an "a".

c pointers and javascript

I have been working on a conversion of a C code into javascript. But they just don't return the same data.
I have an idea on how to handle the pointers. In javascript I'll create an array.
Note: This are not the full code, only partials
Origin:
// file.h
unsigned char m_aucState0[256];
unsigned char m_aucState[256];
unsigned char m_ucI;
unsigned char m_ucJ;
unsigned char* m_pucState1;
unsigned char* m_pucState2;
// file.c
unsigned char *pucKeyData
for(i=0; i<256; i++)
{
m_pucState1 = m_aucState0 + i;
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
m_pucState2 = m_aucState0 + m_ucJ;
//Swaping
m_ucTemp = *m_pucState1;
*m_pucState1 = *m_pucState2;
*m_pucState2 = m_ucTemp;
m_ucI = (m_ucI + 1) % iKeyLen;
}
memcpy(m_aucState, m_aucState0, 256);
Javascript:
// buffer or array???
this.m_aucState0 = new Buffer(256)
this.m_aucState = new Buffer(256)
this.m_ucI
this.m_ucJ
this.m_pucState1 = []
this.m_pucState2 = []
for (var i = 0; i < 256; i++)
{
this.m_pucState1 = this.m_aucState0 + i
this.m_ucJ += this.m_pucState1[0] + (pucKeyData[0] + this.m_ucI)
this.m_pucState2 = this.m_aucState0 + this.m_ucJ
//Swaping
this.m_ucTemp = this.m_pucState1[0]
this.m_pucState1[0] = this.m_pucState2[0]
this.m_pucState2[0] = this.m_ucTemp
this.m_ucI = (this.m_ucI + 1) % iKeyLen
}
this.m_aucState.copy(this.m_aucState0, 0, 0, 256)
So my idea is because a pointer returns an address, that address contains the first byte of the pointer data. So if in an array I could just also point to the first index of the array right?
Is what I did above right?
Just for context let me add 1 function:
Javascript:
Crypt.prototype.setup = function(pucKeyData, iKeyLen) {
if (iKeyLen < 1)
throw new Error("Key Length should be at least 1")
var i;
for (i = 0; i < 256; i++)
this.m_aucState0[i] = i
this.m_ucI = 0
this.m_ucJ = 0
for (var i = 0; i < 256; i++)
{
this.m_pucState1 = this.m_aucState0 + i
this.m_ucJ += this.m_pucState1[i] + (pucKeyData[i] + this.m_ucI)
this.m_pucState2 = this.m_aucState0 + this.m_ucJ
//Swaping
this.m_ucTemp = this.m_pucState1[i]
this.m_pucState1[i] = this.m_pucState2[i]
this.m_pucState2[i] = this.m_ucTemp
this.m_ucI = (this.m_ucI + 1) % iKeyLen
}
this.m_aucState.copy(this.m_aucState0, 0, 0, 256)
//Initialize Indexes
this.m_ucI = 0
this.m_ucJ = 0
//Initialization Finished
this.m_bInit = true
}
CPP:
void CArcfourPRNG::SetKey(unsigned char *pucKeyData, int iKeyLen)
{
if(iKeyLen < 1)
throw exception("Key Length should be at least 1");
int i;
for(i=0; i<256; i++)
m_aucState0[i] = i;
m_ucI = 0;
m_ucJ = 0;
for(i=0; i<256; i++)
{
m_pucState1 = m_aucState0 + i;
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
m_pucState2 = m_aucState0 + m_ucJ;
//Swaping
m_ucTemp = *m_pucState1;
*m_pucState1 = *m_pucState2;
*m_pucState2 = m_ucTemp;
m_ucI = (m_ucI + 1) % iKeyLen;
}
memcpy(m_aucState, m_aucState0, 256);
//Initialize Indexes
m_ucI = 0;
m_ucJ = 0;
//Initialization Finished
m_bInit = true;
}
What is the difference of m_pucState1 and *m_pucState1 in this:
m_pucState1 = m_aucState + m_ucI;
m_ucJ += *m_pucState1;
In Javascript, there are typed buffer objects: http://www.javascripture.com/ArrayBuffer
You will also find something about the ctypes collection, but in my understanding they are used only for native OS library calls.
Also, I don't know a native JS Buffer object like you mention it. There is one in NodeJS, but I don't know its features.
If you insist of translating your code one-by-one, then these typed buffer objects may greatly support you. I think it's not a good way as while translating from C to Javascript, your terminology alters anyway. It alters from adding long pointer values to forming array indices.
Here is one problem example in your translation:
In C, you write:
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
In Javascript, you write:
this.m_ucJ += this.m_pucState1[0] + (pucKeyData[0] + this.m_ucI);
The brackets in the C term make m_ucI altering the address. So in Javascript this should rather be in the square brackets, somehow like this:
this.m_ucJ += this.m_pucState1[0] + pucKeyData[0 + this.m_ucI];
and then you can skip the "0 +". This shows how one-by-one translation between such different languages is full of traps.
So let's assume that we will use the simplest Javascript object, which is the array []. Then this is my suggestion. It's a draft, but it should give you a thorough idea:
// Define arrays
var aState0 = []; // m_aucState0
var aState = []; // m_aucState
// Define helpers
var state1Index; // *m_pucState1
var state2Index; // *m_pucState2
var i; // m_uci. There is no such thing as "uc" in Javascript.
var j; // m_ucj
var iLoop; // i in loop.
// It's readable to have this constant.
var bufferLength = 255;
// Somewhere we need:
var keyData;
var temp;
var iKeyLen;
// Just for here, give the array a size. So it's done in Javascript.
// Alternatively, fill it with 256 values from anywhere.
aState0[bufferLength] = 0;
// console.log(state0.length) will now print 256
// ...
// init i, j, iKeyLen ...
// ...
for (iLoop = 0; iLoop <= bufferLength; iLoop++) {
// This:
// m_pucState1 = m_aucState0 + i;
// m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
// becomes:
state1Index = iLoop;
j += aState0[state1Index] + keyData[i];
// This:
// m_pucState2 = m_aucState0 + m_ucJ;
// becomes:
state2Index = j;
// This:
// m_ucTemp = *m_pucState1;
// *m_pucState1 = *m_pucState2;
// *m_pucState2 = m_ucTemp;
// becomes:
temp = aState0[state1Index];
aState0[state1Index] = aState0[state2Index];
aState0[state2Index] = temp;
// This:
// m_ucI = (m_ucI + 1) % iKeyLen;
// becomes:
i = (i+1) % iKeyLen;
}
// this:
// memcpy(m_aucState, m_aucState0, 256);
// would be a clone. So you'd need jQuery or else. But you can simply write:
for (index in state0) {
state[index] = state0[index];
}
Finally, you can drop j as it is equal to state2Index, and state1Index equal to iLoop.
But this is a puzzle where you will probably have to use paper and pencil and to draw some boxes and arrows to get clear with.
Hth :-)

Categories

Resources