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>