我有一个CustomPainter
可以在屏幕截图中画出这种心形,但是当我做一个简单的动画(例如缩放)时,我发现动画滞后了(它掉了很多帧),但是令人惊讶的是当我不要将笔划宽度设置为绘制对象,动画会顺利进行。
我的问题是: 如何设置笔触宽度并同时获得平滑的动画?
这是完整的应用程序:
import 'package:flutter/material.dart';
void main() {
runApp(Page());
}
class Page extends StatefulWidget {
@override
_PageState createState() => _PageState();
}
class _PageState extends State<Page> with TickerProviderStateMixin {
AnimationController _controller;
var scale = 1.0;
@override
void initState() {
_controller = AnimationController(
vsync: this,
lowerBound: 1.0,
upperBound: 2.0,
duration: Duration(seconds: 3));
_controller.addListener(() {
setState(() {
scale = _controller.value;
});
});
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: Center(
child: Container(
width: 130,
height: 200,
child: GestureDetector(
onTap: () => _controller.forward(from: 0.0),
child: Transform.scale(
scale: scale,
child: CustomPaint(
painter: HeartsPainter(),
),
),
),
),
),
),
Text("Tap to animate", textDirection: TextDirection.ltr),
],
);
}
}
class HeartsPainter extends CustomPainter {
final Paint hearPaint = Paint()
..strokeWidth = 1
..style = PaintingStyle.stroke;
@override
void paint(Canvas canvas, Size size) {
print('Hearts Painting..');
const int count = 100;
for (int i = 0; i < count; i++) {
_drawHeart(
canvas,
Size((i + 1) / count * size.width, (i + 1) / count * size.height),
Colors.blue.withRed((i / count * 255).toInt()).withOpacity(0.4));
}
}
void _drawHeart(Canvas canvas, Size size, Color color) {
final Path path = Path();
final double width = size.width;
final double height = size.height;
// Starting point
path.moveTo(width / 2, height / 5);
// Upper left path
path.cubicTo(5 * width / 14, 0, 0, height / 15, width / 28, 2 * height / 5);
// Lower left path
path.cubicTo(width / 14, 2 * height / 3, 3 * width / 7, 5 * height / 6,
width / 2, height);
// Lower right path
path.cubicTo(4 * width / 7, 5 * height / 6, 13 * width / 14, 2 * height / 3,
27 * width / 28, 2 * height / 5);
// Upper right path
path.cubicTo(width, height / 15, 9 * width / 14, 0, width / 2, height / 5);
canvas.drawPath(path, hearPaint..color = color);
}
@override
bool shouldRepaint(HeartsPainter oldDelegate) => false;
}
答案 0 :(得分:0)
我的问题是:如何设置笔触宽度并变得平滑 动画同时播放?
使用AnimatedBuilder而不是setState,可以在AnimatedBuilder中将预构建窗口小部件作为子参数传递。
使用此预建子项完全是可选的,但可以改善 在某些情况下表现出色,因此是一个很好的选择 练习。
在循环之前创建心脏路径。
使用另一个画布对象来变换心脏。
别忘了产品发布会更快。
import 'dart:ui';
import 'package:flutter/material.dart';
void main() {
runApp(Page());
}
class Page extends StatefulWidget {
@override
_PageState createState() => _PageState();
}
class _PageState extends State<Page> with TickerProviderStateMixin {
AnimationController _controller;
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
void initState() {
_controller = AnimationController(
vsync: this,
lowerBound: 1.0,
upperBound: 2.0,
duration: Duration(seconds: 3),
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: Center(
child: Container(
width: 130,
height: 200,
child: GestureDetector(
onTap: () => _controller.forward(from: 0.0),
child: AnimatedBuilder(
animation: _controller,
child: CustomPaint(
painter: HeartsPainter(),
),
builder: (context, child) {
return Transform.scale(
scale: _controller.value,
child: child,
);
},
),
),
),
),
),
Text("Tap to animate", textDirection: TextDirection.ltr),
],
);
}
}
class HeartsPainter extends CustomPainter {
final Paint heartPaint = Paint()
..strokeWidth = 1
..style = PaintingStyle.stroke;
@override
void paint(Canvas mainCanvas, Size size) {
var heartRecordeer = PictureRecorder();
var canvas = Canvas(heartRecordeer);
var path = _drawHeart(Size(size.width, size.height));
var count = 100;
for (var i = 0; i < count; i++) {
canvas.transform(
(Matrix4.identity()..scale(98 / 100)).storage,
);
canvas.drawPath(
path,
heartPaint..color = Colors.blue.withRed((i / count * 255).toInt()).withOpacity(0.4),
);
}
var picture = heartRecordeer.endRecording();
mainCanvas.drawPicture(picture);
}
@override
bool shouldRepaint(HeartsPainter oldDelegate) => false;
Path _drawHeart(Size size) {
final Path path = Path();
final double width = size.width;
final double height = size.height;
// Starting point
path.moveTo(width / 2, height / 5);
// Upper left path
path.cubicTo(5 * width / 14, 0, 0, height / 15, width / 28, 2 * height / 5);
// Lower left path
path.cubicTo(width / 14, 2 * height / 3, 3 * width / 7, 5 * height / 6, width / 2, height);
// Lower right path
path.cubicTo(4 * width / 7, 5 * height / 6, 13 * width / 14, 2 * height / 3, 27 * width / 28,
2 * height / 5);
// Upper right path
path.cubicTo(width, height / 15, 9 * width / 14, 0, width / 2, height / 5);
return path;
}
}