1. 根本介绍
AutoAnimate 是一个零配置的嵌入式动画实用程序,可为您的 Web 应用程序增加平滑的过渡。您能够将它与 React、Solid、Vue、Svelte 或任何其余 JavaScript 应用程序一起应用。
AutoAnimate 的指标是在不影响开发人员的施行工夫或性能估算的状况下大幅改善应用程序的用户体验。
2. 和其余动画库的区别
之前的动画库根本都是开发者要在哪里加上动画,须要咱们本人决定或者配置才行,而 AutoAnimate 能够帮忙咱们主动在整个利用增加适合的动画。
AutoAnimate 应用一行代码即可实现增加适合的动画,咱们不须要在编写时列表组件时思考到 AutoAnimate。
AutoAnimate 能够追溯利用到代码库中的任何标记,包含第 3 方代码 - 只需提供父 DOM 节点,而后让 AutoAnimate 实现剩下的工作。
3. 使用指南
3.1 装置
yarn add @formkit/auto-animate ornpm install @formkit/auto-animate
3.2 用法
AutoAnimate 实质上是一个 autoAnimate 承受父元素的函数。主动动画将利用于父元素及其间接子元素。当产生以下三个事件之一时,会专门触发动画:
- 一个子级被增加到 DOM 中。
- DOM 中的子级被删除。
- 一个孩子在 DOM 中挪动。
3.3 注意事项
应用其余类型的过渡依然能够。例如,如果您仅应用 CSS 进行款式更改(例如悬停成果),则能够应用规范 CSS 过渡来进行此类款式调整。
- autoAnimate仅当增加、删除或挪动父元素(您传递给的元素)的间接子元素时,才会触发动画。
- position: relative如果父元素是动态定位的,它会主动接管。编写款式时请记住这一点。
- 有时,Flexbox 布局不会立刻调整其子布局的大小。具备属性的子级flex-grow: 1会在捕捉到其残缺宽度之前期待四周的内容。AutoAnimate 在这些状况下成果不佳,但如果您为元素指定更明确的宽度,它应该会像魅力一样工作。
4. 原理介绍
4.1 IntersectionObserver
异步察看指标元素与先人元素或具备顶级文档的视口的相交的变动。
function observePosition(el: Element) { const oldObserver = intersections.get(el) oldObserver?.disconnect() let rect = coords.get(el) let invocations = 0 const buffer = 5 if (!rect) { rect = getCoords(el) coords.set(el, rect) } const { offsetWidth, offsetHeight } = root const rootMargins = [ rect.top - buffer, offsetWidth - (rect.left + buffer + rect.width), offsetHeight - (rect.top + buffer + rect.height), rect.left - buffer, ] const rootMargin = rootMargins .map((px) =>`${-1 * Math.floor(px)}px`) .join(" ") const observer = new IntersectionObserver( () => { ++invocations > 1 && updatePos(el) }, { root, threshold: 1, rootMargin, } ) observer.observe(el) intersections.set(el, observer)}
4.2 MutationObserver
监听DOM树的变动,比方减少、删除、挪动等DOM操作。
function getElements(mutations: MutationRecord[]): Set<Element> | false { const observedNodes = mutations.reduce((nodes: Node[], mutation) => { return [ ...nodes, ...Array.from(mutation.addedNodes), ...Array.from(mutation.removedNodes), ] }, []) // Short circuit if _only_ comment nodes are observed const onlyCommentNodesObserved = observedNodes.every( (node) => node.nodeName === "#comment" ) if (onlyCommentNodesObserved) returnfalse return mutations.reduce((elements: Set<Element> | false, mutation) => { // Short circuit if we find a purposefully deleted node. if (elements === false) returnfalse if (mutation.target instanceof Element) { target(mutation.target) if (!elements.has(mutation.target)) { elements.add(mutation.target) for (let i = 0; i < mutation.target.children.length; i++) { const child = mutation.target.children.item(i) if (!child) continue if (DEL in child) returnfalse target(mutation.target, child) elements.add(child) } } if (mutation.removedNodes.length) { for (let i = 0; i < mutation.removedNodes.length; i++) { const child = mutation.removedNodes[i] if (DEL in child) returnfalse if (child instanceof Element) { elements.add(child) target(mutation.target, child) siblings.set(child, [ mutation.previousSibling, mutation.nextSibling, ]) } } } } return elements }, newSet<Element>())}
4.3 ResizeObserver
对 Element 的内容或边框或 SVGElement 的边框的尺寸的更改
if (typeofwindow !== "undefined") { root = document.documentElement mutations = new MutationObserver(handleMutations) resize = new ResizeObserver(handleResizes) resize.observe(root)}
感兴趣的同学能够关注FED实验室微信公众号理解更多前端前沿资讯和招聘信息。