我正在研究一个动画,当一个点击事件后用jQuery添加一个类时会触发该动画。
它有点像切换:
首次点击按钮后,动画1将会运行https://codepen.io/thijs-webber/pen/dMBKRp
第二次点击相同的按钮后,需要运行反向动画
有没有办法轻松扭转动画链?
.animation-container {
width: 250px;
position: relative;
margin: 0 auto;
margin-top: 50px;
}
.dot-pink-light {
fill: #CE97AE;
}
.dot-pink {
fill: #D82566;
}
.dot-green-light {
fill: #AFBF99;
}
.dot-green {
fill: #77BC1F;
}
/* ANIMATIONS */
@keyframes rotate_clockwise {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
}
@keyframes rotate_anticlockwise {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
}
@keyframes scale_down {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
-webkit-transform: scale(0.5);
transform: scale(0.5);
}
}
@keyframes pop_out_dots_top {
100% {
transform: translate(0px, -80px);
}
}
@keyframes pop_out_dots_bottom {
100% {
transform: translate(0px, 80px);
}
}
/* 1 */
.container.opened {
animation: scale_down 250ms ease;
transform-origin: 50% 50% 0;
}
/* 2 */
.container.opened .groups .extra-dot-top {
animation: pop_out_dots_top 250ms ease;
-webkit-animation-delay: 250ms;
animation-delay: 250ms;
transform-origin: 50% 50% 0;
}
.container.opened .groups .extra-dot-bottom {
animation: pop_out_dots_bottom 250ms ease;
-webkit-animation-delay: 250ms;
animation-delay: 250ms;
transform-origin: 50% 50% 0;
}
.container.opened .groups .group-2 {
animation: rotate_anticlockwise 250ms ease;
transform-origin: 50% 50% 0;
-webkit-animation-delay: 250ms;
animation-delay: 250ms;
}
/* 4 */
.container.opened .groups {
animation: rotate_clockwise 250ms ease;
transform-origin: 50% 50% 0;
-webkit-animation-delay: 500ms;
animation-delay: 500ms;
}
<div class="animation-container">
<div class="col-xs-12">
<?xml version="1.0" ?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" enable-background="new 0 0 200 200">
<!-- Group 1 -->
<g class="container opened">
<g class="groups">
<g class="group-1 pink">
<circle class="dot-pink-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-pink" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink" cx="100" cy="100" r="21.4" />
<circle class="dot-pink" cx="100" cy="178.6" r="21.4" />
</g>
<!-- Group 2 -->
<g class="group-2 green">
<circle class="dot-green-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-green" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green" cx="100" cy="100" r="21.4" />
<circle class="dot-green" cx="100" cy="178.6" r="21.4" />
</g>
</g>
</g>
</svg>
</div>
</div>
答案 0 :(得分:2)
由于您正在寻找仅具有两种不同状态的切换效果,因此使用转场而不是动画会更好。删除类时,转换可以自动产生相反的效果。
演示过渡:
window.onload = function() {
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
document.querySelector('.container').classList.toggle('opened');
});
}
&#13;
.animation-container {
width: 250px;
position: relative;
margin: 0 auto;
margin-top: 50px;
}
.dot-pink-light {
fill: #CE97AE;
}
.dot-pink {
fill: #D82566;
}
.dot-green-light {
fill: #AFBF99;
}
.dot-green {
fill: #77BC1F;
}
/* 1 */
.container {
transform: scale(1);
transition: transform 2.5s ease;
transform-origin: 50% 50% 0;
transition-delay: 5s;
}
.container.opened {
transform: scale(0.5);
transition-delay: 0s;
}
.container .groups .extra-dot-top {
transform: translate(0px, 0px);
transition: transform 2.5s ease;
transition-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.opened .groups .extra-dot-top {
transform: translate(0px, -80px);
}
.container .groups .extra-dot-bottom {
transform: translate(0px, 0px);
transition: transform 2.5s ease;
transition-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.opened .groups .extra-dot-bottom {
transform: translate(0px, 80px);
}
.container .groups .group-2 {
transform: rotate(0deg);
transition: transform 2.5s ease;
transform-origin: 50% 50% 0;
transition-delay: 2.5s;
}
.container.opened .groups .group-2 {
transform: rotate(-90deg);
}
/* 4 */
.container .groups {
transform: rotate(0deg);
transition: transform 2.5s ease;
transform-origin: 50% 50% 0;
}
.container.opened .groups {
transform: rotate(45deg);
transition-delay: 5s;
}
&#13;
<div class="animation-container">
<div class="col-xs-12">
<?xml version="1.0" ?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" enable-background="new 0 0 200 200">
<!-- Group 1 -->
<g class="container">
<g class="groups">
<g class="group-1 pink">
<circle class="dot-pink-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-pink" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink" cx="100" cy="100" r="21.4" />
<circle class="dot-pink" cx="100" cy="178.6" r="21.4" />
</g>
<!-- Group 2 -->
<g class="group-2 green">
<circle class="dot-green-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-green" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green" cx="100" cy="100" r="21.4" />
<circle class="dot-green" cx="100" cy="178.6" r="21.4" />
</g>
</g>
</g>
</svg>
</div>
</div>
<button>Click</button>
&#13;
另一方面,动画不能自动产生反向效果,需要编写代码。即使编写了反向动画的代码,使其工作也很复杂(并且不能用纯CSS完成),因为你必须删除&#34; open&#34;添加&#34;关闭&#34;之前的动画动画和发生时,元素将在执行反向效果之前立即捕捉到其原始位置。输出不会像转换一样优雅,除非你输入很多混乱的代码。
使用动画进行演示:
window.onload = function() {
var btn = document.querySelector('button');
var container = document.querySelector('.container');
var groups = document.querySelector('.groups');
var group2 = document.querySelector('.group-2');
var extradtG = document.querySelector('.green .extra-dot-top');
var extradtP = document.querySelector('.pink .extra-dot-top');
var extradbG = document.querySelector('.green .extra-dot-bottom');
var extradbP = document.querySelector('.pink .extra-dot-bottom');
var opened = false;
btn.addEventListener('click', function() {
if (opened) {
container.style.transform = 'scale(1)';
extradtG.style.transform = 'translate( 0px, 0px)';
extradtP.style.transform = 'translate( 0px, 0px)';
extradbG.style.transform = 'translate( 0px, 0px)';
extradbP.style.transform = 'translate( 0px, 0px)';
group2.style.transform = 'rotate(0deg);'
groups.style.transform = 'rotate(0deg)';
container.classList.remove('opened');
container.clientHeight; // dummy call
container.classList.add('closed');
} else {
container.style.transform = 'scale(0.5)';
extradtG.style.transform = 'translate( 0px, -80px)';
extradtP.style.transform = 'translate( 0px, -80px)';
extradbG.style.transform = 'translate( 0px, 80px)';
extradbP.style.transform = 'translate( 0px, 80px)';
group2.style.transform = 'rotate(-90deg);'
groups.style.transform = 'rotate(45deg)';
container.classList.remove('closed');
container.clientHeight; // dummy call
container.classList.add('opened');
}
opened = !opened;
});
}
&#13;
.animation-container {
width: 250px;
position: relative;
margin: 0 auto;
margin-top: 50px;
}
.dot-pink-light {
fill: #CE97AE;
}
.dot-pink {
fill: #D82566;
}
.dot-green-light {
fill: #AFBF99;
}
.dot-green {
fill: #77BC1F;
}
/* ANIMATIONS */
@keyframes rotate_clockwise {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(45deg);
}
}
@keyframes rotate_anticlockwise {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-90deg);
}
}
@keyframes scale_down {
0% {
transform: scale(1);
}
100% {
transform: scale(0.5);
}
}
@keyframes pop_out_dots_top {
0% {
transform: translate(0px, 0px);
}
100% {
transform: translate(0px, -80px);
}
}
@keyframes pop_out_dots_bottom {
0% {
transform: translate(0px, 0px);
}
100% {
transform: translate(0px, 80px);
}
}
/* 1 */
.container.opened {
animation: scale_down 2.5s ease;
transform-origin: 50% 50% 0;
}
.container.closed {
animation: scale_down 2.5s ease reverse backwards;
transform-origin: 50% 50% 0;
animation-delay: 5s;
}
/* 2 */
.container.opened .groups .extra-dot-top {
animation: pop_out_dots_top 2.5s ease backwards;
animation-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.closed .groups .extra-dot-top {
animation: pop_out_dots_top 2.5s ease reverse backwards;
animation-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.opened .groups .extra-dot-bottom {
animation: pop_out_dots_bottom 2.5s ease backwards;
animation-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.closed .groups .extra-dot-bottom {
animation: pop_out_dots_bottom 2.5s ease reverse backwards;
animation-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.opened .groups .group-2 {
animation: rotate_anticlockwise 2.5s ease backwards;
transform-origin: 50% 50% 0;
animation-delay: 2.5s;
}
.container.closed .groups .group-2 {
animation: rotate_anticlockwise 2.5s ease reverse backwards;
transform-origin: 50% 50% 0;
animation-delay: 2.5s;
}
/* 4 */
.container.opened .groups {
animation: rotate_clockwise 2.5s ease backwards;
transform-origin: 50% 50% 0;
animation-delay: 5s;
}
.container.closed .groups {
animation: rotate_clockwise 2.5s ease reverse backwards;
transform-origin: 50% 50% 0;
}
&#13;
<div class="animation-container">
<div class="col-xs-12">
<?xml version="1.0" ?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" enable-background="new 0 0 200 200">
<!-- Group 1 -->
<g class="container">
<g class="groups">
<g class="group-1 pink">
<circle class="dot-pink-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-pink" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink" cx="100" cy="100" r="21.4" />
<circle class="dot-pink" cx="100" cy="178.6" r="21.4" />
</g>
<!-- Group 2 -->
<g class="group-2 green">
<circle class="dot-green-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-green" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green" cx="100" cy="100" r="21.4" />
<circle class="dot-green" cx="100" cy="178.6" r="21.4" />
</g>
</g>
</g>
</svg>
</div>
</div>
<button>Click</button>
&#13;
(动画版本有一个虚拟调用container.clientHeight
,这样做是为了确保在删除一个动画和添加另一个动画之间存在重画。否则,看起来好像没有发生任何事情您可以在我的回答here中找到更多详细信息。)