我正在制作一个动画,该动画将在单击事件后使用 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>
最佳答案
由于您正在寻找仅具有两种不同状态的切换效果,因此使用过渡效果比使用动画效果要好得多。当类被移除时,过渡可以自动产生相反的效果。
带转换的演示:
window.onload = function() {
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
document.querySelector('.container').classList.toggle('opened');
});
}
.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;
}
<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>
而动画不能自动产生反转效果,需要写代码。即使编写了反向动画的代码,让它工作也很复杂(并且不能使用纯 CSS 完成),因为您必须在添加“关闭”动画之前删除“打开”动画,并且当元素发生时在执行反向效果之前将立即捕捉到它们的原始位置。除非您输入大量困惑的代码,否则输出不会像转换那样优雅。
带动画的演示:
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;
});
}
.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;
}
<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>
(动画版本有一个虚拟调用 container.clientHeight
这样做是为了确保在移除一个动画和添加另一个动画之间进行重绘。否则,它会看起来好像什么都没发生。您可以在我的回答中找到更多详细信息 here 。)
关于css - SVG 元素的反转动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37346935/