Day22 - 鼠標錨點動畫生成指南

本文出自:春哥我的博客:http://www.liyuechun.org
做者:©黎躍春-追時間的人
簡介:JavaScript30Wes Bos 推出的一個 30 天挑戰。項目免費提供了 30 個視頻教程、30 個挑戰的起始文檔和 30 個挑戰解決方案源代碼。目的是幫助人們用純 JavaScript 來寫東西,不借助框架和庫,也不使用編譯器和引用。如今你看到的是這系列指南的第 22 篇。完整中文版指南及視頻教程在 從零到壹全棧部落javascript

效果圖

第22天的練習是一個動畫練習,當鼠標移動到錨點處,會有一個白色的色塊移動到當前錨點所在的位置。演示圖以下所示:css

HTML源碼

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>???Follow Along Nav</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>

    <nav>
        <ul class="menu">
            <li><a href="">Home</a></li>
            <li><a href="">Order Status</a></li>
            <li><a href="">Tweets</a></li>
            <li><a href="">Read Our History</a></li>
            <li><a href="">Contact Us</a></li>
        </ul>
    </nav>

    <div class="wrapper">
        <p>Lorem ipsum dolor sit amet, <a href="">consectetur</a> adipisicing elit. Est <a href="">explicabo</a> unde natus
            necessitatibus esse obcaecati distinctio, aut itaque, qui vitae!</p>
        <p>Aspernatur sapiente quae sint <a href="">soluta</a> modi, atque praesentium laborum pariatur earum <a href="">quaerat</a>            cupiditate consequuntur facilis ullam dignissimos, aperiam quam veniam.</p>
        <p>Cum ipsam quod, incidunt sit ex <a href="">tempore</a> placeat maxime <a href="">corrupti</a> possimus <a href="">veritatis</a>            ipsum fugit recusandae est doloremque? Hic, <a href="">quibusdam</a>, nulla.</p>
        <p>Esse quibusdam, ad, ducimus cupiditate <a href="">nulla</a>, quae magni odit <a href="">totam</a> ut consequatur
            eveniet sunt quam provident sapiente dicta neque quod.</p>
        <p>Aliquam <a href="">dicta</a> sequi culpa fugiat <a href="">consequuntur</a> pariatur optio ad minima, maxime <a href="">odio</a>,
            distinctio magni impedit tempore enim repellendus <a href="">repudiandae</a> quas!</p>
    </div>

</body>

</html>

CSS源碼

html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  min-height: 100vh;
  margin: 0;
  /* Important! */
  font-family: sans-serif;
  background: linear-gradient(45deg, hsla(340, 100%, 55%, 1) 0%, hsla(340, 100%, 55%, 0) 70%), linear-gradient(135deg, hsla(225, 95%, 50%, 1) 10%, hsla(225, 95%, 50%, 0) 80%), linear-gradient(225deg, hsla(140, 90%, 50%, 1) 10%, hsla(140, 90%, 50%, 0) 80%), linear-gradient(315deg, hsla(35, 95%, 55%, 1) 100%, hsla(35, 95%, 55%, 0) 70%);
}

.wrapper {
  margin: 0 auto;
  max-width: 500px;
  font-size: 20px;
  line-height: 2;
  position: relative;
}

a {
  text-decoration: none;
  color: black;
  background: rgba(0, 0, 0, 0.05);
  border-radius: 20px
}

.highlight {
  transition: all 0.2s;
  border-bottom: 2px solid white;
  position: absolute;
  top: 0;
  background: white;
  left: 0;
  z-index: -1;
  border-radius: 20px;
  display: block;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2)
}

.menu {
  padding: 0;
  display: flex;
  list-style: none;
  justify-content: center;
  margin: 100px 0;
}

.menu a {
  display: inline-block;
  padding: 5px;
  margin: 0 20px;
  color: black;
}

JS源碼

