How to declare several CANVAS with different contexts (ctx) in an array? - javascript

I'm using several CANVAS in a HTML file and I want to declare them in an Array. This is the (not array) declaration:
var canvas0 = document.getElementById('canvas0');
var ctxPaint0 = canvas0.getContext('2d');
var canvas1 = document.getElementById('canvas1');
var ctxPaint1 = canvas1.getContext('2d');
var canvas2 = document.getElementById('canvas2');
var ctxPaint2 = canvas2.getContext('2d');
var canvas3 = document.getElementById('canvas3');
var ctxPaint3 = canvas3.getContext('2d');
To optimize this, I'm trying to use For loops, but it doesn't work:
var canvasArray = ["canvas0","canvas1","canvas2","canvas3"];
for (var i = 0; i < canvasArray.length; i++) {
window["canvas"+i] = document.getElementById(canvasArray[i]);
window["ctxPaint"+i] = canvasArray[i].getContext('2d');
}
It outputs this error:
Uncaught TypeError: canvasArray[i].getContext is not a function
EDIT:
Thanks to RSchneyer, changing the Array of strings to an Array of Canvas works fine now:
let canvasArray = Array.from(document.getElementsByTagName("canvas"));
for (var i = 0; i < canvasArray.length; i++) {
window["canvas"+i] = document.getElementById(canvasArray[i]);
window["ctxPaint"+i] = canvasArray[i].getContext('2d');
}

You could do like
const ctxArray = [...document.querySelectorAll('[id^="canvas"]')].map(cvs => cvs.getContext('2d'));
which will result to an array holding all the canvases context - which is all you need, since to get the original canvas out of its context all you need is i.e.:
let i = 0; // or any desired index
const canvas = ctxArray[i].canvas;

canvasArray is an array of strings, which don't have a getContext() function. Try replacing the canvasArray[i] in window["ctxPaint"+i] = canvasArray[i].getContext('2d'); with window["canvas"+i], or create another array to hold your actual canvas variables

Related

web browser crashes invoking REST for Image Data in Uint8ClampedArray JavaScript

In my Project, I have multiple Graphs (max 15 of different plots like Bar , Chart , Bubble, Line) that are being plotted using javascript (Open/SAP UI-5) in HTML5 below is the code for the same
press: function() {
var arrCanvas = document.getElementsByTagName("canvas");
for(var i=0; i<arrCanvas.length; i++){
var canvas = arrCanvas[i];
if(canvas.width!==0 && (typeof imageNames[i] !== 'undefined')){
var imageDetail = {};
var uint8ArrayClamped = canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height).data;
imageDetail.byteData = uint8ArrayClamped;
imageDetail.title = "graph-"+i;
imageDetail.height = canvas.height;
imageDetail.width = canvas.width;
arrImageByte.push(imageDetail);
}
}
}
When I pass this arrImageByte to Ajax call the browser (tested on chrome) crashes with "oh snap" message.
while adding below line to the code
press: function() {
var arrCanvas = document.getElementsByTagName("canvas");
for(var i=0; i<arrCanvas.length; i++){
var canvas = arrCanvas[i];
if(canvas.width!==0 && (typeof imageNames[i] !== 'undefined')){
var imageDetail = {};
var uint8ArrayClamped = canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height).data;
//I belive somwhow This does the trick
imageDetail.byteData = [].slice.call(uint8ArrayClamped);
imageDetail.title = "graph-"+i;
imageDetail.height = canvas.height;
imageDetail.width = canvas.width;
arrImageByte.push(imageDetail);
}
}
}
Copying the unit8ArrayClamped into another empty array does the trick, now the code work and REST is being called, I wonder why this is happening?
but again copying such a huge data into another takes time and for multiple graphs, it takes almost 6-7 seconds, how to reduce this to minimal?
Is there another approach besides copying the byte array into another new array?

Why does this array change its value without being asked to?

