How to obtain value from JSON element being created dynamically. Example below. I was wondering if there is way to get the value from previous element 'top' using some javascript. (Please update the title if its incorrect or misleading)
Following this example on jsfiddle
var info = [
{
src: "http://dummyimage.com/55x80/0d0.png/fff",
pos: {
top: 93,
left: 70
},
rotate: -10,
zIndex: 3
},
{
src: "http://dummyimage.com/55x80/d00.png/fff",
pos: {
top: previousElement(top) + some dynamic value added at run time,
left: 70
},
rotate: 0,
zIndex: 2
},
]
I wouldn't do this, you can calculate it as you go based on the index.
But... if you insist:
Assuming your array is a JS literal (and not JSON, which is different) you can use a simple counter.
Using the fact assignment returns the assigned value (this is kind of ugly though):
var top = 93;
var info = [
{
src: "http://dummyimage.com/55x80/0d0.png/fff",
pos: {
top: top,
left: 70
},
rotate: -10,
zIndex: 3
},
{
src: "http://dummyimage.com/55x80/d00.png/fff",
pos: {
top: top = top + (some dynamic value added at run time),
left: 70
},
rotate: 0,
zIndex: 2
} //... keep doing top = top + sometDynamicValue on all elements
]
A more isolated example might be:
var c = 0,
arr = [
{a:c = c + 5},
{a:c = c + 5},
{a:c = c + 5},
{a:c = c + 5},
{a:c = c + 5},
]
Which creates an array of objects with an increasing by 5 a property.
I was wondering if there is way to get the value from previous element 'top' using some javascript
info is an array so all you need to do is index into it then access the prop object i.e.
var prevTop = info[someIndex].pos.top;
There's no simple syntax to get the value from the previous element in an array literal in Javascript. You have to reference it by index, like this:
pos: {
top: info[0].pos.top + value
left: 70
},
Try this function:
function DoOffset(data, offset)
{
for (var i = 1; i < data.length; i++)
{
data[i].pos.top = data[i - 1].pos.top + offset;
}
}
You can loop through the info array to change the value:
for(var i = 1, len = info.length; i < len; i++) {
info[i].pos.top = info[i - 1].pos.top + newValue;
}
Related
Let's say I have the following arrays with just numbers:
[0, 0, 0, 0]
and
[40, 50, 75, 80]
How do I interpolate from the first to the second, using staggering/cycling (with GSAP)? (And with staggering I mean, first do the first item, then after some delay, do the next).
Note: I have already converted the single number values to objects so that GSAP can work with them (so [{y: 0}, {y: 0}] and so forth
Answered by the following question on the GSAP forum:
https://greensock.com/forums/topic/18692-interpolating-using-staggerto-from-one-array-w-values-to-the-next/
To make it possible to interpolate between a single value in a array (in this case, a number), I had to create a new timeline-like object for every value
var a = [0, 0, 0, 0];
staggerArray(a, [10,20,30,40], {duration:1, stagger:0.5, round:true});
//vars accepts: duration, stagger, round, as well as any typical vars for TimelineMax (like onComplete, onUpdate, repeat, yoyo, etc.)
function staggerArray(start, end, vars) {
var tl = new TimelineMax(vars),
proxy = {},
duration = vars.duration || 0,
stagger = vars.stagger || 0,
proxyUpdate = function(original, proxy, i) {
return function() {
original[i] = proxy[i];
};
},
v, i;
for (i = 0; i < start.length; i++) {
proxy[i] = start[i];
v = {};
v[i] = end[i];
v.onUpdate = proxyUpdate(start, proxy, i);
if (vars.round) {
v.roundProps = i + "";
}
tl.to(proxy, duration, v, stagger * i);
}
return tl;
}
So I hacked this code from somewhere else, but have an object variable to store x,y values in an array every time a hex is clicked, defined with two functions, one to add an element and one to remove the last element
var objMoves = {
length: 0,
addElem: function addElem(elem) {
// obj.length is automatically incremented
// every time an element is added.
[].push.call(this, elem);
},
removeElem: function removeElem(last) {
// this removes the last item in the array
[].splice.call(this,last, 1);
}
};
I call it like this:
objMoves.addElem({ x: hexX, y: hexY });
Result if I dump the objMoves into the console log is "{"0":{"x":2,"y":1},"length":1}"
However, what I really want is something like
objMoves.addElem({ x: hexX, y: hexY },stackID:"abcdef");
So the result would be something like
{stackId:"abcdef",moves:[{"x":2,"y":1},{"x":3,"y":4}]}
{stackId:"xyz",moves:[{"x":5,"y":2},{"x":6,"y":2},{"x":7,"y":2}]}
etc, where the inner array gets added to for a given stackID. I think I need to nest the objects?
push() is for arrays, not objects, so use the right data structure.
var objMoves = [];
// ...
data[0] = { "": "", "": "" };
data[1] = { ....};
// ...
var tempData = [];
for ( var index=0; index<data.length; index++ ) {
if ( data[index].objMoves ) {
tempData.push( data );
}
}
data = tempData;
or deal with it like it is an object. while Objects does not support push property, you can save it as well using the index as key.
It sounds like what you're looking for is something like this:
var objMoves = {
addElem: function(id, elem) {
var obj = this[id] || {
stackId: id,
moves: []
};
obj.moves.push(elem);
this[id] = obj;
},
removeElem: function(id, last) {
this[id].moves.splice(last, 1);
}
}
objMoves.addElem("abcdef", {x: 123, y: 456});
objMoves.addElem("xyz", {x: 1, y: 2});
objMoves.addElem("abcdef", {x: 100, y: 50});
console.log(objMoves);
The functions take a stack ID as a parameter, so they can use that as a key into the object to find the sub-object with that ID. The moves are stored in an array in that sub-object.
I was a little bit fascinated from the code, that you have taken from the MDN JavaScript reference site. It shows us how we could use an object as an array. And so I wrote some functions to do it.
Solution with all, what you need:
var objMoves =
{
// objMoves.length is automatically incremented every time an element is added
length: 0,
//add an object to new(with stackId) or given(by stackId) array element
addElem: function(object, stackId)
{
var index = this.getElemIndex(stackId);
if(index > -1)
this[index].moves.push(object);
else
[].push.call(this, {stackId: stackId, moves: [object]})
},
//remove the array element on lastElemIndex
removeElem: function(lastElemIndex)
{
[].splice.call(this, lastElemIndex, 1)
},
//remove the object on lastElemIndex from the array element with stackId
removeMovesElem: function(stackId, lastElemIndex)
{
var index = this.getElemIndex(stackId);
if(index > -1)
this[index].moves.splice(lastElemIndex, 1)
},
//get the array element index by stackId
getElemIndex: function(stackId)
{
for(var i = this.length; i--;)
if(this[i].stackId == stackId)
return i
return -1
}
};
//we check functions:
objMoves.addElem({x: 2, y: 1}, 'abcdef');
objMoves.addElem({x: 3, y: 4}, 'abcdef');
objMoves.addElem({x: 5, y: 2}, 'xyz');
objMoves.addElem({x: 6, y: 2}, 'xyz');
objMoves.addElem({x: 7, y: 2}, 'xyz');
console.log(JSON.stringify(objMoves, null, '\t'));
console.log('===========================');
var index = objMoves.getElemIndex('abcdef');
objMoves.removeElem(index);
console.log(JSON.stringify(objMoves, null, '\t'));
console.log('===========================');
objMoves.removeMovesElem('xyz', 1);
console.log(JSON.stringify(objMoves, null, '\t'));
I am creating an HTML5 platform game using objects for collision detection and using a 2d tile map to render the level. That is all working.
I want to use the same 2d array to build the object array dynamically to allow the player to build maps as required and also for ease of creating the maps in the first place. When hardcoding the object array, everything works so I know that the collision detect and game engine work.
While I can create objects for each individual array element, I am looking to build objects that have width based on the number of matching elements in the array, (each element is 25x25) i.e. if 3 array elements are 1,1,1 then the object will have a width of 75. Maybe some code will help explain:
The following tile array
var arr1 = [
[0,0,0,1,1,1,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,2,2,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[3,3,3,0,0,0,0,0,0,0]
];
should produce the following object array:
[
{x: 75, y: 0, width: 100, height: 25, value: 1},
{x: 75, y: 50, width: 50, height: 25, value: 2},
{x: 0, y: 100, width: 75, height: 25, value: 3}
]
but it instead it is producing the following:
[
{x: 75, y: 0, width: 25, height: 25, value: 1},
{x: 100, y: 0, width: 25, height: 25, value: 1},
{x: 125, y: 0, width: 25, height: 25, value: 1}
]
My logic is obviously wrong but I can't for the life of me get it.
Example code is below:
Any help really appreciated:
var tmpObj = {};
var objArr = [];
var arr1 = [
[0,0,0,1,1,1,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,2,2,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[3,3,3,0,0,0,0,0,0,0]
];
for (let i=0; i<arr1.length; i++) {
for (let j=0; j<arr1[i].length; j++) {
if (arr1[i][j] > 0 && arr1[i][j] < 6) { // platform blocks only 1 - 5
if (tmpObj.x === undefined) {
tmpObj = {
x: j * 25,
y: i * 25,
width: 25,
height: 25,
value: arr1[i][j]
}
} else if (arr1[i][j] == arr1[i][j-1] && arr1[i][j] == tmpObj.v) {
tmpObj.w += 25;
} else if (arr1[i][j] !== tmpObj.v) { // new tile type
objArr.push(tmpObj);
tmpObj = {
x: j * 25,
y: i * 25,
width: 25,
height: 25,
value: arr1[i][j]
}
} else {
objArr.push(tmpObj);
tmpObj = {};
}
}
}
}
console.log(objArr);
Looking at what you are trying to do your implementation is way too complicated. Rather than hunt down the bug (for which I would have used devTools and stepped through the code line by line to find where the problem was.) I rewrote the function using a while loop to find the width of joined tiles.
I took liberty with the object property names but I am sure you can change it to your needs.
const objArr = [];
const arr1 = [
[0,0,0,1,1,1,1,0,1,0],
[2,0,0,0,0,0,0,0,0,3],
[0,0,0,4,4,0,4,4,4,4],
[0,0,0,0,0,0,0,0,0,0],
[3,3,3,5,5,4,0,0,0,0]
];
const tileSize = 25;
for (let i = 0; i < arr1.length; i++) {
const row = arr1[i]
for (let j = 0; j < row.length; j++) {
if (row[j] > 0 && row[j] < 6) {
let count = j + 1;
while (count < row.length && row[count] === row[j]) { count += 1 }
objArr.push({
x: j * tileSize,
y: i * tileSize,
w: tileSize * (count - j),
h: tileSize,
tile: row[j]
});
j = count - 1;
}
}
}
// show results
objArr.forEach(log);
// unrelated to answer. (I hate the console SO has for snippets.)
function log(data){
show.appendChild(
Object.assign(
document.createElement("div"), {
textContent :
Object.keys(data).reduce((str, key) => {
return str + (" " + key+ ": " + data[key]).padEnd(8,".");
}, ""
)
}
)
);
}
<code id="show"></code>
I want to create such array in loop
dataset: [
{
x: 0,
y: 0,
},
{
x: 1,
y: 0.993,
}
]
But this way is not correct.
var array = new Array(10);
for (var i = 0; i < 5; ++i) {
array[i].x = 1;
array[i].y = 2;
}
How I can initialize in correct way?
The comments made by SLaks and squint are correct, so this answer is more of an explanation of why your code isn't working like you think it should, and an example of what you could do instead.
You created an array with room to hold 10 things but you didn't specify what those things were and so nothing is contained in the array.
var array = new Array(10);
you can visualize your array like this:
array = [undefined, undefined, undefined, undefined,...
The array you created was just a container for 10 things not yet defined. When you tried to assign the 'x' and 'y' properties of the array elements, you were were trying to operate on something that did not exist. To get what you want, I suggest creating an object that has the properties you want, with initial values, and then use your loop to add the number of elements you want.
var array = [];
var arrayObject = {x:0,y:0};
for(i=0; i < 10; i++){
array.push(arrayObject);
}
You can do this job in one assignment line as follows;
var dataSet = (new Array(10)).fill("initial y value").reduce((p,c,i) => p.concat({x:i,y:c}),[]);
console.log(dataSet);
I just couldn't figure what y values you would like to have so inserted the initial values of the array. Change them the way you like later. I hope it helps.
Replace the new Array(10) with
var array = Array.apply( {}, { length: 10 } ).map( function() { return {} });
new Array(10) is creating an array like
[ undefined, undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined]
So you are trying to assign x on undefined
If you tried
new Array(10).map(function(){ return {}; }) it will not work either.
An es6 way to do it would be
Array.from(new Array(10), () => { return { x: 1, y: 2 }; })
In JavaScript the Array acts different than in static-typed languages, so there's no need to initialize it with fixed length.
For ECMAScript 6 specification and later:
var points = [].fill.call({ length: 5 }, {x: 1, y: 1});
It produces
[{x: 1, y: 1},
{x: 1, y: 1},
{x: 1, y: 1},
{x: 1, y: 1},
{x: 1, y: 1}]
To ensure old browsers' support use for loop:
var points = [{x: 1, y: 1}];
for (var i = 0; i < 5; i++) points.push(points[0]);
I want to make an array within an array.
It would contain some enemies with all different positions. I tried writing it like this:
var enemies = [
position = {
x: 0,
y: 0
}
];
enemies.length = 6;
This seem to work, however, I don’t know what to write when I want to call it. enemies[1].position.x doesn’t work at all. Any leads?
You probably want an array of enemy objects instead. Something like:
var enemies = [
{ position: { x: 0, y: 0 } },
{ position: { x: 0, y: 0 } },
{ position: { x: 0, y: 0 } }
];
var firstEnemy = enemies[0];
firstEnemy.position.x; // 0
var totalEnemies = enemies.length; // 3
What you want to do is
var enemies = [
{
position: { x: 0, y: 0 }
}
];
enemies[0].position.x;
Arrays index starts from 0
Also, let's deconstruct why your code doesn't throw an error, and what it exactly does.
You are declaring an array named enemies, and when declaring it you are defining a global variable named position (and its value is returned)
After execution, enemies look like this [ {x: 0, y: 0} ]