【发布时间】:2021-04-20 06:25:59
【问题描述】:
我目前正在使用scss 为“移动”边框编写动画。动画主要基于clip。
$box-size-w: 80px;
$box-size-h: 50px;
@keyframes clipMe {
0%, 100% {
clip: rect(0, $box-size-w, $path-width, 0);
}
25% {
clip: rect(0, $path-width, $box-size-h, 0);
}
50% {
clip: rect(resolveCalc($box-size-h, $path-width), $box-size-w, $box-size-h, 0);
}
75% {
clip: rect(0, $box-size-w, $box-size-h, resolveCalc($box-size-w, $path-width));
}
}
起初动画只适用于方形块(w === h),然后我对其进行了调整,以便可以单独指定 with 和 height。
然后需要再次调整脚本,使其接受percent 值,而不仅仅是pixels。我做了一些研究,发现了这篇文章Clipping and Masking in CSS。从文章看来:
- 旧语法:
clip: rect(10px, 20px, 30px, 40px); - 新语法:
clip-path: inset(10px 20px 30px 40px);
我进行了更改,似乎以下应该可以工作:
$box-size-w: 100%;
$box-size-h: 100%;
@keyframes clipMe {
0%, 100% {
clip-path: inset(0 $box-size-w $path-width 0);
}
25% {
clip-path: inset(0 $path-width $box-size-h 0);
}
50% {
clip-path: inset(resolveCalc($box-size-h, $path-width) $box-size-w $box-size-h 0);
}
75% {
clip-path: inset(0 $box-size-w $box-size-h resolveCalc($box-size-w, $path-width));
}
}
但是在此更改后动画不起作用。我试着玩这个,但结果不是很好,似乎新的 api 也改变了它的工作方式。如何修改 keyframes 使其与 % 值一起使用?
完整的scss代码:
$anime-time: 8s;
$box-size-w: 80px;
$box-size-h: 50px;
$path-width: 1px;
$main-color: #000;
@function resolveCalc($s, $f) {
@return calc(#{$s} - #{$f});
}
%full-fill {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.box {
width: $box-size-w;
height: $box-size-h;
margin: auto;
color: $main-color;
box-shadow: inset 0 0 0 1px rgba($main-color, .1);
position:relative;
&::before,
&::after {
@extend %full-fill;
content: '';
z-index: -1;
margin:0;
box-shadow: inset 0 0 0 $path-width;
}
&.active {
&::before {
animation: clipMe $anime-time linear infinite;
animation-delay: $anime-time * -.5;
}
&::after {
animation: clipMe $anime-time linear infinite;
}
// for debug
&:hover {
&::after,
&::before {
background-color: rgba(#fff, .3);
}
}
}
}
@keyframes clipMe {
0%, 100% {
clip: rect(0, $box-size-w, $path-width, 0);
}
25% {
clip: rect(0, $path-width, $box-size-h, 0);
}
50% {
clip: rect(resolveCalc($box-size-h, $path-width), $box-size-w, $box-size-h, 0);
}
75% {
clip: rect(0, $box-size-w, $box-size-h, resolveCalc($box-size-w, $path-width));
}
}
html,
body {
height: 100%;
}
body {
position: relative;
}
.wrap {
width:50%;
height:25%;
margin:50px auto;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
工作(编译为 css)演示:
.box::before, .box::after {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.box {
width: 80px;
height: 50px;
margin: auto;
color: #000;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
position: relative;
}
.box::before, .box::after {
content: '';
z-index: -1;
margin: 0;
box-shadow: inset 0 0 0 1px;
}
.box.active::before {
animation: clipMe 8s linear infinite;
animation-delay: -4s;
}
.box.active::after {
animation: clipMe 8s linear infinite;
}
.box.active:hover::after, .box.active:hover::before {
background-color: rgba(255, 255, 255, 0.3);
}
@keyframes clipMe {
0%, 100% {
clip: rect(0, 80px, 1px, 0);
}
25% {
clip: rect(0, 1px, 50px, 0);
}
50% {
clip: rect(calc(50px - 1px), 80px, 50px, 0);
}
75% {
clip: rect(0, 80px, 50px, calc(80px - 1px));
}
}
html,
body {
height: 100%;
}
body {
position: relative;
}
.wrap {
width: 50%;
height: 25%;
margin: 10px auto;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
<div class="wrap">
<div class="box active"></div>
</div>
【问题讨论】:
标签: css sass css-animations clip-path