Имена на динамични променливи с Javascript и конструктор: клониране на изображение с EaselJS динамично на множество платна

Добър ден! Тук съм, за да помоля за помощ относно имена на динамични променливи в Javascript, приложени към конструктор. Беше много по-трудно от очакваното. Четох за този проблем в много форуми и уеб страници, но не мога да намеря какво правя погрешно =/

Използвам библиотека HTML5+Javascript, наречена EaselJS, но проблемът ми не е свързан с нея, а със синтаксиса на Javascript! Ето моя проблем. Получих този код:

stage1 = new Stage(document.getElementById("cnvs1"));
stage2 = new Stage(document.getElementById("cnvs2"));
stage3 = new Stage(document.getElementById("cnvs3"));

Тук променливите stage са присвоили Stage обект, който се инициализира с canvas id cnvs Този ред (в контекста на останалата част от моя код) работи! Бих искал да опростя това до един ред с for като това:

for(i = 0; i < 5; i++){
  //Of course this is wrong!
  stage[i] = new Stage(document.getElementById("cnvs[i]"));
}

Тази връзка тук възобновява как може да се направи това: С eval (много хора казват, че не е препоръчително) и с прозорец (препоръчително) Тогава, ако направя това (без for, за да опростя още повече):

var varname = "stage";
var i = 1;
window[varname + i] = new Stage(document.getElementById("cnvs_terminal1"));

Кодът все още работи. Но не мога да разбера как да постигна подобно решение с идентификатора на платното в кавички. Тези редове код са неуспешни:

var i = 1;
var varname = "stage";
var varname2 = 'cnvs1';
var varname3 = "\"cnvs1\"";
var varname4 = "\"cnvs1" + i + "\"";

window[varname +i] = new Stage(document.getElementById(window[varname2]));
window[varname +i] = new Stage(document.getElementById(window[varname3]));
window[varname +i] = new Stage(document.getElementById(window[varname4]));

При тези опити дори да се опитвам да предам точната стойност, от която се нуждая (без i), това не ми помага!! Нарязвам обратно наклонените кавички, защото смятам, че са необходими за getElementbyId=( =( =(

Сега съм безумен! =( Сигурен съм, че има начин да направя това, може би не знам синтаксиса, може би не знам как да извиквам променливи с препратка или по стойност правилно, не знам... Моля, помогнете аз, не знам как да направя тази проста задача!

БЛАГОДАРЯ МНОГО =)

РЕДАКТИРАНЕ: Опитвайки предложението @cHao, също не мога да го направя! Поддържайки го просто, зададох for for i да бъде само едно:

for (var i = 1; i <= 1; ++i) {
  //I use only one of the following lines at a time of course, but I'll write here my failing tries all together:
  stage[i] = new Stage(document.getElementById('cnvs'+i));
  stage[i-1] = new Stage(document.getElementById('cnvs'+i));

  //Hardcoding the first variable works!
  stage1 = new Stage(document.getElementById('cnvs'+i));
}

Половината от проблема е решен, но какво да правим с първата променлива? =/ БЛАГОДАРЯ!!!!

РЕДАКТИРАНЕ 2: Поискани са повече подробности! Ето пример за копиране/поставяне! Просто актуализирайте EaselJS и пътищата на изображението, за да работи това!

<!DOCTYPE HTML>
<html>
  <head>
    <script src="easeljs-0.4.0-26/lib/easel.js"></script>       

    <script type="text/javascript"> 
      function init() {
        //MY PROBLEM LIES HERE!!
        for (var i = 1; i <= 1; ++i) {
          //This code WORKS
          stage1 = new Stage(document.getElementById('cnvs'+i));
          //This code DOES NOT WORKS
          //stage[i] = new Stage(document.getElementById('cnvs'+i));
          //stage[i-1] = new Stage(document.getElementById('cnvs'+i));
        }
        var images = "images/itzapic.jpg";
        bitmap = new Bitmap(images);
        stage1.addChild(bitmap);
        stage1.update();
        Ticker.addListener(window);
      }

      function tick() {
        stage1.update();
      }
    </script>        
  </head>

  <body onload="init()"> 
    <canvas id="cnvs1" width="140" height="82">
  </body>
</html>

______________ ________________ _____________

РЕДАКТИРАНЕ 3: РАЗРЕШЕНО! Ще публикувам крайния код за справка на някой, който иска да използва EaselJS, за да изобрази едно изображение в толкова платна, колкото е необходимо, с един и същ обект . За целта ще ви трябва метода bitmap.clone() и масиви за етапите. Благодаря на @cHao, че ми помогна ;) Следният код ще изобрази едно и също изображение във всички платна! Актуализирайте при необходимост ;)

<!DOCTYPE HTML>
<html>
  <head>
    <script src="easeljs-0.4.0-26/lib/easel.js"></script>       

    <script type="text/javascript"> 
      stage = [];
      function init() {
        for (var i = 1; i <= 6; ++i) {
          stage[i-1] = new Stage(document.getElementById('cnvs'+i));
        }
        var images = "images/itzapic.jpg";
        bitmap = new Bitmap(images);
        stage[0].addChild(bitmap);
        for (var i = 1; i <= 5; ++i) {
          stage[i].addChild(bitmap.clone());
        }
        stage[0].update();
        Ticker.addListener(window);
        }

        function tick() {
        for (var i = 0; i < stage.length; ++i) {
          stage[i].update();
        }
      }
</script>        
</head>

  <body onload="init()"> 
    <canvas id="cnvs1" width="140" height="82"></canvas>
    <canvas id="cnvs2" width="140" height="82"></canvas>
    <canvas id="cnvs3" width="140" height="82"></canvas>
    <canvas id="cnvs4" width="140" height="82"></canvas>
    <canvas id="cnvs5" width="140" height="82"></canvas>
    <canvas id="cnvs6" width="140" height="82"></canvas>
  </body>
</html>

person Metafaniel    schedule 11.04.2012    source източник
comment
Защо не използвате масиви, както е предложено във втория ви кодов фрагмент.   -  person Kapil    schedule 12.04.2012
comment
Благодаря, @Kapil, направих го, но имах нужда от насоки;)   -  person Metafaniel    schedule 12.04.2012


