【译】CSS 过渡101:让我们为切换按钮图标设置动画

101
网络动画起到的角色远远超过了单单装饰品的作用。你可以用它来引导网友的关注、去组织信息并使得信息更容易消化,去使得等待内容的加载变得更快捷、有趣。
好消息是,通过前端开发人员的工具包里的 CSS 过渡动画,你能够在一行代码中添加一些小技巧来改善 web 的用户体验。
在这里,你能够学习到 CSS 过渡动画什么时候能够为你的项目做一个好的选择,以及如何去通过实现来改善你的网站。在本文的最后,你就能够通过 CSS 过渡动画在切换按钮上创建变形动画。
我们开始吧!
 

CSS transitions 还是 keyframe animations?

无论是用CSS transition 动画还是 keyframe animation 动画,都能够不需要 JavaScript,单单使用 CSS 就能添加平滑的切换效果。特别是在一些擅长优化的浏览器中,你为透明度和关键帧动画设置动效的时候,他们在性能方面都非常奏效。

 

Transitions

transition动画 允许你将属性值从它的起始状态更改为结束状态以响应事件,例如,mouseenter,mouseout,click等。这就意味着,如果你的动效只有这两个状态,CSS 的transition 动画是最佳和最简单的工具。transition 的常见用例,包括在悬停或者点击鼠标时,滑入滑出画布边栏,在悬停时改变链接或者按钮的颜色,在点击按钮时淡入或者淡出对话框等等。
使用 transition 的另一个优势是优雅降级:如果一个错误发生了或者浏览器不支持它们,最坏的情况就是元素会突然改变它的状态而不是逐渐改变。
 

Animations

你利用 css 的 transition 属性来创造过渡动画:
.selector {
  transition: property duration transition-timing-function delay;
}
以上代码是这四个属性的简约版:
.selector {
  transition-property: color;
  transition-duration: 0.5s;
  transition-timing-function: ease-in;
  transition-delay: 0.3s;
}

 

transition-property

transition-property 值是你想应用转换的 CSS 属性,可以是任何 CSS 中可动画的属性,例如颜色、高度、宽度等。
并不是所有 CSS 属性都可以转换,但很多都可以,特别是那些由数值表示的属性。这些可以有起始状态和结束状态,能够容易地用表示响应的中间状态的中间数值进行插值。但你不能对 auto 值进行转换。
如果你想转换多个属性,我认为使用关键词 all更好,它将 transition 应用于所有设置了所选元素样式的动画属性。

 

transition-duration

transition-duration 属性表示了css属性从起始值到结束值过渡的时间。你可以用 秒(1s)或者 毫秒(1000ms)来表示值。
 

transition-timing-function

如果你想你的动画看起来自然和平滑,那么 transition-timing-function 属性就很重要。贝塞尔曲线作为表示动画中变化率的值。为简单起见,你可以使用以下的关键词:

 

ease:默认值。它起始很慢,然后加速,再然后慢下来,最终非常慢地结束:
ease

 

linear:变化率保持不变:
leanear

 

ease-in:开始很慢,然后加速:
easein

 

ease-out:开始很快,然后慢下来:
easeout

 

ease-in-out:开始很慢,在中间过程加快,到最后慢下来。这跟 ease 很相似,但不像它到最后一样慢:
easeinout
或者,你可以创建自定义的贝塞尔曲线,你可以使用 cubic-bezier.com 之类的工具快速创建。
 

transition-delay

transition-delay属性表示你在开始持续动画之前要等待的时间。你可以以秒或者毫秒来表示这个值,就像持续时间属性一样。
在这次教程里,你将会使用简约的属性。
请记住,持续时间是唯一必需的值,其他属性都有默认值。在 transition-property 默认为 all 时,transition-timing-function 为 ease,transition-delay 为 0s。如果为持续时间和延迟时间添加两个值,浏览器会将第一个值解释为 transition-duration,第二个值解释为 transition-delay,所以你添加这些值的顺序非常重要。
 

切换按钮图标的变形动画

现在,是时候实际行动看一些 CSS 的过渡动画啦,让我们一起进入敲代码模式吧!
目标是将切换按钮上的图标从汉堡形状变形为 X 形状。结果如下:
X
 

