搜索
首页web前端css教程如何使用WAAPI对细节元素进行动画动画

使用Web Animations API为原生<details></details>元素创建动画效果

网站上最常见的动画需求之一就是手风琴式展开收起效果。有趣的是,jQuery的slideDown()函数早在2006年的第一个版本中就已经存在了。

本文将介绍如何使用Web Animations API为原生的<details></details>元素创建动画效果。

HTML结构

首先,让我们看看实现此动画所需的HTML标记结构。

<details></details>元素需要一个<summary></summary>元素。<summary></summary>是手风琴折叠时可见的内容。<details></details>内的所有其他元素都是手风琴内部内容的一部分。为了方便动画效果的实现,我们将它们包裹在一个

中。
<details>
  <summary>手风琴标题</summary>
  <div class="content">
    <p>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Modi unde, ex rem voluptates autem aliquid veniam quis temporibus repudiandae illo, nostrum, pariatur quae! At animi modi dignissimos corrupti placeat voluptatum!
    </p>
  </div>
</details>

Accordion类

为了提高代码的可重用性,我们应该创建一个Accordion类。这样,我们就可以在页面上的每个<details></details>元素上调用new Accordion()

class Accordion {
  constructor(el) {}
  onClick(e) {}
  shrink() {}
  open() {}
  expand() {}
  onAnimationFinish(open) {}
}

构造函数constructor()

构造函数用于存储每个手风琴所需的数据。

constructor(el) {
  this.el = el;
  this.summary = el.querySelector('summary');
  this.content = el.querySelector('.content');
  this.animation = null;
  this.isClosing = false;
  this.isExpanding = false;
  this.summary.addEventListener('click', (e) => this.onClick(e));
}

onClick()

onClick()函数中,我们会检查元素是否正在进行动画(关闭或展开)。如果用户在元素正在动画时点击手风琴,我们需要进行此检查。如果点击速度过快,我们不希望手风琴从完全展开跳到完全关闭。<details></details>元素在打开时,浏览器会为其添加一个open属性。我们可以通过this.el.open来获取该属性的值。

onClick(e) {
  e.preventDefault();
  this.el.style.overflow = 'hidden';
  if (this.isClosing || !this.el.open) {
    this.open();
  } else if (this.isExpanding || this.el.open) {
    this.shrink();
  }
}

shrink()

shrink()函数使用WAAPI的.animate()函数。您可以阅读MDN文档了解更多信息。WAAPI与CSS @keyframes非常相似。我们需要定义动画的起始和结束关键帧。在本例中,我们只需要两个关键帧,第一个是元素的当前高度,第二个是手风琴关闭后的高度。当前高度存储在startHeight变量中。关闭高度存储在endHeight变量中,等于<summary></summary>的高度。

shrink() {
  this.isClosing = true;
  const startHeight = `${this.el.offsetHeight}px`;
  const endHeight = `${this.summary.offsetHeight}px`;
  if (this.animation) {
    this.animation.cancel();
  }
  this.animation = this.el.animate({
    height: [startHeight, endHeight]
  }, {
    duration: 400,
    easing: 'ease-out'
  });
  this.animation.onfinish = () => this.onAnimationFinish(false);
  this.animation.oncancel = () => this.isClosing = false;
}

open()

open()函数在我们要展开手风琴时调用。此函数目前不控制手风琴的动画。首先,我们计算<details></details>元素的高度,并使用内联样式将其应用于元素。完成后,我们可以设置其open属性以使内容可见,但由于我们对元素设置了overflow: hidden和固定高度,因此内容仍然隐藏。然后,我们等待下一帧调用expand()函数并为元素创建动画。

open() {
  this.el.style.height = `${this.el.offsetHeight}px`;
  this.el.open = true;
  window.requestAnimationFrame(() => this.expand());
}

expand()

expand()函数类似于shrink()函数,但它不是从当前高度动画到关闭高度,而是从元素的高度动画到结束高度。结束高度等于<summary></summary>的高度加上内部内容的高度。

