【问题标题】:Hover effect reset when hovering over other letters悬停在其他字母上时重置悬停效果
【发布时间】:2021-04-16 03:33:25
【问题描述】:

我在 JavaScript (JS) 中制作了一个文本动画,其中悬停的单词会随着时间的推移逐个字母地改变颜色。我只想在单词不再悬停时重置文本动画。

但是,当我将鼠标悬停在单词上并将光标移到单词中的另一个字母上时,悬停动画会重置。有人可以解释它为什么会这样以及我如何能够解决这个问题吗?

const home = document.querySelector("#home");
const homeText = home.textContent;
const splitHomeText = homeText.split("");

home.textContent = "";
for (let i = 0; i < splitHomeText.length; i++) {
  home.innerHTML += "<span>" + splitHomeText[i] + "</span>";
}

let char = 0;
let timer = null;
home.addEventListener("mouseover", highlight);
home.addEventListener("mouseout", clear);

function highlight() {
  timer = setInterval(onTickHome, 50);
}

function onTickHome() {
  const span = home.querySelectorAll("span")[char];
  span.classList.add("highlight");
  char++;
  if (char === splitHomeText.length) {
    complete();
    return;
  }
}

function complete() {
  char = 0;
  clearInterval(timer);
}

function clear() {
  char = 0;
  clearInterval(timer);
  for (let i = 0; i < splitHomeText.length; i++) {
    const span = home.querySelectorAll("span")[i];
    span.classList.remove("highlight");
  }
}
#home {
  text-decoration: none;
  color: black;
  font-size: 30px;
}

.highlight {
  color: #EF233C;
}
&lt;a href="#" id="home"&gt;Home&lt;/a&gt;

【问题讨论】:

    标签: javascript html css


    【解决方案1】:

    更多信息请参考answer

    const home = document.querySelector("#home");
    const homeText = home.textContent;
    const splitHomeText = homeText.split("");
    
    home.textContent = "";
    for(let i = 0; i < splitHomeText.length; i++){
      home.innerHTML += "<span>" + splitHomeText[i] + "</span>";
    }
    
    let char = 0;
    let timer = null;
    home.addEventListener("mouseenter", highlight);
    home.addEventListener("mouseleave", clear);
    
    function highlight() {
      timer = setInterval(onTickHome, 50);
    }
    
    function onTickHome() {
      const span = home.querySelectorAll("span")[char];
      span.classList.add("highlight");
      char++;
      if(char === splitHomeText.length) {
        complete();
        return;
      }
    }
    
    function complete() {
      char = 0;
      clearInterval(timer);
    }
    
    function clear() {
      char = 0;
      clearInterval(timer);
      for(let i = 0; i < splitHomeText.length; i++){
        const span = home.querySelectorAll("span")[i];
        span.classList.remove("highlight");
      }
    }
    #home {
        text-decoration: none;
        color: black;
        font-size: 30px;
    }
    
    .highlight {
        color:#EF233C;
    }
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="style.css">
        <title>Hover Text Animation</title>
    </head>
    <body>
        <a href="#" id="home">Home</a>
    
        <script src="app.js"></script>
    </body>
    </html>

    【讨论】:

      【解决方案2】:
      • 更可重用的东西是不依赖于 ID。
      • 使用 CSS transition-delay 为跨度着色计时(无需复杂的间隔)

      const CharAnim = (sel, color = "#0bf") => {
      
        const anim = (ev, isIn) =>
          ev.currentTarget.querySelectorAll("span").forEach((EL, i) =>
            EL.style.cssText = `
              transition: 0.2s ease ${(isIn ? 30*i : 0)}ms;
              color: ${(isIn ? color : "")};
            `);
            
        document.querySelectorAll(sel).forEach(EL => {
          EL.addEventListener("mouseenter", ev => anim(ev, 1));
          EL.addEventListener("mouseleave", ev => anim(ev, 0));
          EL.innerHTML = EL.textContent.replace(/./g, "<span>$&</span>");
        });
      
      };
      
      
      CharAnim("a", "#EF233C");
      CharAnim(".test1", "#FB0");
      CharAnim(".test2"); // Use default color
      a {
        text-decoration: none;
        color: #000;
        font-size: 30px;
      }
      <a href="#">Home</a><br>
      <a href="#">Don't use IDs. Programming is not copy/pasting</a>
      <div class="test1">Lorem ipsum</div>
      <div class="test2">Dolor sit amet</div>

      【讨论】:

        【解决方案3】:

        问题询问为什么将鼠标从一个字符移动到另一个字符会导致突出显示消失。

        问题的出现是因为当鼠标离开 div 的任何后代时,会触发在 div(整个单词)上设置的 mouseout 事件。所以 clear 会在鼠标远离单个字符的任何移动时调用。

        我们需要的是当鼠标离开 div/word 时触发的东西,而不是每个 span 元素。事件 mouseleave 给了我们想要的东西。见MDN

        当指针离开元素及其所有后代时触发mouseleave,而当指针离开元素或离开元素的后代之一时触发mouseout(即使指针仍在元素内)。

        因此寻找 mouseleave 事件而不是 mouseout 事件可以解决颜色变化问题的过早重置问题。

        const home = document.querySelector("#home");
        const homeText = home.textContent;
        const splitHomeText = homeText.split("");
        
        home.textContent = "";
        for(let i = 0; i < splitHomeText.length; i++){
          home.innerHTML += "<span>" + splitHomeText[i] + "</span>";
        }
        
        let char = 0;
        let timer = null;
        home.addEventListener("mouseenter", highlight);
        home.addEventListener("mouseleave", clear);
        
        function highlight() {
          timer = setInterval(onTickHome, 50);
        }
        
        function onTickHome() {
          const span = home.querySelectorAll("span")[char];
          span.classList.add("highlight");
          char++;
          if(char === splitHomeText.length) {
            complete();
            return;
          }
        }
        
        function complete() {
          char = 0;
          clearInterval(timer);
        }
        
        function clear() {
          char = 0;
          clearInterval(timer);
          for(let i = 0; i < splitHomeText.length; i++){
            const span = home.querySelectorAll("span")[i];
            span.classList.remove("highlight");
          }
        }
        #home {
            text-decoration: none;
            color: black;
            font-size: 30px;
        }
        
        .highlight {
            color:#EF233C;
        }
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <link rel="stylesheet" href="style.css">
            <title>Hover Text Animation</title>
        </head>
        <body>
            <a href="#" id="home">Home</a>
        
            <script src="app.js"></script>
        </body>
        </html>

        【讨论】:

          猜你喜欢
          • 2016-11-08
          • 2017-10-25
          • 1970-01-01
          • 1970-01-01
          • 2023-04-04
          • 2016-06-15
          • 1970-01-01
          • 2016-06-09
          • 1970-01-01
          相关资源
          最近更新 更多