Масштабирование флаттера векторных фигур
Чтобы нарисовать кривую Лиссажу, мы создаем в
LissajousApp
a и инициализировать в виджете объект для некоторых постоянных значений (3, 4).
Мы хотели бы подать заявку
FittedBox
с участием
BoxFit.contain
в
LissajousWidget
при следующих ограничениях:
- Мы не можем воссоздать объект. Учтите, что стоимость его создания слишком высока для повторного запуска.
- В
LissajousCurve
имеет особое соотношение сторон. Он должен отображаться с таким соотношением сторон. - Растеризация должна выполняться после масштабирования, чтобы заполнить холст, а не до этого.
Первое ограничение означает, что если мы
flutter run -d chrome
и измените размер браузера, мы должны увидеть
LissajousCurve.LissajousCurve...
а также
_LissajousWidgetState.build()
только один раз.
Performing hot restart... 105ms
Restarted application in 105ms.
LissajousCurve.LissajousCurve...
_LissajousWidgetState.build()
LissajousPainter.paint()...
LissajousPainter.paint()...
LissajousPainter.paint()...
Второе ограничение означает, что независимо от соотношения сторон окна просмотра соотношение сторон кривой должно сохраняться. Третий гарантирует, что мы не увидим артефактов сглаживания.
Как в настоящее время лучше всего удовлетворить эти три ограничения?
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'dart:ui';
void main() => runApp(LissajousApp());
class LissajousApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return LissajousWidget(LissajousCurve(3, 4));
}
}
class LissajousWidget extends StatefulWidget {
LissajousCurve lissajousCurve;
LissajousWidget(this.lissajousCurve) {}
@override
_LissajousWidgetState createState() => _LissajousWidgetState();
}
class _LissajousWidgetState extends State<LissajousWidget> {
@override
Widget build(BuildContext context) {
print('_LissajousWidgetState.build()');
return CustomPaint(painter: LissajousPainter(widget.lissajousCurve));
}
}
class LissajousCurve {
Path path;
LissajousCurve(int a, int b) {
print('LissajousCurve.LissajousCurve...');
path = Path();
final int N = 10000;
final tValues = List.generate(N, (i) => -2 * math.pi + 6 * math.pi * i / N);
final xValues = tValues.map((t) => 30 * math.sin(3 * t)).toList();
final yValues = tValues.map((t) => 20 * math.sin(4 * t)).toList();
final points = List.generate(N, (i) {
return Offset(xValues[i], yValues[i]);
});
path = Path();
path.moveTo(points[0].dx, points[1].dy);
for (var i = 0; i < N; i++) {
path.lineTo(points[i].dx, points[i].dy);
}
path.close();
}
}
class LissajousPainter extends CustomPainter {
final LissajousCurve lissajousCurve;
LissajousPainter(this.lissajousCurve);
@override
void paint(Canvas canvas, Size size) {
print('LissajousPainter.paint()...');
final paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 4
..color = Colors.indigo;
canvas.drawPath(lissajousCurve.path, paint);
}
@override
bool shouldRepaint(LissajousPainter oldDelegate) => false;
}