CSS 将圆锥形渐变动画化为边框图像
CSS animate a conical gradient as border image
我正在尝试使用 css 作为 boder 图像为圆锥形渐变制作动画。我使用 code pan from another developer 作为样板并尝试更改它。他的动画使用自定义 属性 来旋转边框图像:
div {
--angle: 0deg;
width: 50vmin;
height: 50vmin;
border: 10vmin solid;
border-image: conic-gradient(from var(--angle), red, yellow, lime, aqua, blue, magenta, red) 1;
animation: 10s rotate linear infinite;
}
@keyframes rotate {
to {
--angle: 360deg;
}
}
@property --angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
我试过animate the actual gradien which did not work。我想以这样的方式找到工作:
div {
--angle: 0%;
width: 50vmin;
height: 50vmin;
border: 10vmin solid;
border-image: conic-gradient(from 0deg at 50% 50%, rgba(0, 154, 177, 0) 0%, rgba(0, 154, 177, 0) var(--angle), rgba(0, 154, 177, 1) var(--angle), rgba(0, 154, 177, 1) 100%, rgba(0, 154, 177, 0) 100%, rgba(0, 154, 177, 0) 100%) 1;
animation: 10s rotate linear infinite;
}
@keyframes rotate {
from {
--angle: 0%;
}
to {
--angle: 25%;
}
}
@property --angle {
syntax: '<angle>';
initial-value:0%;
inherits: false;
}
[更新]
通过使用 clip-path 选项,我现在的结果是这样的:
div {
padding: 10px;
}
a{
position:relative;
text-decoration: none;
padding: 10px 20px;
background-color: transparent;
transition: background-color .5s ease-in;
}
a:after{
content:"";
position:absolute;
border:1px solid black;
top:0;
left:0;
width:100%;
height:100%;
box-sizing: border-box;
}
a:hover{
background-color: rgba(0,0,0,.2);
}
a:hover:after{
animation: .8s clipping-border ease-in forwards;
}
* {
box-sizing: border-box;
}
@keyframes clipping-border {
from {
clip-path:polygon(0% 100%, 100% 100%,100% 0%,50% 0%,50% 50%,50% 0%,0% 0%);
}
40% {
clip-path:polygon(0% 100%, 100% 100%,100% 0%,100% 0%,50% 50%,0% 0%,0% 0%);
}
40.1% {
clip-path:polygon(0% 100%, 100% 100%,100% 0%,50% 50%,50% 50%,50% 50%,0% 0%);
}
60% {
clip-path:polygon(0% 100%, 100% 100%,100% 100%,50% 50%,50% 50%,50% 50%,0% 100%);
}
60.1% {
clip-path:polygon(0% 100%, 100% 100%,50% 50%,50% 50%,50% 50%,50% 50%,50% 50%);
}
62% {
clip-path:polygon(5% 100%, 95% 100%,95% 50%,95% 50%,5% 50%,5% 50%,5% 50%);
border-width: 1px;
}
to {
clip-path:polygon(5% 100%, 95% 100%,95% 50%,95% 50%,5% 50%,5% 50%,5% 50%);
border-width: 5px;
}
}
<div>
<a href="#">Some button</a>
</div>
像下面这样更新您的代码。 select 正确的类型很重要,您使用的是百分比而不是角度:
div {
--angle: 0%;
width: 50vmin;
height: 50vmin;
border: 10vmin solid;
border-image: conic-gradient(transparent var(--angle), rgba(0, 154, 177, 1) 0 100%) 1;
animation: 10s rotate linear infinite;
}
@keyframes rotate {
to {
--angle: 100%;
}
}
@property --angle {
syntax: '<percentage>'; /* this one is important */
initial-value: 0%;
inherits: false;
}
input[type="checkbox"] {
position: fixed;
top: 1em;
left: 1em;
}
input[type="checkbox"]:after {
content: 'Toggle Fill';
white-space: nowrap;
padding-left: 1.5em;
}
input[type="checkbox"]:checked+div {
border-image-slice: 1 fill;
}
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
display: grid;
place-items: center;
background: #fff;
}
footer {
text-align: center;
font-style: italic;
}
<input type="checkbox" />
<div></div>
或者像这样:
div {
--angle: 0deg;
width: 50vmin;
height: 50vmin;
border: 10vmin solid;
border-image: conic-gradient(from calc(-1*var(--angle)),transparent calc(2*var(--angle)), rgba(0, 154, 177, 1) 0 100%) 1;
animation: 10s rotate linear infinite;
}
@keyframes rotate {
to {
--angle: 180deg;
}
}
@property --angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
input[type="checkbox"] {
position: fixed;
top: 1em;
left: 1em;
}
input[type="checkbox"]:after {
content: 'Toggle Fill';
white-space: nowrap;
padding-left: 1.5em;
}
input[type="checkbox"]:checked+div {
border-image-slice: 1 fill;
}
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
display: grid;
place-items: center;
background: #fff;
}
footer {
text-align: center;
font-style: italic;
}
<input type="checkbox" />
<div></div>
没有 CSS 变量的另一个想法使用剪辑路径:
div {
width: 50vmin;
height: 50vmin;
position:relative;
}
div::before {
content:"";
position:absolute;
inset:-10vmin;
padding: 10vmin;
background:rgba(0, 154, 177, 1);
-webkit-mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
-webkit-mask-composite:destination-out;
mask-composite:exclude;
animation: 5s rotate linear infinite;
clip-path:polygon(0 0, 50% 0,50% 50%,50% 0,100% 0,100% 100%,0 100%);
}
@keyframes rotate {
20% {
clip-path:polygon(0 0, 0 0,50% 50%,100% 0,100% 0,100% 100%,0 100%);
}
75% {
clip-path:polygon(0 100%, 0 100%,50% 50%,100% 100%,100% 100%,100% 100%,0 100%);
}
100% {
clip-path:polygon(50% 100%, 50% 100%,50% 50%,50% 100%,50% 100%,50% 100%,50% 100%);
}
}
@property --angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
input[type="checkbox"] {
position: fixed;
top: 1em;
left: 1em;
}
input[type="checkbox"]:after {
content: 'Toggle Fill';
white-space: nowrap;
padding-left: 1.5em;
}
input[type="checkbox"]:checked+div:before {
-webkit-mask:none;
}
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
display: grid;
place-items: center;
background: #fff;
}
<input type="checkbox" />
<div></div>
我正在尝试使用 css 作为 boder 图像为圆锥形渐变制作动画。我使用 code pan from another developer 作为样板并尝试更改它。他的动画使用自定义 属性 来旋转边框图像:
div {
--angle: 0deg;
width: 50vmin;
height: 50vmin;
border: 10vmin solid;
border-image: conic-gradient(from var(--angle), red, yellow, lime, aqua, blue, magenta, red) 1;
animation: 10s rotate linear infinite;
}
@keyframes rotate {
to {
--angle: 360deg;
}
}
@property --angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
我试过animate the actual gradien which did not work。我想以这样的方式找到工作:
div {
--angle: 0%;
width: 50vmin;
height: 50vmin;
border: 10vmin solid;
border-image: conic-gradient(from 0deg at 50% 50%, rgba(0, 154, 177, 0) 0%, rgba(0, 154, 177, 0) var(--angle), rgba(0, 154, 177, 1) var(--angle), rgba(0, 154, 177, 1) 100%, rgba(0, 154, 177, 0) 100%, rgba(0, 154, 177, 0) 100%) 1;
animation: 10s rotate linear infinite;
}
@keyframes rotate {
from {
--angle: 0%;
}
to {
--angle: 25%;
}
}
@property --angle {
syntax: '<angle>';
initial-value:0%;
inherits: false;
}
[更新]
通过使用 clip-path 选项,我现在的结果是这样的:
div {
padding: 10px;
}
a{
position:relative;
text-decoration: none;
padding: 10px 20px;
background-color: transparent;
transition: background-color .5s ease-in;
}
a:after{
content:"";
position:absolute;
border:1px solid black;
top:0;
left:0;
width:100%;
height:100%;
box-sizing: border-box;
}
a:hover{
background-color: rgba(0,0,0,.2);
}
a:hover:after{
animation: .8s clipping-border ease-in forwards;
}
* {
box-sizing: border-box;
}
@keyframes clipping-border {
from {
clip-path:polygon(0% 100%, 100% 100%,100% 0%,50% 0%,50% 50%,50% 0%,0% 0%);
}
40% {
clip-path:polygon(0% 100%, 100% 100%,100% 0%,100% 0%,50% 50%,0% 0%,0% 0%);
}
40.1% {
clip-path:polygon(0% 100%, 100% 100%,100% 0%,50% 50%,50% 50%,50% 50%,0% 0%);
}
60% {
clip-path:polygon(0% 100%, 100% 100%,100% 100%,50% 50%,50% 50%,50% 50%,0% 100%);
}
60.1% {
clip-path:polygon(0% 100%, 100% 100%,50% 50%,50% 50%,50% 50%,50% 50%,50% 50%);
}
62% {
clip-path:polygon(5% 100%, 95% 100%,95% 50%,95% 50%,5% 50%,5% 50%,5% 50%);
border-width: 1px;
}
to {
clip-path:polygon(5% 100%, 95% 100%,95% 50%,95% 50%,5% 50%,5% 50%,5% 50%);
border-width: 5px;
}
}
<div>
<a href="#">Some button</a>
</div>
像下面这样更新您的代码。 select 正确的类型很重要,您使用的是百分比而不是角度:
div {
--angle: 0%;
width: 50vmin;
height: 50vmin;
border: 10vmin solid;
border-image: conic-gradient(transparent var(--angle), rgba(0, 154, 177, 1) 0 100%) 1;
animation: 10s rotate linear infinite;
}
@keyframes rotate {
to {
--angle: 100%;
}
}
@property --angle {
syntax: '<percentage>'; /* this one is important */
initial-value: 0%;
inherits: false;
}
input[type="checkbox"] {
position: fixed;
top: 1em;
left: 1em;
}
input[type="checkbox"]:after {
content: 'Toggle Fill';
white-space: nowrap;
padding-left: 1.5em;
}
input[type="checkbox"]:checked+div {
border-image-slice: 1 fill;
}
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
display: grid;
place-items: center;
background: #fff;
}
footer {
text-align: center;
font-style: italic;
}
<input type="checkbox" />
<div></div>
或者像这样:
div {
--angle: 0deg;
width: 50vmin;
height: 50vmin;
border: 10vmin solid;
border-image: conic-gradient(from calc(-1*var(--angle)),transparent calc(2*var(--angle)), rgba(0, 154, 177, 1) 0 100%) 1;
animation: 10s rotate linear infinite;
}
@keyframes rotate {
to {
--angle: 180deg;
}
}
@property --angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
input[type="checkbox"] {
position: fixed;
top: 1em;
left: 1em;
}
input[type="checkbox"]:after {
content: 'Toggle Fill';
white-space: nowrap;
padding-left: 1.5em;
}
input[type="checkbox"]:checked+div {
border-image-slice: 1 fill;
}
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
display: grid;
place-items: center;
background: #fff;
}
footer {
text-align: center;
font-style: italic;
}
<input type="checkbox" />
<div></div>
没有 CSS 变量的另一个想法使用剪辑路径:
div {
width: 50vmin;
height: 50vmin;
position:relative;
}
div::before {
content:"";
position:absolute;
inset:-10vmin;
padding: 10vmin;
background:rgba(0, 154, 177, 1);
-webkit-mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
-webkit-mask-composite:destination-out;
mask-composite:exclude;
animation: 5s rotate linear infinite;
clip-path:polygon(0 0, 50% 0,50% 50%,50% 0,100% 0,100% 100%,0 100%);
}
@keyframes rotate {
20% {
clip-path:polygon(0 0, 0 0,50% 50%,100% 0,100% 0,100% 100%,0 100%);
}
75% {
clip-path:polygon(0 100%, 0 100%,50% 50%,100% 100%,100% 100%,100% 100%,0 100%);
}
100% {
clip-path:polygon(50% 100%, 50% 100%,50% 50%,50% 100%,50% 100%,50% 100%,50% 100%);
}
}
@property --angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
input[type="checkbox"] {
position: fixed;
top: 1em;
left: 1em;
}
input[type="checkbox"]:after {
content: 'Toggle Fill';
white-space: nowrap;
padding-left: 1.5em;
}
input[type="checkbox"]:checked+div:before {
-webkit-mask:none;
}
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
display: grid;
place-items: center;
background: #fff;
}
<input type="checkbox" />
<div></div>