expand() {
  this.isExpanding = true;
  const startHeight = `${this.el.offsetHeight}px`;
  const endHeight = `${this.summary.offsetHeight   this.content.offsetHeight}px`;
  if (this.animation) {
    this.animation.cancel();
  }
  this.animation = this.el.animate({
    height: [startHeight, endHeight]
  }, {
    duration: 400,
    easing: 'ease-out'
  });
  this.animation.onfinish = () => this.onAnimationFinish(true);
  this.animation.oncancel = () => this.isExpanding = false;
}

onAnimationFinish()

此函数在收缩或展开动画结束时调用。如您所见,有一个参数open,在手风琴打开时设置为true,允许我们设置元素上的openHTML属性,因为它不再由浏览器处理。

onAnimationFinish(open) {
  this.el.open = open;
  this.animation = null;
  this.isClosing = false;
  this.isExpanding = false;
  this.el.style.height = this.el.style.overflow = '';
}

设置手风琴

我们完成了代码的大部分工作!

剩下的就是为HTML中的每个<details></details>元素使用我们的Accordion类。为此,我们使用<details></details>标签上的querySelectorAll,并为每个元素创建一个新的Accordion实例。

document.querySelectorAll('details').forEach((el) => {
  new Accordion(el);
});

注意

为了计算关闭高度和打开高度,我们需要确保<summary></summary>和内容始终具有相同的高度。

例如,不要尝试在<summary></summary>打开时添加填充,因为这可能会导致动画过程中出现跳跃。内部内容也是如此——它应该具有固定高度,我们应该避免在打开动画过程中高度发生变化的内容。

此外,不要在<summary></summary>和内容之间添加边距,因为它不会计算高度关键帧。相反,直接在内容上使用填充来添加一些间距。

总结

就这样,我们使用JavaScript创建了一个漂亮的手风琴动画,无需任何库!

How to Animate the Details Element Using WAAPI

请注意,图片的路径 /uploads/20250331/174338369667e9ec90190a3.jpg 需要替换成实际的图片路径。 我无法访问或处理图片文件,所以只能保留原始格式。

以上是如何使用WAAPI对细节元素进行动画动画的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
揭开屏幕读取器的神秘面纱:可访问的表格和最佳实践揭开屏幕读取器的神秘面纱:可访问的表格和最佳实践Mar 08, 2025 am 09:45 AM

这是我们在形式可访问性上进行的小型系列中的第三篇文章。如果您错过了第二篇文章,请查看“以:focus-visible的管理用户焦点”。在

使用智能表单框架创建JavaScript联系表格使用智能表单框架创建JavaScript联系表格Mar 07, 2025 am 11:33 AM

本教程演示了使用智能表单框架创建外观专业的JavaScript表单(注意:不再可用)。 尽管框架本身不可用,但原理和技术仍然与其他形式的建筑商相关。

将框阴影添加到WordPress块和元素将框阴影添加到WordPress块和元素Mar 09, 2025 pm 12:53 PM

CSS盒子阴影和轮廓属性获得了主题。让我们查看一些在真实主题中起作用的示例,以及我们必须将这些样式应用于WordPress块和元素的选项。

使用GraphQL缓存使用GraphQL缓存Mar 19, 2025 am 09:36 AM

如果您最近开始使用GraphQL或审查了其优点和缺点,那么您毫无疑问听到了诸如“ GraphQl不支持缓存”或

使您的第一个自定义苗条过渡使您的第一个自定义苗条过渡Mar 15, 2025 am 11:08 AM

Svelte Transition API提供了一种使组件输入或离开文档(包括自定义Svelte Transitions)时动画组件的方法。

优雅且酷的自定义CSS卷轴:展示柜优雅且酷的自定义CSS卷轴:展示柜Mar 10, 2025 am 11:37 AM

在本文中,我们将深入研究滚动条。我知道,这听起来并不魅力,但请相信我,一个精心设计的页面是齐头并进的

展示,不要说展示,不要说Mar 16, 2025 am 11:49 AM

您花多少时间为网站设计内容演示文稿?当您撰写新的博客文章或创建新页面时,您是在考虑

NPM命令是什么?NPM命令是什么?Mar 15, 2025 am 11:36 AM

NPM命令为您运行各种任务,无论是一次性或连续运行的过程,例如启动服务器或编译代码。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具