SVGA动画-react组件封装

SVGA动画介绍

SVGA 是一种跨平台的开源动画格式,同时兼容 iOS / Android / Web。SVGA 除了使用简单,性能卓越,同时让动画开发分工明确,各自专注各自的领域,大大减少动画交互的沟通成本,提升开发效率。动画设计师专注动画设计,通过工具输出 svga 动画文件,提供给开发工程师在集成 svga player 之后直接使用。动画开发从未如此简单!

SVGA 除了使用简单,性能卓越,同时让动画开发分工明确,各自专注各自的领域,大大减少动画交互的沟通成本,提升开发效率。

动画设计师专注动画设计,通过工具输出 svga 动画文件,提供给开发工程师在集成 SVGAPlayer 之后直接使用。

SVGA在动画播放前,会一次性地上传所有图片信息到GPU,在播放的过程中,这些图片信息会被重复使用。CPU与GPU 交换的次数大大减少,图片信息数目也在可控范围。内存、CPU、GPU 占用能达到最优状态,一个10几MB大的序列帧效果,用svga格式可以只要几百K甚至几十KSVGA 动画的性能可以得到极大的保障。SVGA官方也给出几点SVGA动画的优势:

设计沉思录|SVGA常见问题避坑指南

使用:直播礼物使用了SVGA动画、页面上banner里动画

使用:

iOS

  • 使用 CocoaPods 集成源码,将以下依赖:

  • pod 'SVGAPlayer'

  • 添加至 Podfile 文件。

  • 使用代码或 IB 添加 SVGAPlayer 至 View 中,具体方法参见:
    https://github.com/svga/SVGAPlayer-iOS

Android

  • 使用 Gradle 集成源码,添加 JitPack.io 到 root build.gradle 中
allprojects {
  repositories {
    ...
    maven { url 'https://jitpack.io' }
  }
}
  • 添加以下依赖
compile 'com.github.svga:SVGAPlayer-Android:2.0.0'

Web

在线播放器:https://svga.io/svga-preview.html

转换svga为png序列或svg动画:https://www.nangonghan.com/svga/

 

web案例:

var player = new SVGA.Player('#demoCanvas');
var parser = new SVGA.Parser(); 
parser.load('img/bb.svga', function(videoItem) {
    player.setVideoItem(videoItem);
    player.startAnimation();
    player.onFrame(function (i) {})
});

React组件封装:

import React from "react";
import SVGA, { Player, Parser, VideoEntity } from "svgaplayerweb";

interface Props {
  delay?: number;
  onFrame?: () => void;
  getInstance?: (e: any) => void;

  width: number;
  height: number;
  url: string;
  onLoad?: () => void;
}
interface State {}
class SvgaPlayer extends React.Component<Props, State> {
  private player: Player;
  private parser: Parser;
  private svgaRef: React.RefObject<HTMLDivElement>;
  static defaultProps: Partial<Props>;
  constructor(props: Props) {
    super(props);

    this.player = null;
    this.parser = null;
    this.svgaRef = React.createRef();
    this.init = this.init.bind(this);
    this.onAnimationLoaded = this.onAnimationLoaded.bind(this);
  }

  componentDidMount() {
    this.init(this.props.url);
  }

  componentWillReceiveProps(nextProps: Props) {
    if (nextProps.url !== this.props.url) {
      this.init(nextProps.url);
    }
  }

  componentWillUnmount() {
    if (this.parser) {
      this.parser = null;
      this.player.stopAnimation();
    }
  }

  render() {
    const { width, height } = this.props;

    return (
      <div
        style={
   
   { width, height }}
        className="svga-wraper"
      >
        <div ref={this.svgaRef} className="svga-con">
          {/* <canvas width="573" height="471" style="background-color: transparent;"></canvas> */}
        </div>
      </div>
    );
  }

  init(svgaUrl: string) {
    this.player = new SVGA.Player(this.svgaRef.current);
    //   this.player.loops = 0;
    //   this.player.clearsAfterStop = false;
    this.parser = new SVGA.Parser();
    this.parser.load(svgaUrl, this.onAnimationLoaded);
    this.player.onFrame(this.props.onFrame);
  }

  onAnimationLoaded = (videoItem: VideoEntity) => {
    this.player.setVideoItem(videoItem);
    const me = this;
    setTimeout(function () {
      me.props.onLoad();
      me.player.startAnimation();
    }, this.props.delay);
  };
}

SvgaPlayer.defaultProps = {
  height: 0,
  width: 0,

  delay: 0,
  url: "",
  //getInstance: function (e) {
  //  return e;
  //},
  onLoad: () => {},
  onFrame: () => {},
};

export default SvgaPlayer;

样式:

.svga-wraper {
  padding: 0;
  position: relative;
  margin: auto;
}

.svga-con {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

最近遇到一个bug,封装了一个播放svga的组件,之前使用正常,最近使用发现svga动画不播放了:

               

如上第一张图片:svga根本不播放,第二张svga播放,但是当点击下面的按钮弹出弹窗后如第三章图片,此后svga动画就会停止不在播放。

原因是项目中为了兼容处理了requestAnimationFrame这个API:

window.requestAnimationFrame = () => {
  return (
    window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    function (e) {
      window.setTimeout(e, 1e3 / 60);
    }
  );
};

svgaplayerweb库源码中使用了requestAnimationFrame这个api绘制动画,new SVGA.Player(container)就是在contanner中创建canvas标签插入,之后根据父元素或svga动画本身尺寸以及页面的dpr等设置ctx.setTransform以及canvas画布的width和height,之后根据svga中图片序列帧图片遍历处理这些图片使用canvas一帧帧绘制出来,之后使用第三方动画库等绘制出动画。

猜你喜欢

转载自blog.csdn.net/CamilleZJ/article/details/116271230