js实现点击选项置顶动画效果

让我详细讲解一下如何实现JS点击选项置顶动画效果的攻略。

1. 思路分析

首先,我们需要明确思路,一般来说实现点击选项置顶的效果,我们需要先获取到页面上所有需要滚动到的位置,然后给所有的选项注册点击事件,当点击某一个选项时,获取需要滚动到的位置,然后使用JS实现滚动动画效果即可。

2. 获取元素的位置信息

在实现滚动动画效果之前,我们首先需要获取每个元素的位置信息,即每个选项需要滚动到的位置。这里,我们可以使用JS的offsetTop属性来获取每个元素的相对于文档顶部的位置,具体代码如下所示:

const navLinks = document.querySelectorAll('.navbar-nav a');
const sections = document.querySelectorAll('section');
const sectionOffsets = [];
for (let i = 0; i < sections.length; i++) {
  sectionOffsets[i] = sections[i].offsetTop;
}

上述代码中,我们首先使用querySelectorAll方法获取到所有的导航链接和页面所有的内容区域,然后使用一个数组sectionOffsets来保存每个内容区域相对于文档顶部的位置。在这里,我们使用了一个循环遍历所有内容区域,并通过offsetTop属性获取每个元素相对于文档顶部的位置信息。

3. 注册点击事件

接下来,我们需要为所有的导航链接注册点击事件,当用户点击某个链接时,页面会滚动到对应的内容区域。这里,我们可以通过addEventListener方法来为每个链接添加click事件,然后在事件处理函数中实现页面滚动的动画效果。具体代码如下所示:

for (let i = 0; i < navLinks.length; i++) {
  navLinks[i].addEventListener('click', function(event) {
    event.preventDefault();
    const targetSection = event.target.getAttribute('data-link');
    const targetOffset = sectionOffsets[targetSection];
    scrollToSection(targetOffset);
  })
}

上述代码中,我们使用了一个循环遍历所有的链接,然后为每个链接添加一个click事件监听器,当链接被点击时,我们会通过getAttribute方法获取到目标内容区域的索引,然后再利用之前获取到的位置信息来实现滚动动画。

可以看到,我们在代码中调用了一个scrollToSection函数来实现动画效果,接下来我们就来实现这个函数。

4. 实现滚动动画

最后一步,我们需要实现滚动动画效果,让页面滑动到目标位置。这里,我们可以使用setTimeoutrequestAnimationFrame方法实现一个平滑滚动的过程,具体代码如下所示:

function scrollToSection(offset) {
  const start = window.pageYOffset;
  const distance = offset - start;
  const duration = 300;
  let startTime = null;

  function scroll(timestamp) {
    if (!startTime) {
      startTime = timestamp;
    }
    const progress = timestamp - startTime;
    const ease = easing(progress / duration);
    window.scrollTo(0, start + distance * ease);
    if (progress < duration) {
      requestAnimationFrame(scroll);
    }
  }

  requestAnimationFrame(scroll);
}

function easing(t) {
  return t * t * t;
}

上述代码中,我们根据目标位置与当前位置的差值计算出滚动的距离,然后使用requestAnimationFrame方法实现一个平滑的动画过程。我们通过scroll函数来实现具体的滚动过程,其中,我们通过window.scrollTo方法来实现页面滚动效果,然后使用递归调用requestAnimationFrame方法完成滚动过程中的帧动画。我们还定义了一个easing函数来控制滚动动画的加速度。

5. 示例说明

为了更好的说明实现过程,这里再提供两个示例:

示例1:

在页面中有三个内容区域分别是Introduction、Features和Contact Us,对应的导航链接分别是Introduction、Features和Contact Us。当用户点击Introduction链接时,页面滚动到Introduction内容区域;当用户点击Features链接时,页面滚动到Features内容区域;当用户点击Contact Us链接时,页面滚动到Contact Us内容区域。

HTML代码:

<nav class="navbar">
  <ul class="navbar-nav">
    <li class="nav-item"><a href="#" data-link="0">Introduction</a></li>
    <li class="nav-item"><a href="#" data-link="1">Features</a></li>
    <li class="nav-item"><a href="#" data-link="2">Contact Us</a></li>
  </ul>
</nav>

<section id="section-1">
  <h1>Introduction</h1>
</section>

<section id="section-2">
  <h1>Features</h1>
</section>

<section id="section-3">
  <h1>Contact Us</h1>
</section>

JS代码:

const navLinks = document.querySelectorAll('.navbar-nav a');
const sections = document.querySelectorAll('section');
const sectionOffsets = [];

for (let i = 0; i < sections.length; i++) {
  sectionOffsets[i] = sections[i].offsetTop;
}

for (let i = 0; i < navLinks.length; i++) {
  navLinks[i].addEventListener('click', function(event) {
    event.preventDefault();
    const targetSection = event.target.getAttribute('data-link');
    const targetOffset = sectionOffsets[targetSection];
    scrollToSection(targetOffset);
  })
}