I have this array declared like this :
var gamme =
[
["A"],
["A♯","B♭"],
["B","C♭"],
["C","B♯"],
["C♯","D♭"],
["D"],
["D♯","E♭"],
["E","F♭"],
["F","E♯"],
["F♯","G♭"],
["G"],
["G♯","A♭"],
];
using this array, I’m generating another array.
I want temperamentEgal to look like this :
for example :
temperamentEgal[10] = [103.82617439498631, ["G♯","A♭"]]
temperamentEgal[25] = [233.08188075904502, ["A♯","B♭"]]
so this is what I do :
base = pow(2,1/12); // 2^(1/12)
for (i=0; i<12*octaves; i++) // octaves = 6
{
temperamentEgal[i] = []
temperamentEgal[i][0] = 55*pow(base,i); // = 138.6
temperamentEgal[i][1] = gamme[i%12]; // = ["C♯","D♭"]
console.log("gamme["+i%12+"] = " + gamme[i%12]);
for (j=0; j<temperamentEgal[i][1].length; j++)
{
var octaveNote = 1+i/12;
octaveNote = floor(octaveNote);
temperamentEgal[i][1][j] += str(octaveNote);
}
}
As you can see, at no point I’m changing the value of gamme
nonetheless, as the loop progresses, I’m getting this from the console.log :
gamme[0] = A
gamme[1] = A♯,B♭
gamme[2] = B,C♭
gamme[3] = C,B♯
gamme[4] = C♯,D♭
gamme[5] = D
gamme[6] = D♯,E♭
gamme[7] = E,F♭
gamme[8] = F,E♯
gamme[9] = F♯,G♭
gamme[10] = G
gamme[11] = G♯,A♭
gamme[0] = A1
gamme[1] = A♯1,B♭1
gamme[2] = B1,C♭1
gamme[3] = C1,B♯1
gamme[4] = C♯1,D♭1
gamme[5] = D1
gamme[6] = D♯1,E♭1
gamme[7] = E1,F♭1
gamme[8] = F1,E♯1
gamme[9] = F♯1,G♭1
gamme[10] = G1
gamme[11] = G♯1,A♭1
If I comment out temperamentEgal[i][1][j] += str(octaveNote); it’s not happening anymore.
Why would changing the value of temperamentEgal[i][1] change the value of gamme[i%12] as well ?
while you don't change gamme, you change the anonymous arrays referenced on this line:
temperamentEgal[i][1] = gamme[i%12];
both right side and left side of this assignment now point to the same Array objects - if you want to modify a copy of the Array, you should copy the values of the Array, not the reference to the Array object:
ES5: temperamentEgal[i][1] = gamme[i%12].slice();
ES6: temperamentEgal[i][1] = [...gamme[i%12]] using spread operator

Copy array --> stack or heap overflow?

I have an array named globalArrayAllTrades as you see below. I simply like to INVERT the date in a new copy of the array. So I loop through, create a new object and add it to the new array - simple.
Then function does exactly as expected. BUT if the array contains too many objects the code fails with a "FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory".
My laptop has 8 GB of memory...When the NODEJS process crashes it uses about 1.5 GB and about 70% of of totally amount of available memory is used.
I do run the NODEJS app with the parameter: --max_old_space_size=5000 which normally fixes every thing. But not this one and i have tried MANY different ways to code the same function - BUT each and every time - it fails...unless the original array is smaller.
How can I fix this issue?
function invertTrades(){
var original = globalArrayAllTrades.slice();
globalArrayAllTrades.length = 0;
globalListAllTrades.length = 0;
for(var i = 0; i < original.length; i++){
var objS = original[i];
var objE = original[original.length-1-i];
var objInv = new TradePoint(objS.number, objS.matchdate, objE.price, objE.size, objE.issell);
globalArrayAllTrades.push(objInv);
globalListAllTrades[objInv.matchdate] = objInv;
}
}
You can save some memory by making original just contain the properties you need to invert, not the whole TradePoint object. Then you don't need to construct new TradePoint objects, you can modify them in place.
var original = globalArrayAllTrades.map(function(trade) {
return {
trade.price,
trade.size,
trade.issell
};
}).reverse();
globalArrayAllTrades.forEach(function(trade, i) {
trade.price = original[i].price;
trade.size = original[i].size;
trade.issell = original[i].issell;
});
And since all the objects were modified in place, there's no need to update globalListAllTrades.
Another way is to swap the price, size, and issell properties in place between the pairs of elements:
var midpoint = Math.floor(globalArrayAllTrade.length/2);
for (var i = 0; i < midpoint; i++) {
var objS = globalArrayAllTrades[i];
var objE = globalArrayAllTrades[globalArrayAllTrades.length-1-i];
var temp = objS.price;
objS.price = objE.price;
objE.price = temp;
temp = objS.size;
objS.size = objE.size;
objE.size = temp;
temp = objS.issell;
objS.issell = objE.issell;
objE.issell = temp;
}
Have you considered just doing this?
// Copy array and then reverse it
var newArray = [].concat(original).reverse();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse
I would suggest avoiding to copy that array:
function getInverse(i) {
var objS = globalArrayAllTrades[i];
var objE = globalArrayAllTrades[globalArrayAllTrades.length-1-i];
var objInv = new TradePoint(objS.number, objS.matchdate, objE.price, objE.size, objE.issell);
globalListAllTrades[objInv.matchdate] = objInv;
return objInv;
}
function invertTrades(){
globalListAllTrades.length = 0;
for (var i = 0, l = Math.floor(globalArrayAllTrades.length/2); i < l; i++) {
var j = globalArrayAllTrades.length-1-i;
var a = getInverse(i);
var b = getInverse(j);
globalArrayAllTrades[i] = a;
globalArrayAllTrades[j] = b;
}
}

