Имена динамических переменных с помощью 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, который инициализирован с идентификатором холста cnvs. Эта строка (в контексте остальной части моего кода) работает! Я хотел бы упростить это до одной строки с помощью for:

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

Эта ссылка здесь показывает, как это можно сделать: с помощью eval (многие говорят, что это не рекомендуется) и с window (рекомендуется). Тогда, если я сделаю это (без 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 для 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