径向圆动画

时间:2017-04-12 17:45:04

标签: css animation svg

我试图创建一个循环动画,跟随其他东西的旋转......我很难创建渐变圆动画:https://jsfiddle.net/rmtu913c/

圈子的动画代码是:

.circular-loader {
height: 116%;
width: 121%;
animation: rotate 5s ease-in-out infinite;
transform-origin: center center;
position: absolute;
top: 0;
left: 0;
margin: auto;
}

我现在的问题是渐变总是可见的,现在我只是旋转svg容器,我不知何故需要创建某种“掩码”以达到想要的效果......

我想要实现的是: Circle Animation Illustrated

我希望有人知道如何实现这一目标...我已经尝试了所有不同的方式大约7个小时,但仍然没有运气:( :(

1 个答案:

答案 0 :(得分:0)

生成半圆形渐变的版本非常容易,它使用线性渐变来近似弧度渐变。

body {
  background-color: #2f2f2f;
}

path {
  animation: rot 1.5s linear infinite;
}

@keyframes rot {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
<svg width="300" height="300">
  <defs>
    <linearGradient id="bluefade" x1="0" y1="1" x2="0" y2="0">
      <stop offset="0.05" stop-color="#fff" stop-opacity="0"/>
      <stop offset="1" stop-color="#12b1db" stop-opacity="1"/>
    </linearGradient>
  </defs>

  <g transform="translate(150,150)">
    <path d="M 0,-120 A 120,120 0 0 0 0,120"
          fill="none" stroke="url(#bluefade)" stroke-width="25"/>
  </g>
</svg>

但是你的那个一直不是一个完整的半圆。它似乎从12点钟处的零长度增长,直到6点钟才达到180度的全长。这有点棘手。

我认为您将需要使用Javascript来修改渐变设置(位置),以便适合每个进度百分比。这需要一些三角法来计算正确的位置。

var progress = document.getElementById("progress");
var bluefade = document.getElementById("bluefade");
var RADIUS = 120;

function setProgress(percent)
{
  // Rotation of our semicircular disc representing the progress
  var rotateDeg = (percent * 360) / 100;

  // Calculate position of trailing position of arc segment.
  // At progress=0%, it will be at the same position as the leading point 
  // (0,-120),, a zero degree arc segment.
  // At 25% (3 o'clock) it will be at the 9 o'clock position of the semicircle.
  // At 50% (6 o'clock) it will be at the other side of the semicircle (ie 180deg
  // or (0,120). At >50% it doesn't move from that position.
  // This is also made the trailing point of the gradient.
  var trailAngleRad = Math.min(Math.PI, (percent * Math.PI * 2)/100);
  var x1 = -Math.sin(trailAngleRad) * RADIUS;
  var y1 = -Math.cos(trailAngleRad) * RADIUS;

  // Update the path
  progress.setAttribute("d", "M 0,-120 A 120,120 0 0 0 " + x1 + "," + y1);
  // Update the gradient
  bluefade.x1.baseVal.value = x1;
  bluefade.y1.baseVal.value = y1;

  progress.setAttribute("transform", "rotate(" + rotateDeg + ")");
}

setProgress(20);
body {
  background-color: #2f2f2f;
}
<svg width="300" height="300">
  <defs>
    <linearGradient id="bluefade"
                    gradientUnits="userSpaceOnUse"
                    x1="0" y1="120" x2="0" y2="-120">
      <stop offset="0.05" stop-color="#fff" stop-opacity="0"/>
      <stop offset="1" stop-color="#12b1db" stop-opacity="1"/>
    </linearGradient>
  </defs>

  <g transform="translate(150,150)">
    <path id="progress" d="M 0,-120 A 120,120 0 0 0 0,120"
          fill="none" stroke="url(#bluefade)" stroke-width="25"/>
  </g>
</svg>

或者在动画形式:

var progress = document.getElementById("progress");
var bluefade = document.getElementById("bluefade");
var RADIUS = 120;

function setProgress(percent)
{
  // Rotation of our semicircular disc representing the progress
  var rotateDeg = (percent * 360) / 100;

  // Calculate position of trailing position of arc segment.
  // At progress=0%, it will be at the same position as the leading point 
  // (0,-120),, a zero degree arc segment.
  // At 25% (3 o'clock) it will be at the 9 o'clock position of the semicircle.
  // At 50% (6 o'clock) it will be at the other side of the semicircle (ie 180deg
  // or (0,120). At >50% it doesn't move from that position.
  // This is also made the trailing point of the gradient.
  var trailAngleRad = Math.min(Math.PI, (percent * Math.PI * 2)/100);
  var x1 = -Math.sin(trailAngleRad) * RADIUS;
  var y1 = -Math.cos(trailAngleRad) * RADIUS;

  // Update the path
  progress.setAttribute("d", "M 0,-120 A 120,120 0 0 0 " + x1 + "," + y1);
  // Update the gradient
  bluefade.x1.baseVal.value = x1;
  bluefade.y1.baseVal.value = y1;

  progress.setAttribute("transform", "rotate(" + rotateDeg + ")");
}


var start = null;

function step(timestamp) {
  if (!start) start = timestamp;
  var percent = ((timestamp - start)/50) % 100;
  setProgress(percent);
  window.requestAnimationFrame(step);
}

window.requestAnimationFrame(step);
body {
  background-color: #2f2f2f;
}
<svg width="300" height="300">
  <defs>
    <linearGradient id="bluefade"
                    gradientUnits="userSpaceOnUse"
                    x1="0" y1="120" x2="0" y2="-120">
      <stop offset="0.05" stop-color="#fff" stop-opacity="0"/>
      <stop offset="1" stop-color="#12b1db" stop-opacity="1"/>
    </linearGradient>
  </defs>

  <g transform="translate(150,150)">
    <path id="progress" d="M 0,-120 A 120,120 0 0 0 0,120"
          fill="none" stroke="url(#bluefade)" stroke-width="25"/>
  </g>
</svg>