function scrollToSection(offset) {
  const start = window.pageYOffset;
  const distance = offset - start;
  const duration = 300;
  let startTime = null;

  function scroll(timestamp) {
    if (!startTime) {
      startTime = timestamp;
    }
    const progress = timestamp - startTime;
    const ease = easing(progress / duration);
    window.scrollTo(0, start + distance * ease);
    if (progress < duration) {
      requestAnimationFrame(scroll);
    }
  }

  requestAnimationFrame(scroll);
}

function easing(t) {
  return t * t * t;
}

示例2:

在一个页面中有10个内容区域和导航条,当用户距离页面顶部超过300px时,导航条固定在页面顶部,用户在滑动页面时,导航随之滑动,当用户点击导航链接时,页面滚动到相应的内容区域。

HTML代码:

<nav class="navbar">
  <ul class="navbar-nav">
    <li class="nav-item"><a href="#" data-link="0">Section 1</a></li>
    <li class="nav-item"><a href="#" data-link="1">Section 2</a></li>
    <li class="nav-item"><a href="#" data-link="2">Section 3</a></li>
    <li class="nav-item"><a href="#" data-link="3">Section 4</a></li>
    <li class="nav-item"><a href="#" data-link="4">Section 5</a></li>
    <li class="nav-item"><a href="#" data-link="5">Section 6</a></li>
    <li class="nav-item"><a href="#" data-link="6">Section 7</a></li>
    <li class="nav-item"><a href="#" data-link="7">Section 8</a></li>
    <li class="nav-item"><a href="#" data-link="8">Section 9</a></li>
    <li class="nav-item"><a href="#" data-link="9">Section 10</a></li>
  </ul>
</nav>

<div class="spacer"></div>

<section id="section-1">
  <h1>Section 1</h1>
</section>

<section id="section-2">
  <h1>Section 2</h1>
</section>

<section id="section-3">
  <h1>Section 3</h1>
</section>

<section id="section-4">
  <h1>Section 4</h1>
</section>

<section id="section-5">
  <h1>Section 5</h1>
</section>

<section id="section-6">
  <h1>Section 6</h1>
</section>

<section id="section-7">
  <h1>Section 7</h1>
</section>

<section id="section-8">
  <h1>Section 8</h1>
</section>

<section id="section-9">
  <h1>Section 9</h1>
</section>

<section id="section-10">
  <h1>Section 10</h1>
</section>

CSS代码:

.navbar {
  position: relative;
  z-index: 999;
  background-color: #fff;
}

.spacer {
  height: 80px;
}

.sticky-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}

.current {
  color: #f00;
}

JS代码:

const navLinks = document.querySelectorAll('.navbar-nav a');
const sections = document.querySelectorAll('section');
const sectionOffsets = [];
const navbar = document.querySelector('.navbar');
const spacer = document.querySelector('.spacer');
let isSticky = false;

for (let i = 0; i < sections.length; i++) {
  sectionOffsets[i] = sections[i].offsetTop;
}

window.addEventListener('scroll', function(event) {
  const scrollTop = window.pageYOffset;
  if (scrollTop > 300 && !isSticky) {
    navbar.classList.add('sticky-nav');
    spacer.style.paddingTop = navbar.offsetHeight + 'px';
    isSticky = true;
  } else if (scrollTop <= 300 && isSticky) {
    navbar.classList.remove('sticky-nav');
    spacer.style.paddingTop = '0';
    isSticky = false;
  }

  const currentSection = getCurrentSection(scrollTop, sectionOffsets);
  setActiveLink(currentSection);
})

function getCurrentSection(scrollTop, sectionOffsets) {
  for (let i = sectionOffsets.length - 1; i >= 0; i--) {
    if (scrollTop >= sectionOffsets[i] - 100) {
      return i;
    }
  }
  return 0;
}

function setActiveLink(index) {
  for (let i = 0; i < navLinks.length; i++) {
    navLinks[i].classList.remove('current');
  }
  navLinks[index].classList.add('current');
}

for (let i = 0; i < navLinks.length; i++) {
  navLinks[i].addEventListener('click', function(event) {
    event.preventDefault();
    const targetSection = event.target.getAttribute('data-link');
    const targetOffset = sectionOffsets[targetSection];
    scrollToSection(targetOffset);
  })
}

function scrollToSection(offset) {
  const start = window.pageYOffset;
  const distance = offset - start;
  const duration = 300;
  let startTime = null;

  function scroll(timestamp) {
    if (!startTime) {
      startTime = timestamp;
    }
    const progress = timestamp - startTime;
    const ease = easing(progress / duration);
    window.scrollTo(0, start + distance * ease);
    if (progress < duration) {
      requestAnimationFrame(scroll);
    }
  }

  requestAnimationFrame(scroll);
}

