【问题标题】:Trying to write javascript that fades in background color尝试编写淡入背景颜色的javascript
【发布时间】:2015-08-03 04:02:25
【问题描述】:

我正在尝试自学 javascript,但显然我并没有完全理解。

我想要的是一个框,当您单击它时,背景颜色会从黑色平滑地变为某种颜色。为此,我创建了一个函数,它接受一个 HSV 值并以 #rrggbb 格式输出一个字符串。因此,要淡入,我只需使用 for 循环以 1 为增量将 V 值从 0 移动到 100。

我有一个框,当您单击它时,它会暂停并更改为我正在使用的背景颜色。我还在记录输出,并在最后使用 RGB 十六进制值计算和更新一次。

因此,很明显,我不了解在中间步骤刷新 DOM 所需的任何知识。我为此得到的所有搜索都提出了使用 jQuery 或类似方法的解决方案。这很好,我打算通过 jQuery 等来工作,但首先,我想让一些类似的东西工作,这样我就可以更彻底地了解引擎盖下发生的事情。

代码在这里:http://codepen.io/anon/pen/QbzQJG

代码:

HTML:

<title>Color test</title>

<body>
  <div id="colorbox" onclick="javascript:fadeIn()"></div>
  <div id="console"></div>
</body>

CSS:

  body {
    background: #000;
    color: #999;
  }

  #colorbox {
    background: #000;
    border: 1px solid #333;
    width: 250px;
    height: 250px;
    margin: 0 auto;
  }

Javascript:

var c = function() {
  return ({
    log: function(msg) {
      consoleDiv = document.getElementById('console');
      para = document.createElement('p');
      text = document.createTextNode(msg);
      para.appendChild(text);
      consoleDiv.appendChild(para);
    }
  });
}();

function toRGB(H, S, V) {
  S /= 100;
  V /= 100;
  var C = V * S;
  H /= 60;
  var X = C * (1 - Math.abs((H % 2) - 1));
  var R = 0;
  var G = 0;
  var B = 0;
  if (0 <= H && H < 1) {
    R = C;
    G = X;
    B = 0;
  } else if (1 <= H && H < 2) {
    R = X;
    G = C;
    B = 0;
  } else if (2 <= H && H < 3) {
    R = 0;
    G = C;
    B = X;
  } else if (3 <= H && H < 4) {
    R = 0;
    G = X;
    B = C;
  } else if (4 <= H && H < 5) {
    R = X;
    G = 0;
    B = C;
  } else if (5 <= H && H < 6) {
    R = C;
    G = 0;
    B = X;
  } else {
    R = 0;
    G = 0;
    B = 0;
  }

  var m = V - C;
  R = Math.round(255 * (R + m)).toString(16);
  R.length < 2 ? R = "0" + R : R = "" + R;
  G = Math.round(255 * (G + m)).toString(16);
  G.length < 2 ? G = "0" + G : G = "" + G;
  B = Math.round(255 * (B + m)).toString(16);
  B.length < 2 ? B = "0" + B : B = "" + B;

  var RGB = "#" + R + G + B;
  return RGB;
}

function pause(milliseconds) {
  var dt = new Date();
  while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}

function fadeIn() {
  var colorbox = document.querySelector("#colorbox");
  for (var i = 0; i <= 100; i++) {
    colorbox.style.backgroundColor = toRGB(150, 80, i);
    c.log(toRGB(150, 80, i));
    pause(10);
  }
}

有什么想法吗?

【问题讨论】:

  • 为什么要发明新的轮子。 Jquery UI 库中有一个完美的功能为你做这个jqueryui.com/animate
  • @mimo - 这不是一个好建议。有很多理由不使用 jQuery,实际上使用 vanilla js 越来越普遍
  • @mimo 感谢 jquery 链接。我只是想重新发明轮子,这样我才能了解它是如何工作的。我不一定打算使用它来实现除示例之外的任何内容。我希望我在顶部的文章能防止这种不回答。我想我应该把这个免责声明放在未来更普遍的位置

标签: javascript html css


【解决方案1】:

您的问题在于理解浏览器(以及一般的 JS)中的事件流。 (标准)JavaScript 作为单线程异步进程工作。因此,对于在代码“中间”发生的任何事情,您需要以某种方式将执行返回到调用上下文。当嵌套在 JavaScript 代码中的调用堆栈中时,以及当您想要“查看”代码在浏览器窗口上的效果时,情况都是如此。

您的问题是pause 没有暂停任何内容。它正忙着等待。您需要将控制权交还给浏览器。

你可以这样实现你的目标:

function fadeIn() {
  var colorbox = document.querySelector("#colorbox");

  var i = 0;
  var interval = setInterval(function() {
    if(i > 100) {
      clearInterval(interval);
      return;
    }
    colorbox.style.backgroundColor = toRGB(150, 80, i);
    c.log(toRGB(150, 80, i));
    i++
  }, 10);
}

此解决方案不需要pause

【讨论】:

  • 这正是我需要学习的。谢谢!事件流加上浏览器包含内置调度程序这一事实非常宝贵,让我走上了进一步理解的道路。谢谢!
【解决方案2】:

您的 pass 函数使处理器保持忙碌。因为 JavaScript 是单线程和基于事件的,所以在代码运行时 DOM 不会更新。通过使用setTimeout 暂停执行而不是忙循环,您可以在更改之间进行 DOM 更新,从而显示您的淡入淡出效果。

在这种情况下,fadeIn 的代码如下所示:

function fadeIn(i) {
  if (i >= 100) {return;}
  var colorbox = document.querySelector("#colorbox");
  colorbox.style.backgroundColor = toRGB(150, 80, i);
  c.log(toRGB(150, 80, i));
  setTimeout(function(){fadeIn(i + 1);},10);
}

您的 HTML 调用应该是 fadeIn(0) 并带有此代码。

更多关于 JavaScript 单线程模型的解释可以在this 答案中找到。

您的 codepen 的分叉、改进版本是 here

【讨论】:

  • 这是一个很好的解决方案。谢谢!
【解决方案3】:

你把它复杂化了。您应该使用 CSS 过渡并添加/删除一个类。因此,对于您的 #colorbox,您应该添加 transition 属性:

#colorbox {
    background: #000;
    border: 1px solid #333;
    width: 250px;
    height: 250px;
    margin: 0 auto;

    -webkit-transition: all 500ms ease;
    -moz-transition: all 500ms ease;
    -ms-transition: all 500ms ease;
    -o-transition: all 500ms ease;
    transition: all 500ms ease;
}

那么假设你有一个班级.new-bckgr

.new-bckgr {
    background: #76430; /* or whatever colour you want */
}

现在你需要做的就是这样:

$("#colorbox").on('click', function(){
    $(this).addClass('new-backgr');
});

它会从黑色平滑地褪色到你在.new-bckgr 类中放置的颜色。如果你移除这个类,它会淡出回到变黑

【讨论】:

  • 如果你不喜欢使用其他类来获得新颜色,你可以用.css()api.jquery.com/css更改css
  • 这是一个让淡入淡出工作的好解决方案,但它在没有有意义的 javascript 的情况下这样做。 OP 想学习 javascript 并为此苦苦挣扎,而不是 CSS/DOM/Effects。
  • @Lucian,这对我想要实现的目标没有帮助,学习 javascript。
猜你喜欢
  • 2016-04-05
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 2015-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多