製作一個會強調關鍵字的標記,當滑鼠移到某個關鍵字上頭時,標記會從畫面上追隨該關鍵字。範例連結
要讓關鍵字標記真的有追隨過去的效果,只好創造出一個真正的獨立的元素做為該標記,並讓標記移動到希望他移動的位置。步驟如下:
translate
屬性mouseenter
事件首先是創造標記並賦予 CSS,程式碼如下:
const highlight = document.createElement('span');
highlight.classList.add('highlight')
document.body.append(highlight);
CSS 如下:
.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)
}
將標記事先放置在頁面上,但沒賦予長寬,所以呈現隱藏狀態。
接下來選擇所有關鍵字並監聽 mousenter
事件, 只要滑鼠移動到關鍵字上,便會觸發自訂函式 highlightLink
。程式碼如下:
const triggers = document.querySelectorAll('a');
function highlightLink() {
// 標記關鍵字
}
triggers.forEach(a => a.addEventListener('mouseenter', highlightLink));
接下來實現自訂函式的內容,第一步必須讓標記寬高與關鍵字相等,但如何得知關鍵字的寬高呢?此時可以使用元素的 getBoundingClientRect()
方法,程式碼如下:
function highlightLink() {
linkCoords = this.getBoundingClientRect();
highlight.style.width = `${linkCoords.width}px`;
highlight.style.height = `${linkCoords.height}px`;
}
getBoundingClientRect()
方法可以讓我們取得某個元素的長寬以及該元素相對於瀏覽器視窗原點的距離。這裡的 this
指向觸發 mouseenter
的元素。
寬和高分別存在該方法所回傳的物件的 width
和 height
屬性。將其指定給標記,標記便會隨著滑鼠移到的該關鍵字寬高而改變。
我們也可以用一樣的方法取得關鍵字的位置並指定給標記,程式碼如下:
function highlightLink() {
linkCoords = this.getBoundingClientRect();
// 先把寬高、位置資料處理過
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)`;
}
剛有提到由於 getBoundingClientRect()
取得的是相對於「瀏覽器視窗原點」的位置, top
指的是離瀏覽器視窗上方多遠, left
則是離瀏覽器視窗左方多遠,用這種方式來定位。像 Day 13 的示意圖一樣,我們要的是關鍵字在 document
內的位置,所以必須考慮瀏覽器視窗滾動的影響,將瀏覽器視窗的所在位置補償上去。
最後用 transform
屬性的 translate()
函數將標記移動到補償過的位置就大功告成了。
以上就是 JS30 第二十二篇!
原本這篇要分享 JS30 的 Geolocation API 的,但我發現某些資料只有在模擬器之中才會有效,在實體手機卻沒反應,只好等有研究出原因後再找機會和大家分享!
Element.getBoundingClientRect()
完整程式碼