使用RequestAnimationFrame为SVG动画-消失的元素

时间:2018-08-21 16:26:59

标签: javascript animation svg

我已经陷入一个无法找到任何信息的问题,也许某个在svg方面有丰富经验的人可以伸出援手。

我以编程方式(以下代码)创建了svg星,并希望动态更改其linearGradient offset。当您在检查器中查看时,该值将按预期随着时间变化,到达目标时动画将被取消。问题是-svg不再出现...

HTML:

<div id="newStars"></div>

CSS:

  svg[id*='svg'] {
    transform: scale(0);
  }
  #icon-star1, .animation {
    transform-origin: 50% 50%;
    animation: animateStar 1s linear forwards;
  }
  @keyframes animateStar {
    0% {
      transform: scale(0) rotate(0deg);
    }
    50% {
      transform: scale(1.1) rotate(180deg);
    }
    75% {
      transform:  rotate(360deg);
    }
    100% {
      transform: scale(1);
    }
  }

JS:

function createStar(nb) {
  const svgns = 'http://www.w3.org/2000/svg';

  const svg = document.createElementNS(svgns, 'svg');
  const defs = document.createElementNS(svgns, 'defs');
  const gradient = document.createElementNS(svgns, 'linearGradient');
  const g = document.createElementNS(svgns, 'g');
  const path = document.createElementNS(svgns, 'path');
  const div = document.createElement('div');

  const stops = [
    {
      'color': 'red',
      'offset': '0%',
    }, {
      'color': 'lightgrey',
      'offset': '0%',
    },
  ];

  for (let i = 0; i < stops.length; i++) {
    const stop = document.createElementNS(svgns, 'stop');
    stop.setAttribute('stop-color', stops[i].color);
    stop.setAttribute('offset', stops[i].offset);

    gradient.appendChild(stop);
  }

  // Apply the <lineargradient> to <defs>
  gradient.id = `Gradient${nb}`;
  gradient.setAttribute('x1', '0');
  gradient.setAttribute('x2', '100%');
  gradient.setAttribute('y1', '0');
  gradient.setAttribute('y2', '0');
  defs.appendChild(gradient);

  g.id = `g${nb}`;

  path.setAttribute('stroke', 'blue');
  path.setAttribute('stroke-width', '2');
  path.setAttribute('width', '100%');
  path.setAttribute('height', '100%');
  path.setAttribute('d', 'M20.388,10.918L32,12.118l-8.735,7.749L25.914,31.4l-9.893-6.088L6.127,31.4l2.695-11.533L0,12.118 l11.547-1.2L16.026,0.6L20.388,10.918z');
  path.setAttribute('fill', `url(#Gradient${nb})`);

  svg.setAttribute('width', '100%');
  svg.setAttribute('height', '100%');
  svg.setAttribute('version', '1.1');
  svg.setAttribute('xmlns', svgns);
  // svg.setAttribute('viewBox', '0 0 50 50');
  svg.id = `svg${nb}`;

  div.setAttribute('style', 'width:35px; height:35px;');


  svg.appendChild(defs);
  svg.appendChild(g);
  g.appendChild(path);
  div.appendChild(svg);
  document.querySelector('#newStars').appendChild(div);


  let ii=0;

  function anim() {
    ii++;
    $(`#Gradient${ nb } stop`)[0].setAttribute('offset', `${ii / 10}%`);
    $(`#Gradient${ nb } stop`)[1].setAttribute('offset', `${ii / 10}%`);

    if (ii >= 1000) {cancelAnimationFrame(anim_id)} else requestAnimationFrame(anim);
  }

  let anim_id = requestAnimationFrame(anim);

}


createStar(1);
createStar(2);
createStar(3);

第一次尝试是在循环中创建setTimeout's,但是即使按预期工作,我也发现它效率很低,并且在最后一次setTimeout发生之后同步调用另一个函数特别麻烦。这是可供参考的工作代码:

setTimeout(() => {
      for (let i = 1; i <= 1000; i++) {
        setTimeout(() => {
          $(`#Gradient${ nb } stop`)[0].setAttribute('offset', `${i / 10}%`);
          $(`#Gradient${ nb } stop`)[1].setAttribute('offset', `${i / 10}%`);
        }, i);
      }


      $(`#svg${nb}`).addClass('animation');
}, 1000 * (nb - 1)); 

0 个答案:

没有答案