<script>
   const triggers = document.querySelectorAll('a');
   const highlight = document.createElement('span');
   highlight.classList.add('highlight');
   document.body.appendChild(highlight);

   function highlightLink() {
       const linkCoords = this.getBoundingClientRect();
       // console.log(linkCoords);
       const coords = {
           width: linkCoords.width,
           height: linkCoords.height,
           top: linkCoords.top + window.scrollY,
           left: linkCoords.left + window.scrollX
       };

       highlight.style.width = `${coords.width}px`;
       highlight.style.height = `${coords.height}px`;
       highlight.style.transform = `translate(${coords.left}px, ${coords.top}px)`;

   }

   triggers.forEach(a => a.addEventListener('mouseenter', highlightLink));
</script>

代碼解釋

  • 經過HTML源碼咱們不難發現,全部錨點都是由a標籤組成,因此在js代碼中咱們首先先獲取全部的a標籤對象,將其存儲到triggers變量中。
const triggers = document.querySelectorAll('a');
  • 在效果圖中高亮狀態的小塊其實就是一個span標籤,在JS代碼中建立了一個span標籤,而且爲其添加了一個highlightclass
const highlight = document.createElement('span');
highlight.classList.add('highlight');
document.body.appendChild(highlight);
  • 對全部的a標籤進行事件監聽,當鼠標移動到錨點時,會自動觸發highlightLink方法。
triggers.forEach(a => a.addEventListener('mouseenter', highlightLink));
  • getBoundingClientRect()

getBoundingClientRecthtml

Element.getBoundingClientRect()方法返回元素的大小及其相對於視口的位置。java

語法:git

rectObject = object.getBoundingClientRect();

值:
返回值是一個 DOMRect 對象,這個對象是由該元素的 getClientRects() 方法返回的一組矩形的集合, 即:是與該元素相關的CSS 邊框集合 。github

DOMRect屬性表:api

屬性 類型 描述
bottom float Y 軸,相對於視口原點(viewport origin)矩形盒子的底部。只讀
height float 矩形盒子的高度(等同於 bottom 減 top)。只讀
left float X 軸,相對於視口原點(viewport origin)矩形盒子的左側。只讀
right float X 軸,相對於視口原點(viewport origin)矩形盒子的右側。只讀
top float Y 軸,相對於視口原點(viewport origin)矩形盒子的頂部。只讀
width float 矩形盒子的寬度(等同於 right 減 left)。只讀
x float X軸橫座標,矩形盒子左邊相對於視口原點(viewport origin)的距離。只讀
y float Y軸縱座標,矩形盒子頂部相對於視口原點(viewport origin)的距離。只讀

DOMRect 對象包含了一組用於描述邊框的只讀屬性——left、top、right和bottom,單位爲像素。除了 width 和 height 外的屬性都是相對於視口的左上角位置而言的。app

空邊框盒(譯者注:沒有內容的邊框)會被忽略。若是全部的元素邊框都是空邊框,那麼這個矩形給該元素返回的 width、height 值爲0,left、top值爲第一個css盒子(按內容順序)的top-left值。框架

當計算邊界矩形時,會考慮視口區域(或其餘可滾動元素)內的滾動操做,也就是說,當滾動位置發生了改變,top和left屬性值就會隨之當即發生變化(所以,它們的值是相對於視口的,而不是絕對的)。若是不但願屬性值隨視口變化,那麼只要給top、left屬性值加上當前的滾動位置(經過window.scrollX和window.scrollY),這樣就能夠獲取與當前的滾動位置無關的常量值。ide

  • highlightLink方法
function highlightLink() {
  const linkCoords = this.getBoundingClientRect();
  // console.log(linkCoords);
  <!--`coords`計算座標,寬和高。-->
  const coords = {
      width: linkCoords.width,
      height: linkCoords.height,
      top: linkCoords.top + window.scrollY,
      left: linkCoords.left + window.scrollX
  };

<!--高亮狀態的span標籤的樣式設置-->
  highlight.style.width = `${coords.width}px`;
  highlight.style.height = `${coords.height}px`;
  highlight.style.transform = `translate(${coords.left}px, ${coords.top}px)`;

}

完結!

源碼下載

Github Source Code

相關文章
相關標籤/搜索