Отговори (3)


Не съм сигурен, че разбирам смисъла от оценяването или предварителното изобразяване на имена на променливи и всичко това. Изглежда, че можете просто да правите нещо подобно

for (var i = 1; i <= 5; ++i) {
    stage[i] = new Stage(document.getElementById('cnvs' + i));
}

window["varname"] няма да помогне, освен ако varname не е глобален и...ех. Ще искате да избягвате глобалните, ако можете. И в двата случая не е нужно да избягвате кавички -- изобщо не се нуждаете от кавички в самото име, освен ако вашите идентификатори не съдържат кавички (което AFAIK така или иначе е невалидно) или оценявате (което е зло само по себе си).

Ако искате да поставите етапите в масив (което изглежда като по-добра цел), ще искате първият ви етап да бъде stage[0]. В този случай задайте stage[i-1] вместо stage[i].

И ако се опитвате да зададете stage1, stage2 и т.н... спрете. недей така Имате куп предмети, които третирате еднакво... за такива неща са предназначени масивите. От една страна, забележете колко по-лесно е да работите с елементи от масив, отколкото променливи с подобни имена? Дори не виждах проблема, защото с масивите вече не е проблем.

Колкото до вашия код...гледайте това.

stage = [];

function init() {
    for (var i = 1; i <= 1; ++i) {
        stage[i-1] = new Stage(document.getElementById('cnvs'+i));
    }
    var images = "images/itzapic.jpg";
    bitmap = new Bitmap(images);
    stage[0].addChild(bitmap);
    stage[0].update();
    Ticker.addListener(window);
}

function tick() {
    for (var i = 0; i < stage.length; ++i) {
        stage[i].update();
    }
}

След като преминем от stage1 stage2 счупеността към използване на масив, сега можем да имаме колкото си искаме етапи.

