CSS秘密花园: 动画状态

Credo 8年前
   <p>《 <a href="/misc/goto?guid=4958976660757929944" rel="nofollow,noindex">CSS Secrets</a> 》是 <a href="/misc/goto?guid=4958976660849001117" rel="nofollow,noindex">@Lea Verou</a> 最新著作,这本书讲解了有关于CSS中一些小秘密。是一本CSSer值得一读的一本书,经过一段时间的阅读,我、@南北和@彦子一起将在W3cplus发布一系列相关的读后感,与大家一起分享。</p>    <p><img src="https://simg.open-open.com/show/b873adc9c0b700ab68ae0efe9cf398be.jpg"></p>    <h3>问题</h3>    <p>动画并不总是页面加载的时候就开始。往往,我们都想通过用户的操作来触发动画,比如鼠标的悬浮( :hover )或者鼠标按下时( :active )。在这种情况之下,我们可能没办法控制动画播放的实妹次数,用户可能会迫使动画停止。例如,用户有通过悬浮( :hover )触发动画:鼠标移出元素之前动画结束。在这样的例子中会发生什么呢?</p>    <p>如果你的回答是“动画应该会呆其当前状态”或者“动画会顺利的过渡到前置状态”。默认情况下,动画就会停下来,突然跳到最初始状态。有时候可能会接受这种非常微妙的动画。但在大多数情况下它直接影响用户的体验。那么我们可以改变这种行为吗?</p>    <p><img src="https://simg.open-open.com/show/fff0548abf902b6cbf3b4f8b7b872cd2.png"></p>    <p><img src="https://simg.open-open.com/show/98451c4d2f1468e8113991f7d64ba5b7.png"></p>    <p>我决定拿一个 <a href="/misc/goto?guid=4959670921248646753" rel="nofollow,noindex">简单的页面</a> 来说明这个问题(这个页面是我当作礼物送给我朋友Julian的)。注意右边圆形中的图片,当用户鼠标悬停在圆形上时,圆形中的图片慢慢开始向左滚动,显示被隐藏的那部分。默认情况,当用户鼠标移出圆形图片时,图片会立即回到原来的位置,这给人感觉体验不好。因为这是一个小网站,而这张图片又是该网站核心部分,我不能睁一眼闭一眼,必须得把这个问题给解决。</p>    <h3>解决方案</h3>    <p>假设我们一个很长的景观照片,如下图所示:</p>    <p><img src="https://simg.open-open.com/show/bfa1b0a8ea0a73f924938ae944f42c44.jpg"></p>    <p>但我们要显示的空间只有 150px X 150px 的正方形。解决这个问题的一个方法就需要使用动画:默认显示图像的从图像的左边缘开始,当用户有交互行为时,图片慢慢向左滚动(例如,鼠标悬浮在图片上时)。我们使用单个元素,并且给他设置一个背景图片,通过动画修改 background-position 值来实现。</p>    <pre>  <code class="language-css"><div class="panoramic"></div>    .panoramic {      width: 150px;       height: 150px;      background: url("img/naxos-greece.jpg");      background-size: auto 100%;  }  </code></pre>    <p>目前,它看起来如下图所示:</p>    <p><img src="https://simg.open-open.com/show/1e87da5267d47b9df1f9fb5ad140080d.png"></p>    <p>没有动画和任何交互效果。我们来实战一回,我们可以看到,原来是手动的修改 background-position 从 0 0 到 0 100% 来修改整个背景图像。下面我们来尝试使用 keyframes 来做:</p>    <pre>  <code class="language-css">@keyframes panoramic {      to {          background-position: 100% 0;      }  }  .panoramic {      width: 150px;       height: 150px;      background: url("img/naxos-greece.jpg");      background-size: auto 100%;      animation: panoramic 10s linear infinite alternate;  }  </code></pre>    <p>它能正常的运行。效果看起来就像一个全景,从左向右看。然而,而面加载动画就被触发,这样一来可能会分散用户的集中力,例如,旅游网页,用户可能会试着只专注于阅读有关于纳克索斯岛(Naxos)相关文本,而不是看着美丽的全景照片。当用户鼠标悬浮在图片上时,才触发动画,这样看起来更形象。所以,我们首先想的方案就是这样的。</p>    <pre>  <code class="language-css">.panoramic {      width: 150px;      height: 150px;      background: url("img/naxos-greece.jpg");      background-size: auto 100%;  }  .panoramic:hover,  .panoramic:focus {      animation: panoramic 10s linear infinite alternate;  }  </code></pre>    <p>当鼠标悬浮在图片上时动画被触发:初始状态显示图像的最左边的部分,慢慢滚动显示图像的其他部分。然而,当我们的鼠标移出图像时,图像又突然跳到图像的最左边,如下图所示:</p>    <p><img src="https://simg.open-open.com/show/03414706f60d7a91d8042983d5c027a6.png"></p>    <p>我也是无意之中发现这个问题。</p>    <p>为了解决这个问题,我们要想个办法来解决。我们需要的是不应用动画,这意味着 :hover 无法记忆动画的当前位置。我们需要的是鼠标悬浮在图片是有动画,图片从左向右移动,鼠标移出图片时,动画暂停。值得庆幸的是,动画有一个属性 animation-play-state 可以实现这样的效果。</p>    <p>因此,我们把动画的暂停状态运用在 .panoramic 上,而鼠标悬浮状态( :hover )时又播放动画。因为它不再是播放和取消一个动画,只是暂停和恢复现有的动画,这样动画不会有突然跳跃。最后的代码和效果如下:</p>    <pre>  <code class="language-css">.panoramic {    width: 150px;     height: 150px;    background: url("http://www.w3cplus.com/sites/default/files/blogs/2015/1507/naxos-greece-big.jpg");    background-size: auto 100%;    animation: panoramic 10s linear infinite alternate;    animation-play-state: paused;  }  .panoramic:hover,  .panoramic:focus {    animation-play-state: running;  }  @keyframes panoramic {    to {      background-position: 100% 0;    }  }  </code></pre>    <p>来自: <a href="/misc/goto?guid=4959670921335553945" rel="nofollow">http://www.w3cplus.com/css3/css-secrets/smooth-state-animations.html</a></p>    <p> </p>