Javascript illustrator loop not working

I am trying to send pathitems to the back of the layer via their selection order, but for some reason as the loop iterates though the selection[i] index it doesn't return them in order
var openDoc = app.activeDocument;
for (var i = 0; i < 3; i++){
var topObject = app.activeDocument.selection[i];
var activelayer = topObject.zOrder(ZOrderMethod.SENDTOBACK);
}
but if I try to unfold the loop it works:
var openDoc = app.activeDocument;
var topObject = app.activeDocument.selection[0];
var activelayer = topObject.zOrder(ZOrderMethod.SENDTOBACK);
var topObject2 = app.activeDocument.selection[1];
var activelayer = topObject.zOrder(ZOrderMethod.SENDTOBACK);
What am i doing wrong?

Illustrator ExtendScript set FILL opacity of selection

Is there any way to access a pathItem's fill opacity with javascript? I can access the overall opacity, but I want to lower the opacity of the fill while keeping the stroke fully opaque.
I can't find anything in the documentation, nor can I find anyone else asking this question.
I can set the overall opacity like so:
var selection = app.activeDocument.selection;
selection[0].opacity = 50;
I've tried every variant of "fillOpacity" that I can think of, like this:
var selection = app.activeDocument.selection;
selection[0].fillOpacity = 50;
selection[0].FillOpacity = 50;
selection[0].fill.opacity = 50;
...but it doesn't work.
Am I going about this wrong, or is this just not possible?
You cannot access it, as you cannot access it normally even in illustrator. This is a Photoshop property only. I checked the documentation as well just to make sure. What you could do is this though and it would accomplish same thing:
doc = app.activeDocument;
i = 0
var selection = doc.selection[i];
var storedColor = doc.selection[i].fillColor;
//new object with only fill, we send it to back so it doesn't overlap stroke, if there is one
var newObject = app.selection[i].duplicate(doc, ElementPlacement.PLACEATEND);
//turn off fill for first object
doc.selection[i].filled = false;
i = i + 1;
newObject.stroked = false;
//apply stored color from earlier to new shape
newObject.fillColor = storedColor;
newObject.opacity = 50;
newObject.name = "50p fill";
What I did to solve the problem is to apply a spotcolor to the objects where I uses the tint property
var docRef = app.activeDocument;
var selectedObjects = docRef.selection;
var theTint;
var fillwithSwatch = function (pathItems, sname ){
for (var i=0;i< pathItems.length; i++){
pathItems[i].fill = true;
theTint = pathItems[i].fillColor.gray;
pathItems[i].fillColor = docRef.swatches.getByName ( sname ).color ;
pathItems[i].fillColor.tint = theTint;
}
}
theTint = fillTint(selectedObjects);
// the spotcolor should be in the swatchpallet already
fillwithSwatch (selectedObjects, "myBlue" );

Categories