嵌套for循环同时更新3个变量

时间:2017-01-03 18:03:50

标签: javascript loops

我环顾四周,但没有找到解决办法。

我想打印出'插值'这点之间的分数:

.card.ani25 {
bottom: 72%;
left:85%;
}

和此:

.card.ani49 {
bottom: 46%;
left: 46%;
}

基本上,我正在尝试同时更新该CSS中的所有数值。一次更新一个值有效,但在这种情况下没有用。 我到目前为止所尝试过的一切,包括触发一些无限循环在内的所有想法,但这就是"稳定": - )

for (var i = 25; i < 50; i++){
 for (var j = 72; j >=46; j-=2){
  for (var k = 85; k >=46; k-=3){
t.innerHTML = '.card.ani' + i + ' {' + '<br>' + 'bottom: ' + j + '%;' + '<br>' + 'left: ' + k + '%;' + '<br>' + '}';
  }
 }
}

这只打印出最后一次迭代,如下所示:

http://codepen.io/damianocel/pen/ZLEXOR

如果我在&#34; innerHTML2之后加上+ =,它就会爆炸,屏幕冻结,就像无限循环一样。

我知道,最外面的循环首先运行,然后下一个内循环运行多次,但我从未见过3个变量的情况。老实说,我也不知道2个变量的解决方案。

非常感谢,如果之前有人问过这个问题。

2 个答案:

答案 0 :(得分:1)

问题是通过重新分配innerHTML来更改HTML的操作很慢。当你使用+=时,它会每次重写HTML,这就是导致它变慢的原因。这说它仍然有效,更快的方法是使用变量来保存字符串并更新该变量。然后在最后将t.innerHTML的值分配给该字符串:

var t = document.getElementById('target');
var str = "";
for (var i = 25; i < 50; i++){
 for (var j = 72; j >=46; j-=2){
  for (var k = 85; k >=46; k-=3){
      str += '.card.ani' + i + ' {' + '<br>' + 'bottom: ' + j + '%;' + '<br>' + 'left: ' + k + '%;' + '<br>' + '}';
    }
  }
}

t.innerHTML = str;

修改

在澄清之后,您似乎只需要一个循环并在每次循环中更新变量。在这种情况下,您可以执行以下操作:

var t = document.getElementById('target');
var str = "";
for (var i = 25, j = 72, k = 85; i < 50 && j >=46 && k >=46; i++, j-=2, k-=3){
    str += '.card.ani' + i + ' {' + '<br>' + 'bottom: ' + j + '%;' + '<br>' + 'left: ' + k + '%;' + '<br>' + '}';
}
t.innerHTML = str;

对于for循环for(x;y;z)中的每个部分,您可以使用逗号来生成许多语句。因此,在第一部分中,您可以定义3个变量,在最后一部分中更新3个变量。只要满足所有这些条件,中间部分就会运行循环,当单个条件失败时它会停止。

注意:如果您希望只要其中一个条件成立,就可以使用|| OR )。

<强> Code Pen (single loop)

Code Pen

答案 1 :(得分:1)

我会推广一种非常不同的方法。

我认为这是一些需要并行动画的不同范围。所以我想有一个知道如何做到这一点的函数。

const rangeFns = (...configs) => fn => val => 
  fn.apply(null, configs.map(cfg => (cfg.end - cfg.start) * val + cfg.start))

这将获取范围描述的集合并返回一个函数,该函数接受一个自定义函数,每个范围都有一个参数,最后返回一个接受0到1之间的数字的简单函数,返回自定义函数的结果为各个参数提供的每个范围的插值。这有点拗口,但我觉得它很容易使用:

const anim = rangeFns(
  {start: 25, end: 49},
  {start: 72, end: 46},
  {start: 85, end: 46}
)((ani, bottom, left) => `
  .card.ani${Math.round(ani)} {
    bottom: ${bottom}%;
    left: ${left};
  }`
);

如果你使用0,0.25,0.5,0.75和1的值运行它,你会得到以下结果:

.card.ani25 {
  bottom: 72%;
  left: 85;
}

.card.ani31 {
  bottom: 65.5%;
  left: 75.25;
}

.card.ani37 {
  bottom: 59%;
  left: 65.5;
}

.card.ani43 {
  bottom: 52.5%;
  left: 55.75;
}

.card.ani49 {
  bottom: 46%;
  left: 46;
}

(显然,如果需要,您可以向bottomleft添加舍入。)

然后,您可以通过传递从开始和结束时间计算的值来在动画中使用它。

在我看来,优点是这更明确。它使范围更具说明性,并使使用结果的函数更直接。

Codepen 可以使用此版本。

更新

稍微好一点的版本是使用数组而不是对象。 (我原本在那里有额外的参数,结果是不必要的。我没有注意到删除它们允许一个很好的清理。)

const multiRange = (...ranges) => fn => val => 
  fn.apply(null, ranges.map(range => (range[1] - range[0]) * val + range[0]))

const anim = multiRange([25, 49], [72, 46], [85, 46])((ani, bottom, left) => `
  .card.ani${Math.round(ani)} {
    bottom: ${bottom}%;
    left: ${left};
  }`
);

我认为这样做会更好。

此版本也在 Codepen