function easing(t) {
  return t * t * t;
}

上述代码中,我们实现了一个页面滚动时导航条固定在页面顶部的效果,并且在用户点击导航链接时,页面会滚动到相应的内容区域。在代码中,我们使用了getBoundingClientRect方法来获取元素相对于视口的位置信息,并通过监听scroll事件来实时更新导航条的位置。此外,我们还通过getCurrentSection函数来实时判断当前应该显示哪一个内容区域,并通过setActiveLink函数来设置当前选择的导航链接的样式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:js实现点击选项置顶动画效果 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • JavaScript生成.xls文件的代码

    生成Excel文件是前端开发中常见的需求之一,可以通过JS库来实现。目前比较流行的库有两个:SheetJS和Handsontable,本文将以SheetJS为例来讲解如何使用JS生成Excel文件的完整攻略。 SheetJS库介绍 SheetJS是一组用于处理Excel文件的JS库,可读取、修改和写入Excel文件,支持XLS、XLSX等多种格式。同时She…

    JavaScript 2023年5月19日
    00
  • 前端实现电子签名(web、移动端)通用的实战过程

    前端实现电子签名是一个比较复杂的过程,本文将以通用的实战过程进行详细讲解,主要包含以下几个步骤: 获取签名 处理签名数据 在页面上绘制签名 将签名保存并上传到服务器 1. 获取签名 获取签名有多种方式,常见的包括手写、鼠标绘制、触摸屏绘制等。本文以鼠标绘制为例进行讲解。 在页面上添加一个画布元素,并使用JavaScript获取该元素的上下文对象: <c…

    JavaScript 2023年6月11日
    00
  • 通过event对象的fromElement属性解决热区设置主实体的一个bug

    对于Web开发过程中,经常会涉及到鼠标移动事件,而其中一个常见的问题就是热区设置时容易出现主实体与热区之间相互触发的问题。这时,我们可以通过event对象的fromElement属性来解决这个问题。 什么是event对象? 在JavaScript中,event对象包含了当前页面中发生的事件的相关信息,例如事件类型、事件的目标元素等。当事件触发时,浏览器会自动…

    JavaScript 2023年6月10日
    00
  • Javascript优化技巧(文件瘦身篇)

    Javascript优化技巧(文件瘦身篇) 为什么需要文件瘦身? 在前端开发中,Javascript文件瘦身是一项必修课。因为随着项目的不断庞大,Javascript代码也会不断增加,而且有些代码可能已经过时、冗余、或者被其中其他代码所替代,这些代码对于整个项目的性能影响还是非常大的。 通过文件瘦身技巧,我们可以有效减少代码的冗余,提高代码的复用性,优化代码…

    JavaScript 2023年5月27日
    00
  • JS getMonth()日期函数的值域是0-11

    关于“JS getMonth()日期函数的值域是0-11”的详细讲解,我整理了以下的攻略步骤,希望可以帮到你。 1. 了解 JavaScript Date 对象 在了解 getMonth 函数之前,我们需要先了解 JavaScript 的 Date 对象。Date 对象用于处理日期和时间,它提供了多种方法和属性来操作日期、时间,以及从中提取信息。 2. ge…

    JavaScript 2023年5月27日
    00
  • node爬取新型冠状病毒的疫情实时动态

    “node爬取新型冠状病毒的疫情实时动态”可以通过编写一个node爬虫来完成。下面是完整攻略的步骤: 1. 确定目标网站 首先明确我们要爬取的疫情实时动态信息发布的网站,可以通过查找查询“新型冠状病毒疫情实时动态”得知,目前国内有多个网站可以获取疫情动态信息,比如腾讯新闻疫情实时动态、丁香园疫情实时动态等,这里我们以丁香园为例进行讲解。 2. 分析网站结构 …

    JavaScript 2023年6月11日
    00
  • 实例讲解动态加载gridview中的行及其样式

    我们来详细讲解一下如何实现“实例讲解动态加载gridview中的行及其样式”。 准备工作 在开始这个示例之前,你需要先安装以下工具和组件: .NET Framework 4.0 或以上版本 Visual Studio 2010 或以上版本 接下来,你还需要按照以下步骤创建一个新的 Web 应用程序: 打开 Visual Studio。 选择“文件” -&gt…

    JavaScript 2023年6月11日
    00
  • JS前端组件注册与画布渲染实例

    下面是“JS前端组件注册与画布渲染实例”的完整攻略。 什么是JS前端组件注册? JS前端组件注册是指将一些可复用的DOM组件封装成组件库,以便在多个页面或应用程序中重复使用。其中,组件包括但不限于按钮、表单、下拉框、弹出框等等。 常见的JS前端组件库有:Bootstrap、Element UI、Ant Design等。 组件注册通常需要以下几个步骤: 为组件…

    JavaScript 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部