How to create point object containing x,y and creating its array?
so that i can loop over those points, add/remove points dynamically.
var points = [{x:45, y:64}, {x:56, y:98}, {x:23, y:44}];
var len = points.length;
for(var i = 0; i < len; i++) {
alert(points[i].x + ' ' + points[i].y);
}
// to add more points, push an object to the array:
points.push({x:56, y:87});
Demo: http://jsfiddle.net/gjHeV/
You can create a constructor for a Point object like this:
function Point(x, y) {
this.x = x;
this.y = y;
}
Now you can create Point objects using the new keyword:
var p = new Point(4.5, 19.0);
To create an array of Point objects you simply create an array, and put Point objects in it:
var a = [ new Point(1,2), new Point(5,6), new Point(-1,14) ];
Or:
var a = [];
a.push(new Point(1,2));
a.push(new Point(5,6));
a.push(new Point(-1,14));
You use the . operator to access the properties in the Point object. Example:
alert(a[2].x);
Or:
var p = a[2];
alert(p.x + ',' + p.y);
I suggest you read about JavaScript arrays to learn all that. It is important that you know the basics.
Example for adding:
var points = [];
points.push({x:5, y:3});
Faster, more efficient:
var points = [ [45,64], [56,98], [23,44] ];
for(var i=0, len=points.length; i<len; i++){
//put your code here
console.log( 'x'+points[i][0], 'y'+points[i][1] )
}
// to add more points, push an array to the array:
points.push([100,100]);
The efficiency will only really be noticeable in a very large array of points.
Related
I'm using Canvas/javascript (createjs) and am having difficulty calling an instance or adding a child to stage of a cloned shape (via an array using a for loop adding incremental numbers).
var myShape = new createjs.Shape();
myShape.graphics.f("white").rr(0, 0, 300, 300, 12);
myShape1 = myShape.clone();
myShape2 = myShape.clone();
myShape3 = myShape.clone();
//var arr = [null,cellFlasha1, cellFlasha2, cellFlasha3, cellFlasha4];
var arr = [];
for (var i = 1; i <= 4; i++) {
arr.push(["myShape"+i]);
}
stage.addChild(arr[1]);
I can't seem to add and instance to the stage. It does work when I use the array that has been commented out though. Could it be how i've combined a string and value when I push it to the array as an object?
I know I could just add it to stage by doing stage.addChild(myShape1); etc.. but I want to do it via a loop as there as there will be many more instances to come and similar scenarios (I intend to loop how I add the clones too so the number of objects can just be defined once)
I'm relatively new to javascript so my terminology may not be great. Many thanks in advance. Any help would be much appreciated!
Muzaffar is correct that you can access those variables via the window object, but it is generally a code smell to rely on globals for this kind of thing. Is all you need to get an arbitrary number of those shapes into an array? If so, why not try something like this?
function cloneShapeIntoArray(shape, num) {
var shapeArray = [];
for (var i = 0; i <= num; i++) {
shapeArray.push(shape.clone());
}
return shapeArray;
}
function addShapesToStage(shapes, stage) {
for (var i = 0; i <= shapes.length; i++) {
stage.addChild(shapes[i]);
}
}
var myShape = new createjs.Shape();
myShape.graphics.f("white").rr(0, 0, 300, 300, 12);
var shapes = cloneShapeIntoArray(myShape, 3);
// You can do some extra stuff to the shapes here, eg you could make each one a different scale
// shapes[0].scale = 1
// shapes[1].scale = 1.5
// shapes[2].scale = 2
addShapesToStage(shapes, stage);
That allows you to easily control how many copies you want, and does not pollute the global namespace.
Yes you can do this with "window" global object. Something like this
for(var i=1; i<=4; i++) {
window['myShape'+i] = myShape.clone();
}
var arr = [];
for (var i=1; i<= 4; i++) {
arr.push(window['myShape'+i]);
}
For more detail you can see here:
Use dynamic variable names in JavaScript
Observe:
var groupedLinks = new Array;
for(var i = 0; i < 5; i++) {
linkName = "59notgonnawork" + i;
groupedLinks[linkName] = new Array;
}
I would have expected the result to be the array groupedLinks to be filled up with 5 new keys, the value would be 5 empty arrays.
The actual result in extendscript would be ... grouplinks ... empty.
If I would change this example to be:
var groupedLinks = new Array;
for(var i = 0; i < 5; i++) {
linkName = "notgonnawork" + i;
groupedLinks[linkName] = new Array;
}
It would work perfectly. The only change is the missing "59" at the start of the string used for the array key.
Note that this works perfectly when I run it in console for chrome or firefox. It seems to be indesign and/or extendscript fooling around.
Anything have any ideas why ? I've meanwhile worked around the problem but I'm intrigued.
I would have expected the result to be the array groupedLinks to be filled up with 5 new keys, the value would be 5 empty arrays.
That's exactly what it does, but the way you're viewing the data is likely concealing it because you're not using the proper data structure. Also, property access won't work without using [] because identifiers may not start with a number, so you'd need:
groupedLinks["59notgonnawork0"]
What you're doing isn't meant for arrays, which are expecting sequential numeric indices (though they can technically be assigned other properties too). The type of structure you should be using is a plain object instead.
var groupedLinks = {};
for(var i = 0; i < 5; i++) {
const linkName = "59notgonnawork" + i;
groupedLinks[linkName] = new Array; // Array? plain Object? Depends on its use.
}
Why not trying to push the value in the array on each iteration.
var groupedLinks = new Array;
for(var i = 0; i < 5; i++) {
linkName = "59notgonnawork" + i;
groupedLinks.push(linkName);
}
ExtendScript Arrays are great for stocking data per indeces. If you need key/values objects, why not use… Objects ?
var groupedLinks = {};
for(var i = 0; i < 5; i++) {
linkName = "59notgonnawork" + i;
groupedLinks[linkName] = "Whatever…";
}
alert( groupedLinks["59notgonnawork0" ] ); //"Whatever…"
What is the best way to consolidate this code? As it is, it works perfectly, but it needs to go up to maybe 40-50 items long, so it needs to be shortened dramatically, (I assume, with a for loop).
I'm pretty much a novice when it comes to Javascript, and trying to add arrays to an array with a loop is confusing me immensely.
The "vac1.", "vac2." ...etc, variables are used later on in the code to add pointers onto a Google Maps map.
var x = count.count; // x = a value that changes (between 1 & 50)
if(x == 1){
locations = [
[vac1.vacancy_title, vac1.vacancy_latlng, vac1.vacancy_url, vac1.vacancy_location]
];
}
if(x == 2){
locations = [
[vac1.vacancy_title, vac1.vacancy_latlng, vac1.vacancy_url, vac1.vacancy_location],
[vac2.vacancy_title, vac2.vacancy_latlng, vac2.vacancy_url, vac2.vacancy_location]
];
}
if(x == 3){
locations = [
[vac1.vacancy_title, vac1.vacancy_latlng, vac1.vacancy_url, vac1.vacancy_location],
[vac2.vacancy_title, vac2.vacancy_latlng, vac2.vacancy_url, vac2.vacancy_location],
[vac3.vacancy_title, vac3.vacancy_latlng, vac3.vacancy_url, vac3.vacancy_location]
];
}
...etc etc...
I have tried using a for loop, but it doesn't work and I have no idea if I am anywhere close to figuring out how to do it correctly.
var x = count.count;
locations = [];
array = [];
for (i = 0; i < x; i++) {
array = [vac[i].vacancy_title, vac[i].vacancy_latlng, vac[i].vacancy_url, vac[i].vacancy_location];
locations.push(array);
}
Any help or advice would be greatly appreciated!
Thank you.
You need to consider them as a string:
var x = 5;
locations = [];
array = [];
for (i = 1; i <= x; i++) {
array = ['vac'+i+'.vacancy_title', 'vac'+i+'.vacancy_latlng', 'vac'+i+'.vacancy_url', 'vac'+i+'.vacancy_location'];
locations.push(array);
}
console.log(locations);
Create an array vac and use your previous code :
var x = count.count;
locations = [],
array = [],
vac = [ /* vac1, vac2, ...., vacn */ ];
for (i = 0; i < x; i++) {
array = [vac[i].vacancy_title, vac[i].vacancy_latlng, vac[i].vacancy_url, vac[i].vacancy_location];
locations.push(array);
}
You could use eval for the variable name and build an new array with another array for the wanted keys.
Basically you should reorganize yor program to use a solution without eval. An array could help. It is made for iteration.
var x = count.count,
i,
keys = ['vacancy_title', 'vacancy_latlng', 'vacancy_url', 'vacancy_location'],
locations = [];
object;
for (i = 1; i <= x; i++) {
object = eval('vac' + i);
locations.push(keys.map(function (k) { return object[k]; }));
}
Group the vac* elements in an array and then use slice to cut out as many as you want, then use map to generate the result array:
var vacs = [vac1, vac2 /*, ...*/]; // group the vacs into one single array
var x = count.count; // x is the number of vacs to generate
var locations = vacs.slice(0, x).map(function(vac) { // slice (cut out) x elements from the arrays vacs then map the cut-out array into your result array
return [vac.vacancy_title, vac.vacancy_latlng, vac.vacancy_url, vac.vacancy_location];
});
Because any global variable is a property of the global object :
var vac1 = "whatever";
console.lof(window.vac1); // => logs "whatever"
console.lof(window["vac1"]); // => accessed as an array, logs "whatever" too
You could use the global object and access it as an array to look for your vac1, vac2, vac3 variables :
var x = count.count, i;
locations = [],
array = [],
var globalObject = window; // or whatever the global object is for you
var vac; // this will be used to store your vac1, vac2, etc.
for (i = 0; i < x; i++) {
vac = globalObject["vac"+i]; // the "vac" + i variable read from the global object
if (vac !== undefined) {
array = [vac.vacancy_title, vac.vacancy_latlng, vac.vacancy_url, vac.vacancy_location];
locations.push(array);
}
}
I need to set the value of every item in this array, counting up.
So, for example, path[0].value = 1, path[1].value = 2 etc...
EDIT: I'm looking for the most efficient way to do this.
I think a for loop is the best way, but I want to learn other ways. Can it be done with the map() method or forEach()? What about a for... in statement? I'd like to do it with pure JS, but if you can teach me a better way with jQuery, I'd be interested to learn that too.
Thanks in advance.
function Cell(x,y){
this.xCoordinate = x;
this.yCoordinate = y;
this.value;
}
var path = [new Cell(0,0), new Cell(0,1), new Cell(0,2)];
You can use a for loop or forEach:
for(var i=0; i<path.length; ++i)
path[i].value = i+1;
path.forEach(function(cell, i) {
cell.value = i + 1;
});
Better avoid for...in because of Why is using “for…in” with array iteration such a bad idea?.
If you have an existing array, you can use map.
var path = [0,1,2].map( x => new Cell(0, x))
or to mutate
path = path.map( x => {
x.value = x.yCoordinate - 1
return x
})
A simple for loop should work:
var path = [],
len = 10;
for (
var idx = 0;
idx < len;
path.push(new Cell(0,++idx))
)
<html>
<body>
<p id="demo"></p>
<script>
function Cell(x,y){
this.xCoordinate = x;
this.yCoordinate = y;
this.value;
}
function setValues(element, index, array){
array[index].value = index+1;
}
var path = [new Cell(0,0), new Cell(0,1), new Cell(0,2)];
path.forEach(setValues);
document.getElementById("demo").innerHTML = path[2].value;
</script>
</body>
</html>
What I'm basically trying to do is to map an array of data points into a WebGL vertex buffer (Float32Array) in realtime (working on animated parametric surfaces). I've assumed that representing data points with Float32Arrays (either one Float32Array per component: [xx...x, yy...y] or interleave them: xyxy...xy) should be faster than storing them in an array of points: [[x, y], [x, y],.. [x, y]] since that'd actually be a nested hash and all. However, to my surprise, that leads to a slowdown of about 15% in all the major browsers (not counting array creation time). Here's a little test I've set up:
var points = 250000, iters = 100;
function map_2a(x, y) {return Math.sin(x) + y;}
var output = new Float32Array(3 * points);
// generate data
var data = [];
for (var i = 0; i < points; i++)
data[i] = [Math.random(), Math.random()];
// run
console.time('native');
(function() {
for (var iter = 0; iter < iters; iter++)
for (var i = 0, to = 0; i < points; i++, to += 3) {
output[to] = data[i][0];
output[to + 1] = data[i][1];
output[to + 2] = map_2a(data[i][0], data[i][1]);
}
}());
console.timeEnd('native');
// generate data
var data = [new Float32Array(points), new Float32Array(points)];
for (var i = 0; i < points; i++) {
data[0][i] = Math.random();
data[1][i] = Math.random();
}
// run
console.time('typed');
(function() {
for (var iter = 0; iter < iters; iter++)
for (var i = 0, to = 0; i < points; i++, to += 3) {
output[to] = data[0][i];
output[to + 1] = data[1][i];
output[to + 2] = map_2a(data[0][i], data[1][i]);
}
}());
console.timeEnd('typed');
Is there anything I'm doing wrong?
I think your problem is that you are not comparing the same code. In the first example, you have one large array filled with very small arrays. In the second example, you have two very large arrays, and both of them need to be indexed. The profile is different.
If I structure the first example to be more like the second (two large generic arrays), then the Float32Array implementation far outperforms the generic array implementation.
Here is a jsPerf profile to show it.
In V8 variables can have SMI (int31/int32), double and pointer type. So I guess when you operate with floats it should be converted to double type. If you use usual arrays it is converted to doubles already.