试图使元素在单击后出现一次,但出现多次

时间:2018-09-29 15:26:48

标签: javascript css function

我试图使形状在单击后出现一次。 1.2秒后,它出现,然后单击消失,然后重复整个过程。问题是单击几下就会出现两个形状。

这是程序的链接。 https://jsfiddle.net/EyedFox/w98naLjx/2/

function show() {
  var randomColor = colors[Math.floor(colors.length * Math.random())]; // Random color chosen
  var randomX = Math.floor(Math.random() * 60); // random x axis margin
  var randomY = Math.floor(Math.random() * 80); // random y axis margin

  square = document.getElementById("square");
  circle = document.getElementById("circle");
  var shapeArray = [square, circle];
  var randShape = shapeArray[Math.floor(shapeArray.length * Math.random())];

  randShape.style.margin = randomX + "% " + randomY + "%";
  randShape.style.backgroundColor = randomColor;
  randShape.style.display = "block";
  randShape.addEventListener("click", click);

  function click() {
    randShape.style.display = "none";
    setTimeout(show, 1200);
  }
}

setTimeout(show, 1200);

3 个答案:

答案 0 :(得分:3)

您的代码不断将click事件监听器添加到randShape中,但它从未清除这些事件。结果,它们不断被添加,click(因此show)每次点击都会执行几次。尝试在点击功能的开头添加console.log('clicked on', randShape);来查看它。如果偶然的情况下,所有show执行都选择了相同的形状,则您只会在屏幕上看到该形状,否则将会得到两者。

您的click函数应如下所示:

function click() {
    console.log('clicked on', randShape);
    randShape.style.display = "none";
    setTimeout(show, 1200);
    randShape.removeEventListener('click', click); // cleaning after myself ;-)
}

(btw (function() { ... })()在加载时不是 执行,而是在javascript vm遇到后立即执行)

答案 1 :(得分:0)

这是解决问题的小提琴。

根据@autra回复编辑了我的回复

在重新绘制之前,我可能会彻底清洁画布:

https://jsfiddle.net/c0L54uk3/

基本上是这样的复位功能:

  function reset(){
     square = document.getElementById("square").style.display = "none";
     circle = document.getElementById("circle").style.display = "none";
     randShape.removeEventListener("click", click);
  }

并在click()函数开始时调用它以重置画布,如下所示:

function click() {
reset();
setTimeout(show, 1200);

}

希望有帮助。

答案 2 :(得分:0)

委托事件,而不是单独注册

addEventListener()应该在回调函数之外(即show())。有一个事件侦听器被添加到clicked标记中,但是没有一个被删除。因此,当发生第4到第7次点击时,浏览器开始放慢速度,并且setTimeout永远不会是1.2秒,因为它将提示启动,这意味着它将等待很长时间然后再等待1.2秒。随着提示的累积,点击次数将超过setTimeout

注册父标记.container,以监听其所有子标记的click事件事件。此模式称为Event Delegation。这样,您可以仅使用一个事件监听器(而不是每个形状一个监听器)将click事件添加到.container中的无限数量的标签中。

#triangle从未设置样式,因此它是一个不可见的div,它在周围浮动。在演示中,我为#triangle设置了样式,并添加了以金色轮廓的.blank <div>(您可以删除.blank)。

演示

Fiddle

演示中评论的详细信息

// Reference parent tag
var box = document.querySelector('.container');

function show() {
  // Collect all .shape into a NodeList and convert into an array
  var shapes = Array.from(document.querySelectorAll('.shape'));
  var colors = ["yellow", "red", "green", "purple", "aqua", "chartreuse", "coral", "dodgerBlue", "deepPink"];

  var rColor = colors[Math.floor(colors.length * Math.random())];
  var rX = Math.floor(Math.random() * 60);
  var rY = Math.floor(Math.random() * 80);
  var rShape = shapes[Math.floor(shapes.length * Math.random())];

  rShape.style.margin = rX + "% " + rY + "%";

  // if #triangle change the border-bottom-color
  if (rShape.id === 'triangle') {
    rShape.style.borderBottomColor = rColor;
    // otherwise change background-color
  } else {
    rShape.style.backgroundColor = rColor;
  }
  rShape.style.display = "block";

}
/* 
Run show()
A setTimeout nor an IIFE is needed to initially run show()
Simply call it.
*/
show();

// Register box to click event...
box.addEventListener('click', function(e) {

  // ...reference the clicked tag (i.e. .shape)...
  var tgt = e.target;

  // ...reference the registered parent tag...
  var cur = e.currentTarget;

  /*
  ...if the clicked tag IS NOT the registered parent tag...
  */
  if (tgt !== cur) {
    // ...then hide clicked element...
    tgt.style.display = "none";
    // ...and run show() in about 1.2 seconds
    setTimeout(show(), 1200);
  }
});
.container {
  overflow: hidden;
  height: 800px;
  width: 80%;
  background-color: rgb(0, 34, 85);
  margin: 0 auto;
  margin-top: 5em;
}

#square {
  width: 80px;
  height: 80px;
  background-color: red;
  margin-left: 0%;
  margin-top: 10%;
  display: none
}

#circle {
  width: 100px;
  height: 100px;
  background: red;
  border-radius: 50px;
  display: none
}

#triangle {
  width: 0;
  height: 0;
  border-left: 45px solid transparent;
  border-right: 45px solid transparent;
  border-bottom: 90px solid cyan;
  display: none
}

.shape {
  cursor: pointer
}

.blank {
  outline: 10px solid gold
}
<div class="container">
  <div id="square" class='shape'></div>
  <div id="triangle" class='shape'></div>
  
  <!--
  This .blank represents what #triangle was before it
  had any style. 
  -->
  <div class='blank'></div>
  <div id="circle" class='shape'></div>
</div>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />