22 Follow Along Link Highliter 中文指南

本篇作者:©大史快跑Dashrun——Chinasoft Frontend Developer

简介:JavaScript30Wes Bos 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 22 篇。完整指南在 GitHub,喜欢请 Star 哦♪(^∇^*)

创建时间:2017-09-12
最后更新:2017-09-16

挑战任务

初始文档index-start.html提供了一组使用<ul><li>标签包裹的导航标签。本次的编程挑战任务是完成如下动画效果:当鼠标移动至某个对应标签上时,为标签添加一个白色的背景框,高亮表示该标签被选中,当鼠标移动至其他标签后,白色背景框不消失,而是直接跟随鼠标平移至新的标签,实现效果见下图展示。

实现效果

结果展示

相关知识

Element.getBoundingClientRect()
Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。
返回值是一个DOMRect对象,这个对象是由该元素的getClientRects()方法返回的一组矩形的集合, 即:是与该元素相关的CSS边框集合。DOMRect 对象包含了一组用于描述边框的只读属性——left、top、right和bottom,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。
DOMRect相关属性:

Attribute Type Description
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)的距离。只读。

编程思路

1.生成一个绝对定位的块元素,在后续改变其topleft坐标值移动至对应标签处,来呈现不同标签被激活的效果;
2.鼠标移动至<li>标签后,使用Element.getBoundingClientRect()方法获得该标签的位置信息;
3.将获得的<li>topleft值赋给绝对定位块元素,使其移动至被激活的标签,位于标签文字下方。

过程指南

1.生成绝对定位块元素

  1. var activeBackground = document.createElement('span');
  2. activeBackground.setAttribute('class','highlight');
  3. document.body.appendChild(activeBackground);
  4. //避免第一次激活时跳动,如果没有此句,可以看到第一次标签被激活时,块元素会从左上角移动至对应标签处。
  5. activeBackground.style.display = 'none';

2.使用Element.getBoundingClientRect()方法获得对应标签的位置信息

  1. function lightOn(e){
  2. var activeLink = e.target.getBoundingClientRect();
  3. var coords = {
  4. height:activeLink.height,
  5. width:activeLink.width,
  6. left:window.pageXOffset + activeLink.left,
  7. top: window.pageYOffset + activeLink.top
  8. }
  9. activeBackground.style.height = `${coords.height}px`;
  10. activeBackground.style.width = `${coords.width}px`;
  11. activeBackground.style.left = `${coords.left}px`;
  12. activeBackground.style.top = `${coords.top}px`;
  13. activeBackground.style.display = 'inline';
  14. }

3.将点亮函数与标签的鼠标移入事件绑定

  1. //监听鼠标移入事件及鼠标移出事件
  2. for(var i = 0; i < len; i++){
  3. oLi[i].onmouseenter = lightOn;
  4. }