使用 JavaScript 和构造函数的动态变量名称:使用 EaselJS 将图像动态克隆到多个画布

Dynamic variable names with JavaScript and constructor: cloning an image with EaselJS dynamically to multiple canvases

本文关键字:动态 使用 图像 EaselJS 构造函数 JavaScript 变量名      更新时间:2023-09-26

我正在尝试使用应用于构造函数的JavaScript中的动态变量名称。这比预期的要困难得多。我已经在许多论坛和网页上读到过这个问题,但我找不到我做错了什么。

我正在使用一个名为EaselJS的HTML5 + JavaScript库,但我的问题与它无关,而是与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"));

代码仍然有效。但是我不知道如何使用引号中的画布 id 完成类似的解决方案。以下代码行失败:

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 WORK
          //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>

不确定我是否理解评估或预先计算变量名称等等的意义。 似乎你可以这样做

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

window["varname"]无济于事,除非varname是全球性的,而且......呵呵 如果可以的话,你会想要避免全局变量。 无论哪种方式,您都不需要转义引号——您根本不需要在名称本身中使用引号,除非您的 ID 中有引号(无论如何,AFAIK 都是无效的)或者您正在评估(这本身就是邪恶的)。

如果您希望将阶段放入数组中(这似乎是一个更好的目标),您将希望您的第一个阶段stage[0] . 在这种情况下,请设置 stage[i-1] 而不是 stage[i]

如果你想设置stage1stage2等......停。 别这样。 你有一堆物品,你对待得一模一样......这就是数组的用途。 首先,请注意使用数组元素比使用名称相似的变量容易得多? 我什至没有看到问题,因为对于数组来说,这已经不是问题了。

至于你的代码...看这个。

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中断切换到使用数组,现在我们可以拥有任意数量的阶段。

我想你想要这个:

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));
}

与其使用带有数字后缀的 id 来引用您的画布,不如通过标签名称获取它们:

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 的新功能,但如果浏览器支持 JS5,<canvas>则支持 JS5。 无论如何,这里是可用于支持旧版浏览器的Array.map()实现的链接,以防您必须支持较旧的浏览器并且尚未使用 JS5 填充程序。

(代表问题作者发布解决方案以将其移动到答案空间)。

我将发布最终代码,供想要使用 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>