当鼠标悬停在某些文本上时,我试图为其添加一个逐渐增加的省略号,然后在鼠标移出时消失。我已经设法创建了效果,但前提是用户必须非常小心地将光标移到受影响的元素上。我如何才能使其表现更好,以便如果用户将光标移动到所有元素上,而我又看不到下面的错误行为(尝试在元素上快速运行光标)?我已经尝试过setInterval,发现问题更加严重。任何帮助表示赞赏。谢谢。



var i=1;
var $test=$();
var mousedOver=0;

function test() {
  if(i!==0) {
    $test.append('<span class="a">.</span>');
  } else {
    $('.a').remove();
  }
  if(mousedOver===1){
    i=(i+1)%4;
    setTimeout(test,1000);
  }
}

$('.nav>p').on('mouseover',function() {
  var $test2=$(this);
  setTimeout(function() {
    $test=$test2;
    mousedOver=1;
    test();
  },1000);
})

$('.nav>p').on('mouseout',function() {
  $test=$();
  mousedOver=0;
  $('.a').remove();
  i=1;
})

.nav {
  display: flex;
  height: 100vh;
  width:30%;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  border-radius:40px;
  border-style: solid;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<head>
</head>
<body>
  <div class="nav">
    <p>text1</p>
    <p>text2</p>
    <p>text3</p>
  </div>
</body>

最佳答案

代码的主要问题是,您仅使用一个标志变量(mousedOver)确定何时应激活3个动画中的任何一个。因此,如果有人将鼠标移到其中一个元素上,它将等待1000ms并将标志设置为1,然后说“确定,我将等待1000ms并再次检查mousedOver是否仍为1”。如果用户将鼠标移开(将mousedOver设置为0),然后在移动1000ms之前移到另一个元素(将mousedOver设置为1),则当第一个元素再次检查并看到mousedOver仍为1时,没有理由停止动画。

有几种方法可以解决此问题:

首先,可以为每个元素使用不同的标志,以便确定该特定元素何时应取消其超时。这是更多的工作,但可能会使内容更易于阅读和理解。

另一个JS解决方案使用clearTimeout方法:将每个超时ID存储在变量中,以便您可以在mouseout上“清除” /取消它们:

的JavaScript


var timeoutID = null;

// Whenever you set a timeout, store its index to be cleared if necessary
timeoutID = setTimeout(test,1000);

// inside the "mouseout" handler
clearTimeout(timeoutID);



请注意,您只需要一个timeoutID变量,因为您将在创建新超时之前清除所有现有超时(onmouseout)。

最后是纯CSS方法。由于您使用的是CSS flex,因此我假设您可以使用CSS3。可以考虑始终将它们放在那里并更改颜色或不透明度,而不是添加/删除这些椭圆,即将CSS colorrgba(0, 0, 0, 0)更改为rgba(0, 0, 0, 1)opacity0更改为1 。当使用其中一个JS流程时,这甚至可能是一个好主意,因为至少您知道当显示点时文本不会四处移动。

在视觉上,此选项与上面的选项之间的主要区别是,这些选项将显示一些“淡入”,这可能不是您想要的。下面的代码显示了如何设置所有“第一”点(设置第二和第三点是相似的)。

的CSS


@keyframes show-first-dot {
  /* Start all the animations transparent */
  0% {
    color: rgba(0, 0, 0, 0);
  }

  /* End transparency at a different % for each dot to control when it fades in */
  50% {
    color: rgba(0, 0, 0, 0);
  }

  /* End all the animations opaque */
  100% {
    color: rgba(0, 0, 0, 1);
  }
}

/* keep dot transparent by default */
.nav > p a {
  color: rgba(0, 0, 0, 0);
}

/* Keep each dot opaque after animation ends */
.nav > p:hover a {
  color: rgba(0, 0, 0, 1);
}

/* Use CSS selectors to assign animations to each dot */
.nav > p:hover a:first-of-type {
  animation-name: show-first-dot;
  animation-duration: 1s;
}

/* ... set up an animation for nth-of-type(2), etc. for as many dots as you want */

07-24 22:04