diff --git a/TODO1/integrating-third-party-animation-libraries-to-a-project-2.md b/TODO1/integrating-third-party-animation-libraries-to-a-project-2.md index d092521a9b9..faba8f1ce83 100644 --- a/TODO1/integrating-third-party-animation-libraries-to-a-project-2.md +++ b/TODO1/integrating-third-party-animation-libraries-to-a-project-2.md @@ -2,25 +2,25 @@ > * 原文作者:[Travis Almand](https://css-tricks.com/author/travisalmand/) > * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner) > * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO1/integrating-third-party-animation-libraries-to-a-project-2.md](https://github.com/xitu/gold-miner/blob/master/TODO1/integrating-third-party-animation-libraries-to-a-project-2.md) -> * 译者: -> * 校对者: +> * 译者:[Baddyo](https://juejin.im/user/5b0f6d4b6fb9a009e405dda1) +> * 校对者:[lgh757079506](https://github.com/lgh757079506) -# Integrating Third-Party Animation Libraries to a Project - Part 2 +# 在项目中集成第三方动画库 —— 第二部分 -> - [Integrating Third-Party Animation Libraries to a Project - Part 1](https://github.com/xitu/gold-miner/blob/master/TODO1/integrating-third-party-animation-libraries-to-a-project-1.md) -> - [Integrating Third-Party Animation Libraries to a Project - Part 2](https://github.com/xitu/gold-miner/blob/master/TODO1/integrating-third-party-animation-libraries-to-a-project-2.md) +> - [在项目中集成第三方动画库 —— 第一部分](https://github.com/xitu/gold-miner/blob/master/TODO1/integrating-third-party-animation-libraries-to-a-project-1.md) +> - [在项目中集成第三方动画库 —— 第二部分](https://github.com/xitu/gold-miner/blob/master/TODO1/integrating-third-party-animation-libraries-to-a-project-2.md) -## Moving stuff out of the way +## 过关斩将 -When researching for this article, I found that transitions (not to be confused with CSS transitions) are easily the most common type of animations in the third-party libraries. These are simple animations that are built to allow an element to enter or leave the page. A very common pattern seen in modern Single Page Applications is to have one element leave the page while another replaces it by entering the page. Think of the first element fading out and the second fading in. This could be replacing old data with new data, moving to the next panel in a sequence, or moving from one page to another with a router. Both [Sarah Drasner](https://css-tricks.com/native-like-animations-for-page-transitions-on-the-web/) and [Georgy Marchuk](https://css-tricks.com/page-transitions-for-everyone/) have excellent examples of these types of transitions. +在为本文查资料时,我发现第三方动画库中最常见的动画类型就是过渡动画(并非 CSS transition)了。有些简单的动画应用于元素出入页面的过程。现代单页应用中最司空见惯的模式就是让一个元素进入页面,顶替另一个离开页面的元素。想想这种情况:第一个元素淡出而第二个元素淡入。这个动画可以用于新旧数据交替、按顺序移动面板或切换路由到另一个页面。[Sarah Drasner](https://css-tricks.com/native-like-animations-for-page-transitions-on-the-web/) 和 [Georgy Marchuk](https://css-tricks.com/page-transitions-for-everyone/) 都列举了很多此类过渡动画的优秀案例。 -For the most part, animation libraries will not provide the means to remove and add elements during the transition animations. The libraries that provide additional JavaScript may actually have this functionality, but since most do not, we’ll discuss how to handle this functionality now. +大多数情况下,动画库不支持在过渡动画中添加或删除元素。用额外的 JavaScript 代码实现的库也许支持这样的功能,但毕竟这样的库很少见,因此我们现在就来讨论如何实现该功能。 -### Inserting a single element +### 插入单个元素 -For this example, we’ll again use Animate.css as our library. In this case, I’ll be using the `fadeInDown` animation. +对于本例,我们继续使用 Animate.css,并会用到 fadeInDown 动画。 -Now, please keep in mind there are many ways to handle inserting an element into the DOM and I don’t wish to cover them here. I’ll just be showing how to leverage an animation to make the insertion nicer and more natural than the element simply popping into view. For Animate.css (and likely many other libraries), inserting an element with the animation is quite easy. +在 DOM 中插入元素有很多种方式,在此不再赘述。我仅会展示如何用动画优雅流畅地插入元素,而非让元素生硬地突现。对于 Animate.css(或其他类似的库)来说,这个功能十分简单。 ```javascript let insertElement = document.createElement('div'); @@ -34,11 +34,11 @@ insertElement.addEventListener('animationend', function () { document.body.append(insertElement); ``` -However you decide to create the element doesn’t much matter; you just need to be sure the needed classes are already applied before inserting the element. Then it’ll nicely animate into place. I also included an event listener for the `animationend` event that removes the classes. As usual, there are several ways to go about doing this and this is likely the most direct way to handle it. The reason for removing the classes is to make it easier to reverse the process if we wish. We wouldn’t want the entering animation competing with a leaving animation. +你如何创建该元素不重要,关键在于确保元素插入之前添加了所需的类。然后,此元素就会以优雅的动画登场。我还监听了 `animationend` 事件,用于移除动画类。通常来说,实现此效果的方式不一而足,而这种方式是最直接的方式了。移除动画类是为了方便实现退场效果。我们不想让退场动画和进场动画相互冲突。 -### Removing a single element +### 移除单个元素 -Removing a single element is sort of similar to inserting an element. The element already exists, so we just apply the desired animation classes. Then at the `animationend` event we remove the element from the DOM. In this example, we’ll use the `fadeOutDown` animation from Animate.css because it works nicely with the `fadeInDown` animation. +移除单个元素和插入大体类似。目标元素已经存在了,我们添加所需的动画类就好。然后在 `animationend` 事件触发时,我们把该元素从 DOM 中移除。在本例中,我们会使用 Animate.css 提供的 `fadeOutDown` 动画,因为它和 `fadeInDown` 动画是相互呼应的。 ```javascript let removeElement = document.querySelector('#removeElement'); @@ -50,18 +50,18 @@ removeElement.addEventListener('animationend', function () { removeElement.classList.add('animated', 'fadeOutDown'); ``` -As you can see, we target the element, add the classes, and remove the element at the end of the animation. +如你所见,锁定目标元素、添加类以及在动画结束时移除元素,一气呵成。 -An issue with all this is that with inserting and removing elements this way will cause the other elements on the page to jump around to adjust. You’ll have to account for that in some way, most likely with CSS and the layout of the page to keep a constant space for the elements. +这个过程会有一个问题,那就是随着目标元素的插入或移除,其他元素将会在页面中重排。我们需要去考虑使用 CSS 技术和一些布局方式去规避这个问题。 -### Get out of my way, I’m coming through! +### 你方唱罢我登场 -Now we are going to swap two elements, one leaving while another enters. There are several ways of handling this, but I’ll provide an example that’s essentially combining the previous two examples. +现在我们要切换两个元素,一进一出。条条大路通罗马,但我举的例子是上文中两个例子的结合。 -See the Pen [ -3rd Party Animation Libraries: Transitioning Two Elements](https://codepen.io/talmand/pen/JqPLbm/) by Travis Almand ([@talmand](https://codepen.io/talmand)) on [CodePen](https://codepen.io). -I’ll go over the JavaScript in parts to explain how it works. First, we cache a reference to a button and the container for the two elements. Then, we create two boxes that’ll be swapped inside the container. +参见 [CodePen](https://codepen.io) 上来自 Travis Almand([@talmand](https://codepen.io/talmand))的代码示例:[第三方动画库:双元素过渡](https://codepen.io/talmand/pen/JqPLbm/)。 + +我会把 JavaScript 代码分块来讲解其原理。首先,我们创建 button、container 变量分别存储对应的两个 DOM 节点。然后,我们创建 box1、box2 来存储在 container 中要交换的两个元素。 ```javascript let button = document.querySelector('button'); @@ -70,7 +70,7 @@ let box1 = document.createElement('div'); let box2 = document.createElement('div'); ``` -I have a generic function for removing the animation classes for each `animationEnd` event. +我写了一个通用函数,用来在每次触发 `animationEnd` 时移除动画类。 ```javascript let removeClasses = function () { @@ -79,7 +79,7 @@ let removeClasses = function () { } ``` -The next function is the bulk of the swapping functionality. First, we determine the current box being displayed. Based on that, we can deduce the leaving and entering elements. The leaving element gets the event listener that called the `switchElements` function removed first so we don’t find ourselves in an animation loop. Then, we remove the leaving element from the container since its animation has finished. Next, we add the animation classes to the entering element and append it to the container so it’ll animate into place. +第二个函数则是切换功能的核心。首先,我们确定当前显示的是哪个元素。借此我们可以推断出哪个元素切入,哪个切出。切出元素用 `switchElements` 函数监听,预先移除动画类,避免陷入动画循环。然后,等切出元素的动画完成,我们将其从容器中移除。接下来,给切入元素添加动画类,并将其插入容器,让它以动画登场。 ```javascript let switchElements = function () { @@ -94,7 +94,7 @@ let switchElements = function () { } ``` -We need to do some general setup for the two boxes. Plus, we append the first box to the container. +我们需要给两个盒子做一些通用设置。接着,将第一个盒子插入到容器中。 ```javascript box1.classList.add('box', 'box1'); @@ -105,7 +105,7 @@ box2.addEventListener('animationend', removeClasses); container.appendChild(box1); ``` -Finally, we have a click event listener for our button that does the toggling. How these sequences of events are started is technically up to you. For this example, I decided on a simple button click. I figure out which box is currently being displayed, which will be leaving, to apply the appropriate classes to make it animate out. Then I apply an event listener for the `animationEnd` event that calls the `switchElements` function shown above that handles the actual swap. +最后,给触发切换的按钮添加点击事件监听。这一系列事件的启动顺序取决于你。在本例中,我打算从按钮点击事件开始。我确定了正在显示的盒子 —— 即将切出的盒子,给它添加对应的类让它以动画切出。然后我监听切出元素的 `animationEnd` 事件,触发该事件会调用切实操纵切换的函数 —— 上面列出的 `switchElements` 函数。 ```javascript button.addEventListener('click', function () { @@ -121,17 +121,17 @@ button.addEventListener('click', function () { } ``` -One obvious issue with this example is that it is extremely hard-coded for this one situation. Although, it can be easily extended and adjusted for different situations. So, the example is useful in terms of understanding one way of handling such a task. Thankfully, some animation libraries, like [MotionUI](https://zurb.com/playground/motion-ui), provide some JavaScript to help with element transitions. Another thing to consider is that some JavaScript frameworks, such as [VueJS](https://vuejs.org/v2/guide/transitions.html)) have functionality to assist with animating element transitions. +这个例子眼下有个问题:其代码是专门为这一情况写死的。当然了,它也很易于扩展,也能适应不同场景。故此,该例子只是用来理解如何实现这一功能的。还好,一些诸如 [MotionUI](https://zurb.com/playground/motion-ui) 这样的动画库支持用 JavaScript 操纵元素的过渡动画。另外,像 [VueJS](https://vuejs.org/v2/guide/transitions.html) 这类 JavaScript 框架也支持切换元素的过渡动画。 -I have also created another example that provides a more flexible system. It consists of a container that stores references to leave and enter animations with data attributes. The container holds two elements that will switch places on command. The way this example is built is that the animations are easily changed in the data attributes via JavaScript. I also have two containers in the demo; one using Animate.css and the other using Animista for animations. It’s a large example, so I won’t examine code here; but it is heavily commented, so take a look if it is of interest. +我在另一个例子中展示了一个更灵活的系统。它由一个容器构成,该容器存放着用 data 属性引用的切入和切出动画。容器中的两个元素按照命令切换位置。这个例子的原理是,通过 JavaScript 控制 data 属性可以轻松改变动画。Demo 中还有两个容器,一个用的是 Animate.css 实现动画;另一个用的则是 Animista。这个例子代码量较大,我将不在本文中讲解,但这个例子的注释很充足,感兴趣的话可以看看。 -See the Pen [3rd Party Animation Libraries: Custom Transition Example](https://codepen.io/talmand/pen/mYdeBb/) by Travis Almand ([@talmand](https://codepen.io/talmand)) on [CodePen](https://codepen.io). +参见 [CodePen](https://codepen.io) 上来自 Travis Almand([@talmand](https://codepen.io/talmand))的代码示例:[第三方动画库:自定义动画示例](https://codepen.io/talmand/pen/mYdeBb/)。 -## Take a moment to consider... +## 停下来思考一下…… -Does everyone actually want to see all these animations? Some people could consider our animations over-the-top and unnecessary, but for some, they can actually cause problems. Some time ago, WebKit introduced the [`prefers-reduced-motion`](https://webkit.org/blog/7551/responsive-design-for-motion/) media query to assist with possible [Vestibular Spectrum Disorder](https://alistapart.com/article/accessibility-for-vestibular/) issues. Eric Bailey also [posted a nice introduction](https://css-tricks.com/introduction-reduced-motion-media-query/) to the media query, as well as [a follow-up with considerations for best practices](https://css-tricks.com/revisiting-prefers-reduced-motion-the-reduced-motion-media-query/). Definitely read these. +是所有人都想看到这些动画吗?可能有些人会觉得这些动画浮夸,没什么必要,而另一些人会认为这些动画会导致一些问题。就在前不久,WebKit 为了解决 [Vestibular Spectrum Disorder](https://alistapart.com/article/accessibility-for-vestibular/) 问题,引入了 [`prefers-reduced-motion`](https://webkit.org/blog/7551/responsive-design-for-motion/) 媒体查询功能。Eric Bailey 也针对该媒体查询功能发表了一篇[详尽的说明文章](https://css-tricks.com/introduction-reduced-motion-media-query/),和[一篇关于最佳实践的跟进文章](https://css-tricks.com/revisiting-prefers-reduced-motion-the-reduced-motion-media-query/)。务必看看这些资料。 -So, does your animation library of choice support the `prefers-reduced-motion`? If the documentation doesn’t say that it does, then you may have to assume it does not. Although, it is rather easy to check the code of the library to see if there is anything for the media query. For instance, Animate.css has it in the [`_base.scss`](https://github.com/daneden/animate.css/blob/0ca8f2dc7c74c9e76b93bc378dad8b1cc1590dad/source/_base.css#L46) partial file. +那么,你选择的动画库支持 `prefers-reduced-motion` 吗?如果官方文档没说能支持,那你最好假设不支持。就算官方文档语焉不详,你还可以查看动画库的代码来确定是否支持,这也容易。例如,Animate.css 在 [`_base.scss`](https://github.com/daneden/animate.css/blob/0ca8f2dc7c74c9e76b93bc378dad8b1cc1590dad/source/_base.css#L46) 文件中就有关于媒体查询的代码。 ```css @media (print), (prefers-reduced-motion) { @@ -142,7 +142,7 @@ So, does your animation library of choice support the `prefers-reduced-motion`? } ``` -This bit of code also provides an excellent example of how to do this for yourself if the library doesn’t support it. If the library has a common class it uses — like Animate.css uses "animated" — then you can just target that class. If it does not support such a class then you’ll have to target the actual animation class or create your own custom class for that purpose. +如果你选择的动画库不支持媒体查询,那么看到这里的代码,你也会知道如何自己动手写一个补丁。如果该库使用一个通用类 —— 比如 Animate.css 的 animated 类 —— 那你以这个通用类为目标就行了。如果没有这样一个通用类,那你可以选某个特定的动画类或者自己写一个来实现。 ```css .scale-up-center { @@ -162,15 +162,15 @@ This bit of code also provides an excellent example of how to do this for yourse } ``` -As you can see, I just used the example as provided by Animate.css and targeted the animation class from Animista. Keep in mind that you’ll have to repeat this for every animation class you choose to use from the library. Although, in Eric’s follow-up piece, [he suggests treating all animations as progressive enhancement](https://css-tricks.com/revisiting-prefers-reduced-motion-the-reduced-motion-media-query/#article-header-id-4) and that could be one way to both reduce code and make a more accessible user experience. +可以看到,我比照 Animate.css 中的代码改造了 Animista 中的动画类。记住,你得把所选库中每个动画类都做这样的处理。在 Eric 的文章中,他建议[对所有动画都做渐进增强](https://css-tricks.com/revisiting-prefers-reduced-motion-the-reduced-motion-media-query/#article-header-id-4),以此减少代码并提高用户体验。 -## Let a framework do the heavy lifting for you +## 让框架帮你干力气活 -In many ways, the various frameworks such as React and Vue can make using third-party CSS animation easier than with vanilla JavaScript, mainly because you don’t have to wire up the class swaps or `animationend` events manually. You can leverage the functionality the frameworks already provide. The beauty of using frameworks is that they also provide several different ways of handling these animations depending on the needs of the project. The examples below is only a small example of options. +在很多方面,React、Vue 这些五花八门的框架,让第三方 CSS 动画库比原生 JavaScript 更加易用,因为你不需要手动接驳那些类或者 `animationend` 事件。你可以用框架提供的现成功能实现所需效果。使用框架的便利之处在于框架还提供多种操纵动画的方式,满足多种项目需求。下面的例子展示的只是冰山一角。 -### Hover effects +### hover 效果 -For hover effects, I would suggest setting them up with CSS (as I suggested above) as the better way to go. If you really need a JavaScript solution in a framework, such as Vue, it would be something like this: +对于 hover 效果,我建议用 CSS(一如上文中的建议)来设置会比较好。如果你确实需要在 Vue 之类的框架中用 JavaScript 实现,将会是这样: ```html