person cHao    schedule 11.04.2012
comment
Съжалявам, че забравих да кажа във въпроса си, че опитах това преди, ще редактирам въпроса си с това. В синтез вече опитах без успех! Какво би могло да бъде? =( - person Metafaniel; 12.04.2012
comment
@Metafaniel: Добре...какво точно се опитваш да направиш? Отговорете ясно и точно. Защото това е доста лесен начин да направите това, което повечето хора трябва да направят. Ако имате нужда от нещо различно, тогава промяната зависи от това как вашият проблем се различава от това, което си мисля, че е. - person cHao; 12.04.2012
comment
ДОБРЕ! Ще изясня още повече с пример за копиране/поставяне след минута, благодаря! - person Metafaniel; 12.04.2012
comment
ах Спрете да правите етап 1, етап 2. Използвайте масив като истински програмист. :) - person cHao; 12.04.2012
comment
ХЕХЕ Знам, че знам =P Благодаря, но просто не мога да се справя с тази наглед проста задача! Добавих примера с вашето предложение, което не работи =( - person Metafaniel; 12.04.2012
comment
Не можете да направите тази привидно проста задача, защото не е толкова проста с куп променливи. Гледай това. (редактиран) - person cHao; 12.04.2012
comment
О УАУ!!! Страхотен! Виждам изображението! Но е необходим малко повече код, за да работи това точно както искам, но почти е решено! Изчакайте... - person Metafaniel; 12.04.2012
comment
ИМАМ ГО!! Последният код за това, от което се нуждаех. МНОГО БЛАГОДАРЯ! Ще го добавя към въпроса си като справка! БЛАГОДАРЯ!!! Ти наистина ми помогна =D - person Metafaniel; 12.04.2012

Мисля, че искаш това:

var stagePrefix = 'stage';
var canvasPrefix = 'cnvs';
//adjust loop below based on your naming e.g. do they start at 0 or 1?
for(var i=1;i<5;i++){
  window[stagePrefix + i] = new Stage(document.getElementById(canvasPrefix + i));
}
person scunliffe    schedule 11.04.2012
comment
ХЕЙ!!! Това всъщност решава проблема ми! Работи =D Ако само този начин не създаде глобални променливи =/ Може ли да има начин да се постигне това без да се използва Window?? Ако не дойдат по-добри отговори, вие ще бъдете най-добрият отговор ;) БЛАГОДАРЯ! - person Metafaniel; 12.04.2012
comment
Вашият отговор също ми помогна и реши проблема ми, НО отговорът на @cHao е по-добър, защото той не използва глобални променливи, както направих аз първоначално! Благодаря много и за вашия работещ отговор!! Благодаря =) - person Metafaniel; 12.04.2012
comment
Да, търсех решението, което отговаряше на вашия въпрос... но както отбелязахте, използването на една променлива, която да съдържа всички препратки, е по-добро. - person scunliffe; 12.04.2012

Вместо да използвам идентификатор с цифров суфикс за препратка към вашите платна, бих ги получил по име на етикет:

var canvases = document.getElementsByTagName("canvas");

Или, ако искате да обработите само определен набор от елементи на платното на страницата, дайте им клас:

var canvases = document.getElementsByClassName("cnvs");

След това, за да получите масив от етапи от вашите платна, откраднете метода Array.map()*:

var stages = [].map.call(canvases, function(canvas) {
    return new Stage(canvas);
});



*Array.map() е нов за JS5, но ако вашият браузър поддържа <canvas>, той поддържа JS5. Независимо от това, ето връзката към имплементация на Array.map() вас може да се използва за поддръжка на по-стари браузъри, в случай че трябва да поддържате по-стари браузъри и все още не използвате JS5 подложка.

person gilly3    schedule 11.04.2012
comment
Това звучи доста интересно и горно кодиране хехе. Ще трябва да прочета повече за него по-късно, но не съм сигурен дали мога да го използвам. Използвам Google Chrome 18. Поддържа ли този метод?? - person Metafaniel; 12.04.2012
comment
@Metafaniel - Да, работи във всяка версия на Chrome. Ако вашият браузър поддържа <canvas>, той със сигурност поддържа Array.map(). Ще имате проблеми само с IE8 и IE7. Но добавянето на поддръжка за IE7 и IE8 е тривиално. - person gilly3; 12.04.2012