flutter开发实战-svga播放svgaplayer_flutter直播礼物特效等效果使用
最近开发过程中用到了SVGA进行播放动画,这里记录一下svgaplayer_flutter使用过程。svga可以做一些非常精美的动画,包括直播的刷礼物(火箭、跑车特效动画)等等。
效果图如下
一、SVGA与SVGAPlayer
- SVGA是什么呢?
SVGA 是一种同时兼容 iOS、Android、Flutter、Web 多个平台的动画格式。
官网地址:https://svga.io/
- SVGAPlayer是什么呢?
SVGAPlayer是一个轻量的动画渲染库。你可以使用工具从Adobe Animate CC 或者Adobe After Effects 中导出动画文件,然后使用 SVGAPlayer 在移动设备上渲染并播放。
二、svgaplayer_flutter
svgaplayer_flutter通过CustomPainter进行渲染动画。
2.1、引入svgaplayer_flutter
在工程中的pubspec.yaml中引入svgaplayer_flutter
# svg
svgaplayer_flutter: ^2.2.0
2.2、使用SVGASimpleImage
class MyWidget extends Widget {
Widget build(BuildContext context) {
return Container(
child: SVGASimpleImage(
resUrl: "https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true"),
);
}
}
2.3、使用SVGAAnimationController
若要控制动画渲染,需要像Flutter常规动画一样创建SVGAAnimationController实例。分配给SVGAImage,使用SVGAParser加载和解码资源,然后使用SVGAAnimationController按需执行操作。
i
mport 'package:flutter/material.dart';
import 'package:svgaplayer_flutter/svgaplayer_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
SVGAAnimationController animationController;
void initState() {
this.animationController = SVGAAnimationController(vsync: this);
this.loadAnimation();
super.initState();
}
void dispose() {
this.animationController.dispose();
super.dispose();
}
void loadAnimation() async {
final videoItem = await SVGAParser.shared.decodeFromURL(
"https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true");
this.animationController.videoItem = videoItem;
this
.animationController
.repeat() // Try to use .forward() .reverse()
.whenComplete(() => this.animationController.videoItem = null);
}
Widget build(BuildContext context) {
return Container(
child: SVGAImage(this.animationController),
);
}
}
2.4、MovieEntity重用
AnimationController的dispose调用后,MovieEntity也将被dispose。在dispose后,MovieEntity不能再使用。
如果要重用MovieEntity,需要设置autorelease为false
final videoItem = await SVGAParser.shared.decodeFromURL(
"https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true");
videoItem.autorelease = false;
最后在不需要使用videoItem,调用dispose即可
2.5、使用位图替换元素
在我参照H5时候看到代码,可以使用setImage替换元素
var player = new SVGA.Player("#pCanvas");
var parser = new SVGA.Parser('#pCanvas');
parser.load('https://github.com/yyued/SVGA-Samples/blob/master/angel.svga', function(item) {
player.loops = 1;
player.clearsAfterStop = false;
player.setImage("imageUrl", "imageKey");
player.setVideoItem(item);
player.startAnimation();
player.onFrame(function (i) { });
});
之后找到在svgaplayer_flutter也可以使用位图替换指定元素,需要使用的是SVGADynamicEntity
setImage、setImageWithUrl
void setImage(ui.Image image, String forKey) {
this.dynamicImages[forKey] = image;
}
Future<void> setImageWithUrl(String url, String forKey) async {
this.dynamicImages[forKey] =
await decodeImageFromList((await get(Uri.parse(url))).bodyBytes);
}
具体实现如下
Future<void> startSVGAAnim() async {
animationController = SVGAAnimationController(vsync: this);
var file = await CustomCacheManager().getSingleFile(
"https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true");
var bodyBytes = await file.readAsBytes();
final videoItem = await SVGAParser.shared.decodeFromBuffer(bodyBytes);
animationController?.videoItem = videoItem;
animationController?.videoItem?.dynamicItem.setImageWithUrl("图片地址", "img_key");
animationController?.forward().whenComplete(() {
});
if (mounted) {
setState(() {});
}
}
imageKey为SVGA动画中的图层png的文件名,图层png的文件名为abc.png,那么imageKey则为abc。
2.6、使用文本替换元素
在上面使用位图替换指定元素,也可以使用文本替换元素。
在SVGADynamicEntity,可以找到方法
void setText(TextPainter textPainter, String forKey) {
if (textPainter.textDirection == null) {
textPainter.textDirection = TextDirection.ltr;
textPainter.layout();
}
this.dynamicText[forKey] = textPainter;
}
具体文本替换元素的代码
Future<void> startSVGAAnim() async {
animationController = SVGAAnimationController(vsync: this);
var file = await CustomCacheManager().getSingleFile(
"https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true");
var bodyBytes = await file.readAsBytes();
final videoItem = await SVGAParser.shared.decodeFromBuffer(bodyBytes);
animationController?.videoItem = videoItem;
animationController?.videoItem?.dynamicItem.setText(
TextPainter(
text: TextSpan(
text: "Flutter!",
style: TextStyle(
fontSize: 20,
color: Colors.red,
fontWeight: FontWeight.bold,
))),
"imageKey");
animationController?.forward().whenComplete(() {
});
if (mounted) {
setState(() {});
}
}
imageKey为SVGA动画中的图层png的文件名,图层png的文件名为abc.png,那么imageKey则为abc。
2.7、隐藏显示指定元素
在SVGADynamicEntity也可以隐藏显示指定元素。
SVGADynamicEntity类中找到方法
void setHidden(bool value, String forKey) {
this.dynamicHidden[forKey] = value;
}
具体隐藏显示指定元素的代码
Future<void> startSVGAAnim() async {
animationController = SVGAAnimationController(vsync: this);
var file = await CustomCacheManager().getSingleFile(
"https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true");
var bodyBytes = await file.readAsBytes();
final videoItem = await SVGAParser.shared.decodeFromBuffer(bodyBytes);
animationController?.videoItem = videoItem;
animationController?.videoItem?.dynamicItem.setHidden(true, "imageKey"); // true隐藏元素,false显示元素
animationController?.forward().whenComplete(() {
});
if (mounted) {
setState(() {});
}
}
imageKey为SVGA动画中的图层png的文件名,图层png的文件名为abc.png,那么imageKey则为abc。
2.8、指定元素动态绘制
在SVGADynamicEntity可以在指定元素动态绘制图形。
SVGADynamicEntity类中找到方法
void setDynamicDrawer(SVGACustomDrawer drawer, String forKey) {
this.dynamicDrawer[forKey] = drawer;
}
具体在指定元素动态绘制图形的代码
Future<void> startSVGAAnim() async {
animationController = SVGAAnimationController(vsync: this);
var file = await CustomCacheManager().getSingleFile(
"https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true");
var bodyBytes = await file.readAsBytes();
final videoItem = await SVGAParser.shared.decodeFromBuffer(bodyBytes);
animationController?.videoItem = videoItem;
animationController?.videoItem?.dynamicItem.setDynamicDrawer((canvas, frameIndex) {
canvas.drawRect(Rect.fromLTWH(50, 50, 100, 100), Paint()..color = Colors.blue);
}, "forKey");
animationController?.forward().whenComplete(() {
});
if (mounted) {
setState(() {});
}
}
forKey为SVGA动画中的图层png的文件名,图层png的文件名为abc.png,那么imageKey则为abc。
三、小结
flutter开发实战-svga播放svgaplayer_flutter使用,svgaplayer_flutter播放SVGA,替换指定元素。
学习记录,每天不停进步。