如何实现基于媒体查询断点的CSS动画



作为使我们的网络系统对移动设备做出响应的一部分,我使用CSS媒体查询在标题栏和汉堡菜单之间进行切换。

现在,当桌面用户将浏览器窗口的大小调整到媒体查询定义的范围之外时,如果它在两种布局之间设置动画,我认为这将是一个很好的噱头。作为概念验证测试,我一直在尝试在大徽标和小徽标之间进行转换。

我的animations.scss文件包含以下两个动画:

@mixin ToSmallLogo() {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapToSmallLogo;
@keyframes SwapToSmallLogo {
0% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
}
@mixin SwapToBigLogo() {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapToBigLogo;
@keyframes SwapToBigLogo {
0% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
}
}

然后我得到了一个专门用于媒体查询的SCSS文件,其中包含:

@import '../../Variables/Sizes.scss';
@import '../Animations/animations.scss';
@media screen and (max-width: $bigToSmallFISLogo) {
#franklin {
@include ToSmallLogo();
}
}
@media screen and (min-width: $bigToSmallFISLogo){
#franklin{
@include SwapToBigLogo();
}
}

而应用媒体查询之前的CSS是这样的:

#franklin {
display: block;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
}

我的问题是,虽然将屏幕缩小到定义的大小之外效果很好,但返回时只会捕捉到更大的图像,而没有动画。我认为罪魁祸首是在应用媒体查询之前,我在CSS中定义了图像,所以我删除了其中的那部分;但这只会导致没有图像。

然后在输入这个问题时,我想到了使用媒体查询来确定动画的方向,比如:

@mixin SwapLogo() {
/*    background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;*/
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapLogo;
@media screen and (max-width: $bigToSmallFISLogo) {
animation-direction: normal;
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
@media screen and (min-width: $bigToSmallFISLogo) {
animation-direction: reverse;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
@keyframes SwapLogo {
0% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
}

这导致动画在页面加载时运行,但在调整大小时不运行。

有什么办法做我要找的吗?

选项1包含一些错误的css

您已在SwapToBigLogo上将起始设置为width: 100%;

@keyframes SwapToBigLogo {
0% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
width: 100%; <---- culprit
background-image: url('../../../PageAssets/Fis.png');
}

从本质上讲,您是从width: 100%width:100%的动画。如果你去掉那条线,它可能会起作用。

选项2倒车棘手

反转动画时,它不会重置动画的迭代次数和进度
IE,如果在100%完成时"反转"动画。它将只应用"反向"状态的100%完成未从0%反向开始并动画化为100%反向

如果你想绕过,请看我对这个问题的回答

备选方案,请改用转换

如果您不需要复杂的动画,只想平稳地从一种状态过渡到另一种状态
我更喜欢使用css转换

#franklin {
display: block;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
transition: width 2s ease-in; // <--- this will animate when the media query kicks in.
}

@media screen and (max-width: $bigToSmallFISLogo) {
#franklin {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%; 
}
}
@media screen and (min-width: $bigToSmallFISLogo){
#franklin{
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
}

奖金

您可以将转换应用于*选择器。(我不建议生产级网站这样做,但玩起来很有趣。(当媒体查询更改宽度/布局时,它会使一切顺利过渡。

* {
transition: all 2s;
}
body {
background-color: red;
color: black;
font-size: 30px;
}
.logo {
width: 200px;
border: 5px solid black;
border-radius: 30px;
padding:20px;
}

/* On screens that are 992px wide or less, the background color is blue */
@media screen and (max-width: 630px) {
body {
background-color: blue;
color: white;
font-size: 20px;
}
.logo {
width: 100px;
border: 3px solid orange;
border-radius: 10px;
padding:10px;
}
}

/* On screens that are 600px wide or less, the background color is olive */
@media screen and (max-width: 400px) {
body {
background-color: lime;
color: white;
font-size: 12px;
}
.logo {
width: 50px;
border: 1px solid indigo;
border-radius: 5px;
padding:2px;
}
}
<h1>Resize window</h1>
<p>
<img class="logo" src="http://placekitten.com/200/300" alt="logo">
</p>

经过大量的实验,我终于发现了它。正如Lars所指出的,从本质上讲,我忘了删除几个片段;但我最终得到的解决方案(看起来有点平滑,因为它会将一个图像渐变为另一个图像(是将基本CSS设置为:

#franklin {
display: block;
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
}

然后混合应用动画如下:

@mixin SwapLogo($img, $width, $startIMG, $startWidth, $animationName) {
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: $animationName;
background-image: $img;
width: $width;
@keyframes #{$animationName} {
0% {
width: $startWidth;
background-image: $startIMG;
}
100% {
background-image: $img;
width: $width;
}
}
}

媒体查询为:

@media screen and (max-width: calc($bigToSmallFISLogo + 10px)) { //This overlap of 10px basically allows for the animation to take effect as the other animation is removed. 
#franklin {
@include SwapLogo(url('../../../../PageAssets/fissmall.png'), 7%, url('../../../../PageAssets/Fis.png'), 100%, LogoGoSmall);
margin-top: 13px;
}
}
@media screen and (min-width: $bigToSmallFISLogo) {
#franklin {
@include SwapLogo(url('../../../../PageAssets/Fis.png'), 100%, url('../../../../PageAssets/fissmall.png'), 7%, LogoGoBig);
}
}
@media screen and (max-width: $minSizeForDesktopMenu) and (min-width: $bigToSmallFISLogo) {
#franklin {
margin-top: 26px;
}
}
@media screen and (min-width: $minSizeForDesktopMenu) {
#franklin {
margin-top: 13px;
}
}

最新更新