Files
iroute/packages/idraw/lib/p12/s04.dart
2023-12-21 22:06:28 +08:00

168 lines
4.3 KiB
Dart

import 'dart:async';
import 'dart:math';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../components/coordinate_pro.dart';
/// create by 张风捷特烈 on 2020-03-19
/// contact me by email 1981462002@qq.com
/// 说明: 纸
class Paper extends StatelessWidget {
const Paper({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: RulerChooser(
onChanged: (value) {},
),
);
}
}
class RulerChooser extends StatefulWidget {
final Size size;
final void Function(double) onChanged;
final int min;
final int max;
const RulerChooser(
{Key? key,
required this.onChanged,
this.max = 200,
this.min = 100,
this.size = const Size(240.0, 60)})
: super(key: key);
@override
_RulerChooserState createState() => _RulerChooserState();
}
class _RulerChooserState extends State<RulerChooser> {
ValueNotifier<double> _dx = ValueNotifier(0.0);
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanUpdate: _parser,
child: CustomPaint(
size: widget.size,
painter: _HandlePainter(dx: _dx, max: widget.max, min: widget.min)),
);
}
double dx = 0;
void _parser(DragUpdateDetails details) {
dx += details.delta.dx;
if (dx > 0) {
dx = 0.0;
}
var limitMax = -(widget.max - widget.min) * (_kSpacer + _kStrokeWidth);
if (dx < limitMax) {
dx = limitMax;
}
_dx.value = dx;
if (widget.onChanged != null) {
widget.onChanged(details.delta.dx / (_kSpacer + _kStrokeWidth));
}
}
}
const double _kHeightLevel1 = 20; // 短线长
const double _kHeightLevel2 = 25; // 5 线长
const double _kHeightLevel3 = 30; //10 线长
const double _kPrefixOffSet = 5; // 左侧偏移
const double _kVerticalOffSet = 12; // 线顶部偏移
const double _kStrokeWidth = 2; // 刻度宽
const double _kSpacer = 4; // 刻度间隙
const List<Color> _kRulerColors = [
// 渐变色
Color(0xFF1426FB), Color(0xFF6080FB), Color(0xFFBEE0FB),
];
const List<double> _kRulerColorStops = [0.0, 0.2, 0.8];
class _HandlePainter extends CustomPainter {
var _paint = Paint();
Paint _pointPaint = Paint();
final ValueNotifier<double> dx;
final int max;
final int min;
_HandlePainter({required this.dx, required this.max, required this.min})
: super(repaint: dx) {
_paint
..strokeWidth = _kStrokeWidth
..shader = ui.Gradient.radial(
Offset(0, 0), 25, _kRulerColors, _kRulerColorStops, TileMode.mirror);
_pointPaint
..color = Colors.purple
..strokeWidth = 4
..strokeCap = StrokeCap.round;
}
@override
void paint(Canvas canvas, Size size) {
canvas.clipRect(Offset.zero & size);
drawArrow(canvas);
canvas.translate(dx.value, 0);
drawRuler(canvas);
}
// 绘制刻度
void drawRuler(Canvas canvas) {
double y = _kHeightLevel1;
for (int i = min; i < max + 5; i++) {
if (i % 5 == 0 && i % 10 != 0) {
y = _kHeightLevel2;
} else if (i % 10 == 0) {
y = _kHeightLevel3;
_simpleDrawText(canvas, i.toString(),
offset: Offset(-3, _kHeightLevel3 + 2));
} else {
y = _kHeightLevel1;
}
canvas.drawLine(Offset.zero, Offset(0, y), _paint);
canvas.translate(_kStrokeWidth + _kSpacer, 0);
}
}
// 绘制三角形尖角
void drawArrow(Canvas canvas) {
var path = Path()
..moveTo(_kStrokeWidth / 2 + _kPrefixOffSet, 3)
..relativeLineTo(-3, 0)
..relativeLineTo(3, _kPrefixOffSet)
..relativeLineTo(3, -_kPrefixOffSet)
..close();
canvas.drawPath(path, _pointPaint);
canvas.translate(_kStrokeWidth / 2 + _kPrefixOffSet, _kVerticalOffSet);
}
void _simpleDrawText(Canvas canvas, String str,
{Offset offset = Offset.zero}) {
var builder = ui.ParagraphBuilder(ui.ParagraphStyle())
..pushStyle(
ui.TextStyle(
color: Colors.black, textBaseline: ui.TextBaseline.alphabetic),
)
..addText(str);
canvas.drawParagraph(
builder.build()
..layout(ui.ParagraphConstraints(width: 11.0 * str.length)),
offset);
}
@override
bool shouldRepaint(_HandlePainter oldDelegate) =>
oldDelegate.dx != dx || oldDelegate.min != min || oldDelegate.max != max;
}