代码概述

HTML 包括了一个简单的 button 和 span 元素。图标由 span和两个 span 的 before 和 after 伪元素组成,使其看起来像汉堡的图标。这里是相关的 HTML 代码:
现在轮到 CSS啦。这里是渲染汉堡图标的默认样式(仅有相关的规则):
/* give the span element and related pseudo-elements the appearance of white lines */
.hamburger__icon,
.hamburger__icon::before,
.hamburger__icon::after {
  position: absolute;
  width: 44px; 
  height: 4px;
  border-radius: 4px;
  background-color: #fff;
}
/* set the span element in the middle of its containing div */
.hamburger__icon {
  top: calc(50% - 2px);
  left: calc(50% - 22px);
}
/* set the content property and left position of the two pseudo-elements*/
.hamburger__icon::before,
.hamburger__icon::after {
  content: "";
  left: 0;
}
/* set the bottom property of the before pseudo-element */
.hamburger__icon::before {
  bottom: 12px;
}
/* set the top property of the after pseudo-element */
.hamburger__icon::after {
  top: 12px;
}
上面的代码片段创建了汉堡包图标外观的三条典型线条。
接下来,是轮到悬停的样式了。当用户在按钮上悬停时,将旋转 span 和伪元素(使用css的transform 的 rotate()方法),并且它们的背景颜色、位置、高度和宽度会变成一个典型的关闭图标。以下是代码:
/* HOVER STYLES ON THE BUTTON */
/* increase width and height of span element, */
/* recalculate top and left position, rotate it and change background-color */
.hamburger__button:hover .hamburger__icon {
  height: 10px;
  width: 110px;
  left: 5px;
  top: calc(50% - 4px);
  transform: rotate(-45deg);
  background-color: #e20650;
}
/* adjust properties on the after pseudo element */
.hamburger__button:hover .hamburger__icon::after {
  width: 110px;
  height: 10px;
  top: -1px;
  transform: rotate(-270deg);
  background-color: #e20650;
}
/* hide the before pseudo-element by scaling it to 0 */
.hamburger__button:hover .hamburger__icon::before {
  transform: scale(0);
}
如果你现在悬停在按钮上,你能够看到汉堡按钮突然变成关闭按钮。添加css过渡将实现我们追求的逐渐变形效果。
 

CSS transition 代码

如果你添加过渡效果到悬停状态上,当用户在按钮上悬停的时候就会生效,但并不是鼠标离开按钮的时候。换句话说,汉堡图标会逐渐地并且平滑地变成关闭图标,但关闭按钮会一下子变回汉堡icon。为了确保动画效果完全发生在鼠标进入和鼠标离开的时候,你需要在全局默认样式上添加过渡的代码,而不只是在悬停的样式上。如下:
/* this is one of the lines of the close icon */
.hamburger__icon {
  /* preceding code stays the same */
  transition: all 0.3s linear;
}
/* this is the other line of the close icon */
  .hamburger__icon::after {
  /* preceding code stays the same */
  transition: all 0.3s linear;
}
在单单一行代码里,你已经告诉浏览器将一个在0.3秒时间内、没有任何速度变化(用 linear timing function)的可动画特性的过渡效果作用在可动画的特性上。
除了用关键词 all 之外,你还可以罗列每条 css 特性名字。例如:
.hamburger__button:hover .hamburger__icon {
  /* preceding code stays the same */
  transition: height 0.3s linear,
              width 0.3s linear,
              left 0.3s linear,
              top 0.3s linear,
              transform 0.3s linear,
              background-color 0.3s linear;
}
当您计划将转换应用于选择器上的几个属性时,或者如果要指定任何属性变化时,如不同的持续时间或者时间函数。事实上,使用这种技术可以提高代码效率和性能。但是,如果您仍然需要为相当多的属性设置动画,那么这样做可能会冗长,重复且容易出错。
测试你的代码:按钮悬停的变形效果现在看起来应该是平滑和让人愉悦的交互效果。此外,尝试不同的转换时间函数,尝试不同的持续时间值,或者为什么不添加几毫秒的延迟然后看看会发生什么。
 

css 过渡和 javascript

转换元素时,您不仅限于悬停事件。您可以将转换绑定到CSS类,然后利用 JavaScript 将 CSS 类添加到要设置动画的元素。
换句话说,CSS 将通过动态添加和删除 CSS 类来处理外观,即动画效果,以及具有行为或 DOM 操作的 JavaScript。
为了说明这一点,这里有与上面相同的变形效果,但是会在点击按钮时执行。
第一步是用您选择的类名替换您之前编写的所有悬停样式实例。我命名我的类名为 toggled。这是相关的片段:
.toggled.hamburger__button .hamburger__icon {
  height: 10px;
  width: 110px;
  left: 5px;
  top: calc(50% - 4px);
  transform: rotate(-45deg);
  background-color: #e20650;
}
.toggled.hamburger__button .hamburger__icon::after {
  width: 110px;
  height: 10px;
  top: -1px;
  transform: rotate(-270deg);
  background-color: #e20650;
}
.toggled.hamburger__button .hamburger__icon::before {
  transform: scale(0);
}
使用上面的代码,每次将切换的类添加到按钮时,图标将变为关闭图标。同样地,当移除切换的类时,图标变形为汉堡图标。
JavaScript代码的唯一任务是在按钮点击时切换类 .toggled:
hamburgerButton.addEventListener( "click", () => hamburgerButton.classList.toggle("toggled") );
这就是你所需要的一切。测试你的代码,变形效果看起来应该与你之前创建的悬停示例完全相同:https://codepen.io/antonietta/pen/KeqrdZ
 

将CSS过渡应用于动态创建的HTML元素

上面的示例工作正常,因为转换应用于静态DOM元素,即在HTML源代码中写死了的的元素。但是,如果你动态创建元素并且用javascript附加到DOM,那么本来应该触发过渡效果的类将无法达到预期的结果。一旦浏览器渲染了这个元素,过渡的效果已经结束了,动画也丢失了。
这就是我的意思。假设当您单击页面上的按钮时,box从顶部滑入。使用上面使用的相同技术实现滑入效果:动态添加类以触发CSS转换,同时将过渡属性应用于box元素:
.box {
  /* more code above, transition below */
  transition: 1s;
}
这次不同的是,并不是box已经在你的html文档里,而是使用javascript动态创建它。
jsvascript代码看起来像是这样的:
// add event listener to the button element
button.addEventListener('click', () => {
  // create the box element with a class of .box
  const box = document.createElement("div");
  box.classList.add("box");
  // append the new element box to the DOM
  document.querySelector("body").appendChild(box);
  // add the class that triggers the transition to the box element
  document.querySelector(".box").classList.add("slide-in");
}
看一下在codepen上一个运行的demo:https://codepen.io/antonietta/pen/WyZjEN
当你点击按钮时,box将立即实现到页面上,而不显示动画。
要解决此问题,您需要在创建新元素后经过一小段时间后添加转换触发类。为此,您可以使用 .setTimeout()方法,或者更好的是 .requestAnimationFrame()方法。由于.requestAnimationFrame()是专为网页动画设计的,因此我将使用这个方法来修复此演示。
作为第一步,您需要编写函数,将过渡触发类添加到元素并调用.requestAnimationFrame():
const doTransition = () => {
  // add the class that triggers the transition to the box element
  document.querySelector('.box').classList.add("slide-in");
  // call requestAnimationFrame passing this same function as argument
  window.requestAnimationFrame(doTransition);
};
下一步是在按钮点击事件中调用.requestAnimationFrame(),再次传入doTransition()函数作为参数。
在将box附加到DOM的代码之后添加此位:
// call requestAnimationFrame passing the doTransition function as argument
window.requestAnimationFrame(doTransition);
而且你已经完成了!看看工作演示来看看差异:https://codepen.io/antonietta/pen/eKGRVK

 

总结

在 CSS 过渡动画介绍中,我讨论了什么时候适合用 CSS 关键帧做动画转换,和怎样使用过渡动画使汉堡图片变换做切换按钮,无论使在悬停还是点击的时候都使用 JavaScript。

原文:https://blog.logrocket.com/css-transitions-101-lets-animate-a-toggle-button-icon-333967f5b971

发表评论