books
This commit is contained in:
758
assets/palettes.json
Normal file
758
assets/palettes.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -62,7 +62,6 @@ class MenuStore with ChangeNotifier {
|
|||||||
?.label;
|
?.label;
|
||||||
|
|
||||||
void selectMenuPath(String path) {
|
void selectMenuPath(String path) {
|
||||||
print("======================selectMenuPath:$path======${_shouldAddHistory}==============");
|
|
||||||
MenuNode root = MenuNode(
|
MenuNode root = MenuNode(
|
||||||
path: '',
|
path: '',
|
||||||
label: '',
|
label: '',
|
||||||
@@ -160,6 +159,14 @@ class MenuStore with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void select(MenuNode menu) {
|
void select(MenuNode menu) {
|
||||||
|
bool hasHistory = _history.where((e) => e.menuPath==menu.path).isNotEmpty;
|
||||||
|
if(hasHistory){
|
||||||
|
_shouldAddHistory = false;
|
||||||
|
selectMenuPath(menu.path);
|
||||||
|
notifyListeners();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (menu.isLeaf) {
|
if (menu.isLeaf) {
|
||||||
_state = state.copyWith(activeMenu: menu.path);
|
_state = state.copyWith(activeMenu: menu.path);
|
||||||
goRouter.go(menu.path);
|
goRouter.go(menu.path);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:components/components.dart';
|
import 'package:components/components.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:iroute/navigation/router/routers/anima.dart';
|
import 'package:iroute/navigation/router/routers/anima.dart';
|
||||||
@@ -7,13 +8,13 @@ import 'package:iroute/navigation/router/routers/render.dart';
|
|||||||
import 'package:iroute/navigation/router/routers/scroll.dart';
|
import 'package:iroute/navigation/router/routers/scroll.dart';
|
||||||
import 'package:iroute/navigation/router/routers/touch.dart';
|
import 'package:iroute/navigation/router/routers/touch.dart';
|
||||||
|
|
||||||
|
import '../../transition/size_clip_transition.dart';
|
||||||
import '../../views/app_navigation.dart';
|
import '../../views/app_navigation.dart';
|
||||||
import '../../../pages/empty/empty_panel.dart';
|
import '../../../pages/empty/empty_panel.dart';
|
||||||
import 'dashboard.dart';
|
import 'dashboard.dart';
|
||||||
import 'draw.dart';
|
import 'draw.dart';
|
||||||
import 'layout.dart';
|
import 'layout.dart';
|
||||||
|
|
||||||
|
|
||||||
final RouteBase appRoute = ShellRoute(
|
final RouteBase appRoute = ShellRoute(
|
||||||
builder: (BuildContext context, GoRouterState state, Widget child) {
|
builder: (BuildContext context, GoRouterState state, Widget child) {
|
||||||
return TolyBookNavigation(content: child);
|
return TolyBookNavigation(content: child);
|
||||||
@@ -29,9 +30,27 @@ final RouteBase appRoute = ShellRoute(
|
|||||||
animaRouters,
|
animaRouters,
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/code',
|
path: '/code',
|
||||||
builder: (BuildContext context, GoRouterState state) {
|
pageBuilder: (BuildContext context, GoRouterState state) {
|
||||||
String? path = state.uri.queryParameters['path'];
|
String? path = state.uri.queryParameters['path'];
|
||||||
return CodeView(path: path??'',);
|
return CustomTransitionPage(
|
||||||
|
transitionDuration: const Duration(milliseconds: 500),
|
||||||
|
reverseTransitionDuration: const Duration(milliseconds: 500),
|
||||||
|
child: CodeView(
|
||||||
|
path: path ?? '',
|
||||||
|
),
|
||||||
|
transitionsBuilder: (_, a1, a2, child) =>
|
||||||
|
SizeClipTransition(
|
||||||
|
animation: a1,
|
||||||
|
secondaryAnimation: a2,
|
||||||
|
child: child,
|
||||||
|
)
|
||||||
|
// CupertinoPageTransition(
|
||||||
|
// primaryRouteAnimation: a1,
|
||||||
|
// secondaryRouteAnimation: a2,
|
||||||
|
// linearTransition: true,
|
||||||
|
// child: child,
|
||||||
|
// ),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
|
|||||||
@@ -5,32 +5,76 @@ import 'package:iroute/pages/empty/empty_panel.dart';
|
|||||||
|
|
||||||
final RouteBase drawRouters = GoRoute(
|
final RouteBase drawRouters = GoRoute(
|
||||||
path: '/draw/chapter:index',
|
path: '/draw/chapter:index',
|
||||||
builder: (BuildContext context, GoRouterState state) {
|
pageBuilder: (BuildContext context, GoRouterState state) {
|
||||||
String? index = state.pathParameters['index'];
|
String? index = state.pathParameters['index'];
|
||||||
switch(index){
|
Widget child = const EmptyPanel(msg: '暂未实现');
|
||||||
|
switch (index) {
|
||||||
case '1':
|
case '1':
|
||||||
return const P01Page();
|
child = const P01Page();
|
||||||
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
return const P02Page();
|
child = const P02Page();
|
||||||
|
break;
|
||||||
case '3':
|
case '3':
|
||||||
return const P03Page();
|
child = const P03Page();
|
||||||
|
break;
|
||||||
case '4':
|
case '4':
|
||||||
return const P04Page();
|
child = const P04Page();
|
||||||
|
break;
|
||||||
case '5':
|
case '5':
|
||||||
return const P05Page();
|
child = const P05Page();
|
||||||
|
break;
|
||||||
case '6':
|
case '6':
|
||||||
return const P06Page();
|
child = const P06Page();
|
||||||
|
break;
|
||||||
case '7':
|
case '7':
|
||||||
return const P07Page();
|
child = const P07Page();
|
||||||
|
break;
|
||||||
case '8':
|
case '8':
|
||||||
return const P08Page();
|
child = const P08Page();
|
||||||
|
break;
|
||||||
case '9':
|
case '9':
|
||||||
return const P09Page();
|
child = const P09Page();
|
||||||
|
break;
|
||||||
case '10':
|
case '10':
|
||||||
return const P10Page();
|
child = const P10Page();
|
||||||
|
break;
|
||||||
case '11':
|
case '11':
|
||||||
return const P11Page();
|
child = const P11Page();
|
||||||
|
break;
|
||||||
|
case '12':
|
||||||
|
child = const P12Page();
|
||||||
|
break;
|
||||||
|
case '13':
|
||||||
|
child = const P13Page();
|
||||||
|
break;
|
||||||
|
case '14':
|
||||||
|
child = const P14Page();
|
||||||
|
break;
|
||||||
|
case '15':
|
||||||
|
child = const P15Page();
|
||||||
|
break;
|
||||||
|
case '16':
|
||||||
|
child = const P16Page();
|
||||||
|
break;
|
||||||
|
case '17':
|
||||||
|
child = const P17Page();
|
||||||
|
break;
|
||||||
|
case '18':
|
||||||
|
child = const P18Page();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return const EmptyPanel(msg: '暂未实现');
|
|
||||||
|
return CustomTransitionPage(
|
||||||
|
child: child,
|
||||||
|
transitionsBuilder: (ctx, a1, a2, child) => FadeTransition(
|
||||||
|
opacity: a1.drive(CurveTween(curve: Curves.easeIn)),
|
||||||
|
child: SlideTransition(
|
||||||
|
position: Tween<Offset>(
|
||||||
|
begin: Offset.zero, end: const Offset(-1.0, 0.0))
|
||||||
|
.animate(a2),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class FadePageTransitionsBuilder extends PageTransitionsBuilder {
|
class FadePageTransitionsBuilder extends PageTransitionsBuilder {
|
||||||
|
|
||||||
const FadePageTransitionsBuilder();
|
const FadePageTransitionsBuilder();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -12,31 +11,8 @@ class FadePageTransitionsBuilder extends PageTransitionsBuilder {
|
|||||||
Animation<double> secondaryAnimation,
|
Animation<double> secondaryAnimation,
|
||||||
Widget child,
|
Widget child,
|
||||||
) {
|
) {
|
||||||
return _FadePagePageTransition(
|
|
||||||
animation: animation,
|
|
||||||
secondaryAnimation: secondaryAnimation,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _FadePagePageTransition extends StatelessWidget {
|
|
||||||
|
|
||||||
const _FadePagePageTransition({
|
|
||||||
required this.animation,
|
|
||||||
required this.secondaryAnimation,
|
|
||||||
required this.child,
|
|
||||||
});
|
|
||||||
|
|
||||||
final Animation<double> animation;
|
|
||||||
final Animation<double> secondaryAnimation;
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
var curveTween = CurveTween(curve: Curves.easeIn);
|
|
||||||
return FadeTransition(
|
return FadeTransition(
|
||||||
opacity: animation.drive(curveTween),
|
opacity: animation.drive(CurveTween(curve: Curves.easeIn)),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
105
lib/navigation/transition/size_clip_transition.dart
Normal file
105
lib/navigation/transition/size_clip_transition.dart
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
|
class SizeClipTransition extends StatelessWidget {
|
||||||
|
final Animation<double> animation;
|
||||||
|
final Animation<double> secondaryAnimation;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const SizeClipTransition({
|
||||||
|
super.key,
|
||||||
|
required this.animation,
|
||||||
|
required this.secondaryAnimation,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ClipPath(
|
||||||
|
clipper: CirclePathClipper(Curves.easeIn.transform(animation.value)),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SizePathClipper extends CustomClipper<Path> {
|
||||||
|
final double progress;
|
||||||
|
|
||||||
|
SizePathClipper(this.progress);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Path getClip(Size size) {
|
||||||
|
Rect box = Rect.fromLTWH(0, 0, size.width, size.height);
|
||||||
|
Rect center = Rect.fromCenter(
|
||||||
|
center: Offset(size.width / 2, size.height / 2),
|
||||||
|
width: size.width * (1 - progress),
|
||||||
|
height: size.height,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Path()
|
||||||
|
..addRect(box)
|
||||||
|
..addRect(center)
|
||||||
|
..fillType = PathFillType.evenOdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldReclip(covariant SizePathClipper oldClipper) {
|
||||||
|
return oldClipper.progress != progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScalePathClipper extends CustomClipper<Path> {
|
||||||
|
final double progress;
|
||||||
|
|
||||||
|
ScalePathClipper(this.progress);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Path getClip(Size size) {
|
||||||
|
Rect box = Rect.fromLTWH(0, 0, size.width, size.height);
|
||||||
|
Rect center = Rect.fromCenter(
|
||||||
|
center: Offset(size.width / 2, size.height / 2),
|
||||||
|
width: size.width * (1 - progress),
|
||||||
|
height: size.height* (1 - progress),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Path()
|
||||||
|
..addRect(box)
|
||||||
|
..addRect(center)
|
||||||
|
..fillType = PathFillType.evenOdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldReclip(covariant ScalePathClipper oldClipper) {
|
||||||
|
return oldClipper.progress != progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CirclePathClipper extends CustomClipper<Path> {
|
||||||
|
final double progress;
|
||||||
|
|
||||||
|
CirclePathClipper(this.progress);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Path getClip(Size size) {
|
||||||
|
print('progress:$progress');
|
||||||
|
if(progress==0){
|
||||||
|
return Path();
|
||||||
|
}
|
||||||
|
Rect box = Rect.fromLTWH(0, 0, size.width, size.height);
|
||||||
|
Rect center = Rect.fromCircle(
|
||||||
|
center: Offset(size.width , 0),
|
||||||
|
radius: sqrt(size.width*size.width+size.height*size.height) * (progress),
|
||||||
|
);
|
||||||
|
|
||||||
|
Path zone = Path()..addRect(box);
|
||||||
|
Path cliper = Path()..addOval(center);
|
||||||
|
|
||||||
|
return Path.combine(PathOperation.intersect, zone, cliper );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldReclip(covariant CirclePathClipper oldClipper) {
|
||||||
|
return oldClipper.progress != progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ class TolyBookNavigation extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Row(
|
body: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class AppTopBar extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// String? lable = MenuScope.of(context).currentNode?.label;
|
// String? lable = MenuScope.of(context).currentNode?.label;
|
||||||
return DragToMoveWrap(
|
return DragToMoveWrap(
|
||||||
|
child: SizedBox(
|
||||||
|
height: 36,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
children: [Row(
|
children: [Row(
|
||||||
@@ -28,6 +30,7 @@ class AppTopBar extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),WindowButtons()]
|
),WindowButtons()]
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,20 +18,22 @@ class _CodeViewState extends State<CodeView> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
// TODO: implement initState
|
|
||||||
super.initState();
|
super.initState();
|
||||||
_loadContent();
|
_loadContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SingleChildScrollView(
|
return ColoredBox(
|
||||||
|
color: Colors.white,
|
||||||
|
child: SingleChildScrollView(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20),
|
padding: EdgeInsets.symmetric(horizontal: 20,vertical: 10),
|
||||||
child: Material(
|
child: Material(
|
||||||
child: CodeWidget(code:'${content}', style: HighlighterStyle.fromColors(HighlighterStyle.lightColor),),
|
child: CodeWidget(code:'${content}', style: HighlighterStyle.fromColors(HighlighterStyle.lightColor),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ class Coordinate {
|
|||||||
this.gridColor = Colors.grey});
|
this.gridColor = Colors.grey});
|
||||||
|
|
||||||
final Paint _gridPaint = Paint();
|
final Paint _gridPaint = Paint();
|
||||||
final Path _gridPath = Path();
|
|
||||||
|
|
||||||
void paint(Canvas canvas, Size size) {
|
void paint(Canvas canvas, Size size) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
@@ -30,6 +29,8 @@ class Coordinate {
|
|||||||
canvas.restore();
|
canvas.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _drawAxis(Canvas canvas, Size size) {
|
void _drawAxis(Canvas canvas, Size size) {
|
||||||
_gridPaint
|
_gridPaint
|
||||||
..color = Colors.blue
|
..color = Colors.blue
|
||||||
@@ -49,28 +50,30 @@ class Coordinate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _drawGridLine(Canvas canvas, Size size) {
|
void _drawGridLine(Canvas canvas, Size size) {
|
||||||
|
final Path path = Path();
|
||||||
|
|
||||||
_gridPaint
|
_gridPaint
|
||||||
..style = PaintingStyle.stroke
|
..style = PaintingStyle.stroke
|
||||||
..strokeWidth = .5
|
..strokeWidth = .5
|
||||||
..color = Colors.grey;
|
..color = Colors.grey;
|
||||||
|
|
||||||
for (int i = 0; i < size.width / 2 / step; i++) {
|
for (int i = 0; i < size.width / 2 / step; i++) {
|
||||||
_gridPath.moveTo(step * i, -size.height / 2 );
|
path.moveTo(step * i, -size.height / 2 );
|
||||||
_gridPath.relativeLineTo(0, size.height);
|
path.relativeLineTo(0, size.height);
|
||||||
|
|
||||||
_gridPath.moveTo(-step * i, -size.height / 2 );
|
path.moveTo(-step * i, -size.height / 2 );
|
||||||
_gridPath.relativeLineTo(0, size.height);
|
path.relativeLineTo(0, size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < size.height / 2 / step; i++) {
|
for (int i = 0; i < size.height / 2 / step; i++) {
|
||||||
_gridPath.moveTo(-size.width / 2,step * i );
|
path.moveTo(-size.width / 2,step * i );
|
||||||
_gridPath.relativeLineTo(size.width,0 );
|
path.relativeLineTo(size.width,0 );
|
||||||
|
|
||||||
_gridPath.moveTo(-size.width / 2,-step * i, );
|
path.moveTo(-size.width / 2,-step * i, );
|
||||||
_gridPath.relativeLineTo(size.width,0 );
|
path.relativeLineTo(size.width,0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.drawPath(_gridPath, _gridPaint);
|
canvas.drawPath(path, _gridPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _drawAxisText(Canvas canvas, String str,
|
void _drawAxisText(Canvas canvas, String str,
|
||||||
@@ -160,4 +163,3 @@ class Coordinate {
|
|||||||
canvas.restore();
|
canvas.restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,3 +11,10 @@ export 'p08/p08.dart';
|
|||||||
export 'p09/p09.dart';
|
export 'p09/p09.dart';
|
||||||
export 'p10/p10.dart';
|
export 'p10/p10.dart';
|
||||||
export 'p11/p11.dart';
|
export 'p11/p11.dart';
|
||||||
|
export 'p12/p12.dart';
|
||||||
|
export 'p13/p13.dart';
|
||||||
|
export 'p14/p14.dart';
|
||||||
|
export 'p15/p15.dart';
|
||||||
|
export 'p16/p16.dart';
|
||||||
|
export 'p17/p17.dart';
|
||||||
|
export 'p18/p18.dart';
|
||||||
|
|||||||
1
packages/idraw/lib/p12/p12.dart
Normal file
1
packages/idraw/lib/p12/p12.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export 'p12_page.dart';
|
||||||
25
packages/idraw/lib/p12/p12_page.dart
Normal file
25
packages/idraw/lib/p12/p12_page.dart
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:components/components.dart';
|
||||||
|
import 's01.dart' as s1;
|
||||||
|
import 's02.dart' as s2;
|
||||||
|
import 's03.dart' as s3;
|
||||||
|
import 's04.dart' as s4;
|
||||||
|
|
||||||
|
class P12Page extends StatelessWidget {
|
||||||
|
const P12Page({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const DemoShower(
|
||||||
|
srcCodeDir: 'draw/p12',
|
||||||
|
|
||||||
|
demos: [
|
||||||
|
s1.Paper(),
|
||||||
|
s2.Paper(),
|
||||||
|
s3.Paper(),
|
||||||
|
s4.Paper(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
66
packages/idraw/lib/p12/s01.dart
Normal file
66
packages/idraw/lib/p12/s01.dart
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/11/3
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: HandleWidget(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HandleWidget extends StatefulWidget {
|
||||||
|
final double size;
|
||||||
|
final double handleRadius;
|
||||||
|
|
||||||
|
HandleWidget({Key? key, this.size = 160.0, this.handleRadius = 20.0})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_HandleWidgetState createState() => _HandleWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HandleWidgetState extends State<HandleWidget> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CustomPaint(
|
||||||
|
size: Size(widget.size, widget.size),
|
||||||
|
painter: _HandlePainter(handleR: widget.handleRadius));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HandlePainter extends CustomPainter {
|
||||||
|
var _paint = Paint();
|
||||||
|
|
||||||
|
var handleR;
|
||||||
|
|
||||||
|
_HandlePainter({this.handleR}) {
|
||||||
|
_paint
|
||||||
|
..color = Colors.blue
|
||||||
|
..style = PaintingStyle.fill
|
||||||
|
..isAntiAlias = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
canvas.clipRect(Offset.zero & size);
|
||||||
|
|
||||||
|
final bgR = size.width / 2 - handleR;
|
||||||
|
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
_paint.color = _paint.color.withAlpha(100);
|
||||||
|
canvas.drawCircle(Offset(0, 0), bgR, _paint);
|
||||||
|
_paint.color = _paint.color.withAlpha(150);
|
||||||
|
canvas.drawCircle(Offset(0, 0), handleR, _paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(_HandlePainter oldDelegate) =>
|
||||||
|
oldDelegate.handleR != handleR;
|
||||||
|
}
|
||||||
109
packages/idraw/lib/p12/s02.dart
Normal file
109
packages/idraw/lib/p12/s02.dart
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
import 'package:flutter/material.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: HandleWidget(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HandleWidget extends StatefulWidget {
|
||||||
|
final double size;
|
||||||
|
final double handleRadius;
|
||||||
|
|
||||||
|
HandleWidget({Key? key, this.size = 160, this.handleRadius = 20.0})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_HandleWidgetState createState() => _HandleWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HandleWidgetState extends State<HandleWidget> {
|
||||||
|
ValueNotifier<Offset> _offset = ValueNotifier(Offset.zero);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onPanEnd: reset,
|
||||||
|
onPanUpdate: parser,
|
||||||
|
child: CustomPaint(
|
||||||
|
size: Size(widget.size, widget.size),
|
||||||
|
painter: _HandlePainter(
|
||||||
|
color: Colors.green,
|
||||||
|
handleR: widget.handleRadius,
|
||||||
|
offset: _offset)));
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(DragEndDetails details) {
|
||||||
|
_offset.value = Offset.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
parser(DragUpdateDetails details) {
|
||||||
|
final offset = details.localPosition;
|
||||||
|
double dx = 0.0;
|
||||||
|
double dy = 0.0;
|
||||||
|
|
||||||
|
dx = offset.dx - widget.size / 2;
|
||||||
|
dy = offset.dy - widget.size / 2;
|
||||||
|
var rad = atan2(dx, dy);
|
||||||
|
if (dx < 0) {
|
||||||
|
rad += 2 * pi;
|
||||||
|
}
|
||||||
|
var bgR = widget.size / 2 - widget.handleRadius;
|
||||||
|
var thta = rad - pi / 2; //旋转坐标系90度
|
||||||
|
if (sqrt(dx * dx + dy * dy) > bgR) {
|
||||||
|
dx = bgR * cos(thta);
|
||||||
|
dy = -bgR * sin(thta);
|
||||||
|
}
|
||||||
|
_offset.value = Offset(dx, dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HandlePainter extends CustomPainter {
|
||||||
|
final _paint = Paint();
|
||||||
|
final ValueNotifier<Offset> offset;
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
var handleR;
|
||||||
|
|
||||||
|
_HandlePainter({this.handleR,required this.offset, this.color = Colors.blue})
|
||||||
|
: super(repaint: offset) ;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
canvas.clipRect(Offset.zero & size);
|
||||||
|
|
||||||
|
final bgR = size.width / 2 - handleR;
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
_paint.style = PaintingStyle.fill;
|
||||||
|
_paint.color = color.withAlpha(100);
|
||||||
|
|
||||||
|
canvas.drawCircle(Offset(0, 0), bgR, _paint);
|
||||||
|
|
||||||
|
_paint.color = color.withAlpha(150);
|
||||||
|
|
||||||
|
canvas.drawCircle(
|
||||||
|
Offset(offset.value.dx, offset.value.dy), handleR, _paint);
|
||||||
|
|
||||||
|
_paint.color = color;
|
||||||
|
_paint.style = PaintingStyle.stroke;
|
||||||
|
canvas.drawLine(Offset.zero, offset.value, _paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(_HandlePainter oldDelegate) =>
|
||||||
|
oldDelegate.offset != offset ||
|
||||||
|
oldDelegate.color != color ||
|
||||||
|
oldDelegate.handleR != handleR;
|
||||||
|
}
|
||||||
153
packages/idraw/lib/p12/s03.dart
Normal file
153
packages/idraw/lib/p12/s03.dart
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
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 StatefulWidget{
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<Paper> createState() => _PaperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaperState extends State<Paper> {
|
||||||
|
double _rotate = 0;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Transform.rotate(
|
||||||
|
angle: _rotate,
|
||||||
|
child:
|
||||||
|
Container(
|
||||||
|
color: Colors.blue,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
HandleWidget(
|
||||||
|
onMove: _onMove,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onMove(double rotate, double distance) {
|
||||||
|
setState(() {
|
||||||
|
_rotate= rotate;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class HandleWidget extends StatefulWidget {
|
||||||
|
final double size;
|
||||||
|
final double handleRadius;
|
||||||
|
final void Function(double rotate, double distance) onMove;
|
||||||
|
|
||||||
|
HandleWidget(
|
||||||
|
{Key? key,
|
||||||
|
this.size = 160,
|
||||||
|
this.handleRadius = 20.0,
|
||||||
|
required this.onMove})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_HandleWidgetState createState() => _HandleWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HandleWidgetState extends State<HandleWidget> {
|
||||||
|
ValueNotifier<Offset> _offset = ValueNotifier(Offset.zero);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RepaintBoundary(
|
||||||
|
child: GestureDetector(
|
||||||
|
onPanEnd: reset,
|
||||||
|
onPanUpdate: parser,
|
||||||
|
child: CustomPaint(
|
||||||
|
size: Size(widget.size, widget.size),
|
||||||
|
painter: _HandlePainter(
|
||||||
|
color: Colors.green,
|
||||||
|
handleR: widget.handleRadius,
|
||||||
|
offset: _offset))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(DragEndDetails details) {
|
||||||
|
_offset.value = Offset.zero;
|
||||||
|
widget.onMove(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
parser(DragUpdateDetails details) {
|
||||||
|
final offset = details.localPosition;
|
||||||
|
double dx = 0.0;
|
||||||
|
double dy = 0.0;
|
||||||
|
|
||||||
|
dx = offset.dx - widget.size / 2;
|
||||||
|
dy = offset.dy - widget.size / 2;
|
||||||
|
var rad = atan2(dx, dy);
|
||||||
|
if (dx < 0) {
|
||||||
|
rad += 2 * pi;
|
||||||
|
}
|
||||||
|
var bgR = widget.size / 2 - widget.handleRadius;
|
||||||
|
var thta = rad - pi / 2; //旋转坐标系90度
|
||||||
|
var d = sqrt(dx * dx + dy * dy);
|
||||||
|
if (d > bgR) {
|
||||||
|
dx = bgR * cos(thta);
|
||||||
|
dy = -bgR * sin(thta);
|
||||||
|
}
|
||||||
|
widget.onMove(thta, d);
|
||||||
|
_offset.value = Offset(dx, dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HandlePainter extends CustomPainter {
|
||||||
|
var _paint = Paint();
|
||||||
|
final ValueNotifier<Offset> offset;
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
var handleR;
|
||||||
|
|
||||||
|
_HandlePainter({this.handleR,required this.offset, this.color = Colors.blue})
|
||||||
|
: super(repaint: offset);
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
|
||||||
|
canvas.clipRect(Offset.zero & size);
|
||||||
|
|
||||||
|
final bgR = size.width / 2 - handleR;
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
_paint.style = PaintingStyle.fill;
|
||||||
|
_paint.color = color.withAlpha(100);
|
||||||
|
|
||||||
|
canvas.drawCircle(Offset(0, 0), bgR, _paint);
|
||||||
|
|
||||||
|
_paint.color = color.withAlpha(150);
|
||||||
|
|
||||||
|
canvas.drawCircle(
|
||||||
|
Offset(offset.value.dx, offset.value.dy), handleR, _paint);
|
||||||
|
|
||||||
|
_paint.color = color;
|
||||||
|
_paint.style = PaintingStyle.stroke;
|
||||||
|
canvas.drawLine(Offset.zero, offset.value, _paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(_HandlePainter oldDelegate) =>
|
||||||
|
oldDelegate.offset != offset ||
|
||||||
|
oldDelegate.color != color ||
|
||||||
|
oldDelegate.handleR != handleR;
|
||||||
|
}
|
||||||
167
packages/idraw/lib/p12/s04.dart
Normal file
167
packages/idraw/lib/p12/s04.dart
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
1
packages/idraw/lib/p13/p13.dart
Normal file
1
packages/idraw/lib/p13/p13.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export 'p13_page.dart';
|
||||||
25
packages/idraw/lib/p13/p13_page.dart
Normal file
25
packages/idraw/lib/p13/p13_page.dart
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:components/components.dart';
|
||||||
|
import 's01.dart' as s1;
|
||||||
|
import 's02.dart' as s2;
|
||||||
|
import 's03.dart' as s3;
|
||||||
|
import 's04.dart' as s4;
|
||||||
|
|
||||||
|
class P13Page extends StatelessWidget {
|
||||||
|
const P13Page({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const DemoShower(
|
||||||
|
srcCodeDir: 'draw/p13',
|
||||||
|
|
||||||
|
demos: [
|
||||||
|
s1.Paper(),
|
||||||
|
s2.Paper(),
|
||||||
|
s3.Paper(),
|
||||||
|
s4.Paper(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
114
packages/idraw/lib/p13/s01.dart
Normal file
114
packages/idraw/lib/p13/s01.dart
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'dart:ui'as ui;
|
||||||
|
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
// 使用CustomPaint
|
||||||
|
painter: PaperPainter(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
|
||||||
|
final List<Offset> points = [];
|
||||||
|
|
||||||
|
final double step = 1;
|
||||||
|
final double min = 0;
|
||||||
|
final double max = 360;
|
||||||
|
|
||||||
|
void initPoints() {
|
||||||
|
for (double x = min; x <= max; x += step) {
|
||||||
|
points.add(Offset(x, f(x)));
|
||||||
|
// double thta = (pi / 180 * x);
|
||||||
|
// var p = f(thta);
|
||||||
|
// points.add(Offset(p * cos(thta), p * sin(thta)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initPointsWithPolar() {
|
||||||
|
for (double x = min; x <= max; x += step) {
|
||||||
|
double thta = (pi / 180 * x); // 角度转化为弧度
|
||||||
|
var p = f(thta);
|
||||||
|
points.add(Offset(p * cos(thta), p * sin(thta)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// double f(double x) {
|
||||||
|
// double y = -x * x / 200 + 100;
|
||||||
|
// return y;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// double f(double thta) {
|
||||||
|
// double p = 10 * thta;
|
||||||
|
// return p;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// double f(double thta) {
|
||||||
|
// double p = 100 * (1-cos(thta));
|
||||||
|
// return p;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// double f(double thta) {
|
||||||
|
// double p = 150*sin(5*thta).abs();
|
||||||
|
// return p;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
double f(double thta) { // 100*(1-4*sinθ)
|
||||||
|
double p = 50*(pow(e,cos(thta)) - 2 * cos(4 * thta) +pow(sin(thta / 12), 5));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
// initPoints();
|
||||||
|
initPointsWithPolar();
|
||||||
|
Path path = Path();
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.red
|
||||||
|
..strokeWidth = 1.5
|
||||||
|
..style = PaintingStyle.stroke;
|
||||||
|
var colors = [
|
||||||
|
Color(0xFFF60C0C),
|
||||||
|
Color(0xFFF3B913),
|
||||||
|
Color(0xFFE7F716),
|
||||||
|
Color(0xFF3DF30B),
|
||||||
|
Color(0xFF0DF6EF),
|
||||||
|
Color(0xFF0829FB),
|
||||||
|
Color(0xFFB709F4),
|
||||||
|
];
|
||||||
|
var pos = [1.0 / 7, 2.0 / 7, 3.0 / 7, 4.0 / 7, 5.0 / 7, 6.0 / 7, 1.0];
|
||||||
|
|
||||||
|
paint.shader = ui.Gradient.linear(
|
||||||
|
Offset(0, 0), Offset(100, 0), colors, pos,TileMode.mirror);
|
||||||
|
|
||||||
|
// canvas.drawPoints(PointMode.points, points, paint);
|
||||||
|
canvas.drawPoints(PointMode.polygon, points, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
123
packages/idraw/lib/p13/s02.dart
Normal file
123
packages/idraw/lib/p13/s02.dart
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'dart:ui'as ui;
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatelessWidget{
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
// 使用CustomPaint
|
||||||
|
painter: PaperPainter(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
|
||||||
|
final List<Offset> points = [];
|
||||||
|
|
||||||
|
final double step = 6;
|
||||||
|
final double min = -240;
|
||||||
|
final double max = 240;
|
||||||
|
|
||||||
|
void initPoints() {
|
||||||
|
for (double x = min; x < max; x += step) {
|
||||||
|
points.add(Offset(x, f(x)));
|
||||||
|
}
|
||||||
|
points.add(Offset(max, f(max)));
|
||||||
|
points.add(Offset(max, f(max)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void initPointsWithPolar() {
|
||||||
|
for (double x = min; x < max; x += step) {
|
||||||
|
double thta = (pi / 180 * x); // 角度转化为弧度
|
||||||
|
var p = f(thta);
|
||||||
|
points.add(Offset(p * cos(thta), p * sin(thta)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// double f(double x) {
|
||||||
|
// double y = -x * x / 200 + 100;
|
||||||
|
// return y;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// double f(double thta) {
|
||||||
|
// double p = 10 * thta;
|
||||||
|
// return p;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// double f(double thta) {
|
||||||
|
// double p = 100 * (1-cos(thta));
|
||||||
|
// return p;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// double f(double thta) {
|
||||||
|
// double p = 150*sin(5*thta).abs();
|
||||||
|
// return p;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
double f(double thta) { // 100*(1-4*sinθ)
|
||||||
|
double p = 50*(pow(e,cos(thta)) - 2 * cos(4 * thta) +pow(sin(thta / 12), 5));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
// initPoints();
|
||||||
|
initPointsWithPolar();
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.red
|
||||||
|
..strokeWidth = 1.5
|
||||||
|
..style = PaintingStyle.stroke;
|
||||||
|
var colors = [
|
||||||
|
Color(0xFFF60C0C),
|
||||||
|
Color(0xFFF3B913),
|
||||||
|
Color(0xFFE7F716),
|
||||||
|
Color(0xFF3DF30B),
|
||||||
|
Color(0xFF0DF6EF),
|
||||||
|
Color(0xFF0829FB),
|
||||||
|
Color(0xFFB709F4),
|
||||||
|
];
|
||||||
|
var pos = [1.0 / 7, 2.0 / 7, 3.0 / 7, 4.0 / 7, 5.0 / 7, 6.0 / 7, 1.0];
|
||||||
|
|
||||||
|
paint.shader = ui.Gradient.linear(
|
||||||
|
Offset(0, 0), Offset(100, 0), colors, pos,TileMode.mirror);
|
||||||
|
|
||||||
|
|
||||||
|
Offset p1 = points[0];
|
||||||
|
Path path = Path()..moveTo(p1.dx, p1.dy);
|
||||||
|
|
||||||
|
for (var i = 1; i < points.length-1; i++) {
|
||||||
|
double xc = (points[i].dx + points[i + 1].dx) / 2;
|
||||||
|
double yc = (points[i].dy + points[i + 1].dy) / 2;
|
||||||
|
Offset p2 = points[i];
|
||||||
|
path.quadraticBezierTo(p2.dx, p2.dy, xc, yc);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
|
||||||
|
// canvas.drawPoints(PointMode.points, points, paint..shader=null..strokeWidth=3);
|
||||||
|
// canvas.drawPoints(PointMode.polygon, points, paint..shader=null..strokeWidth=1..color=Colors.blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
130
packages/idraw/lib/p13/s03.dart
Normal file
130
packages/idraw/lib/p13/s03.dart
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatefulWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PaperState createState() => _PaperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaperState extends State<Paper> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(seconds: 15),
|
||||||
|
vsync: this,
|
||||||
|
)..repeat()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: PaperPainter(_controller),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
// final Coordinate coordinate = Coordinate();
|
||||||
|
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
PaperPainter(this.repaint) : super(repaint: repaint) {
|
||||||
|
initPointsWithPolar();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Offset> points = [];
|
||||||
|
final Path path = Path();
|
||||||
|
final double step = 4;
|
||||||
|
final double min = -240;
|
||||||
|
final double max = 240;
|
||||||
|
|
||||||
|
void initPointsWithPolar() {
|
||||||
|
for (double x = min; x < max; x += step) {
|
||||||
|
double thta = (pi / 180 * x); // 角度转化为弧度
|
||||||
|
var p = f(thta);
|
||||||
|
points.add(Offset(p * cos(thta), p * sin(thta)));
|
||||||
|
}
|
||||||
|
double thta = (pi / 180 * max);
|
||||||
|
points.add(Offset(f(thta) * cos(thta), f(thta) * sin(thta)));
|
||||||
|
points.add(Offset(f(thta) * cos(thta), f(thta) * sin(thta)));
|
||||||
|
}
|
||||||
|
|
||||||
|
double f(double thta) {
|
||||||
|
double p = 150*sin(5*thta).abs();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.red
|
||||||
|
..strokeWidth = 1.5
|
||||||
|
..style = PaintingStyle.stroke;
|
||||||
|
|
||||||
|
var colors = [
|
||||||
|
Color(0xFFF60C0C),
|
||||||
|
Color(0xFFF3B913),
|
||||||
|
Color(0xFFE7F716),
|
||||||
|
Color(0xFF3DF30B),
|
||||||
|
Color(0xFF0DF6EF),
|
||||||
|
Color(0xFF0829FB),
|
||||||
|
Color(0xFFB709F4),
|
||||||
|
];
|
||||||
|
var pos = [1.0 / 7, 2.0 / 7, 3.0 / 7, 4.0 / 7, 5.0 / 7, 6.0 / 7, 1.0];
|
||||||
|
|
||||||
|
paint.shader = ui.Gradient.linear(
|
||||||
|
Offset(0, 0), Offset(100, 0), colors, pos, TileMode.mirror);
|
||||||
|
|
||||||
|
Offset p1 = points[0];
|
||||||
|
|
||||||
|
|
||||||
|
path.reset();
|
||||||
|
path..moveTo(p1.dx, p1.dy);
|
||||||
|
|
||||||
|
for (var i = 1; i < points.length - 1; i++) {
|
||||||
|
double xc = (points[i].dx + points[i + 1].dx) / 2;
|
||||||
|
double yc = (points[i].dy + points[i + 1].dy) / 2;
|
||||||
|
Offset p2 = points[i];
|
||||||
|
path.quadraticBezierTo(p2.dx, p2.dy, xc, yc);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
|
||||||
|
PathMetrics pms = path.computeMetrics();
|
||||||
|
pms.forEach((pm) {
|
||||||
|
Tangent? tangent = pm.getTangentForOffset(pm.length * repaint.value);
|
||||||
|
if(tangent == null) return;
|
||||||
|
canvas.drawCircle(
|
||||||
|
tangent.position, 5, Paint()..color = Colors.blue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PaperPainter oldDelegate) =>
|
||||||
|
oldDelegate.repaint != repaint;
|
||||||
|
}
|
||||||
129
packages/idraw/lib/p13/s04.dart
Normal file
129
packages/idraw/lib/p13/s04.dart
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatefulWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PaperState createState() => _PaperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaperState extends State<Paper> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(seconds: 15),
|
||||||
|
vsync: this,
|
||||||
|
)..repeat()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: PaperPainter(_controller),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
PaperPainter(this.repaint) : super(repaint: repaint) {
|
||||||
|
initPointsWithPolar();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Offset> points = [];
|
||||||
|
final Path path = Path();
|
||||||
|
final double step = 4;
|
||||||
|
final double min = 0;
|
||||||
|
final double max = 360;
|
||||||
|
|
||||||
|
void initPointsWithPolar() {
|
||||||
|
for (double x = min; x < max; x += step) {
|
||||||
|
double thta = (pi / 180 * x); // 角度转化为弧度
|
||||||
|
var p = f(thta);
|
||||||
|
points.add(Offset(p * cos(thta), p * sin(thta)));
|
||||||
|
}
|
||||||
|
double thta = (pi / 180 * max);
|
||||||
|
points.add(Offset(f(thta) * cos(thta), f(thta) * sin(thta)));
|
||||||
|
points.add(Offset(f(thta) * cos(thta), f(thta) * sin(thta)));
|
||||||
|
}
|
||||||
|
|
||||||
|
double f(double thta) {
|
||||||
|
double p = 150*sin(5*thta).abs();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.red
|
||||||
|
..strokeWidth = 1.5
|
||||||
|
..style = PaintingStyle.stroke;
|
||||||
|
|
||||||
|
var colors = [
|
||||||
|
Color(0xFFF60C0C),
|
||||||
|
Color(0xFFF3B913),
|
||||||
|
Color(0xFFE7F716),
|
||||||
|
Color(0xFF3DF30B),
|
||||||
|
Color(0xFF0DF6EF),
|
||||||
|
Color(0xFF0829FB),
|
||||||
|
Color(0xFFB709F4),
|
||||||
|
];
|
||||||
|
var pos = [1.0 / 7, 2.0 / 7, 3.0 / 7, 4.0 / 7, 5.0 / 7, 6.0 / 7, 1.0];
|
||||||
|
|
||||||
|
paint.shader = ui.Gradient.linear(
|
||||||
|
Offset(0, 0), Offset(100, 0), colors, pos, TileMode.mirror);
|
||||||
|
|
||||||
|
Offset p1 = points[0];
|
||||||
|
|
||||||
|
|
||||||
|
path.reset();
|
||||||
|
path..moveTo(p1.dx, p1.dy);
|
||||||
|
|
||||||
|
for (var i = 1; i < points.length - 1; i++) {
|
||||||
|
double xc = (points[i].dx + points[i + 1].dx) / 2;
|
||||||
|
double yc = (points[i].dy + points[i + 1].dy) / 2;
|
||||||
|
Offset p2 = points[i];
|
||||||
|
path.quadraticBezierTo(p2.dx, p2.dy, xc, yc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PathMetrics pms = path.computeMetrics();
|
||||||
|
pms.forEach((pm) {
|
||||||
|
Tangent? tangent = pm.getTangentForOffset(pm.length * repaint.value);
|
||||||
|
if(tangent == null) return;
|
||||||
|
canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), paint);
|
||||||
|
canvas.drawCircle(
|
||||||
|
tangent.position, 5, Paint()..color = Colors.blue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PaperPainter oldDelegate) =>
|
||||||
|
oldDelegate.repaint != repaint;
|
||||||
|
}
|
||||||
1
packages/idraw/lib/p14/p14.dart
Normal file
1
packages/idraw/lib/p14/p14.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export 'p14_page.dart';
|
||||||
27
packages/idraw/lib/p14/p14_page.dart
Normal file
27
packages/idraw/lib/p14/p14_page.dart
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:components/components.dart';
|
||||||
|
import 's01.dart' as s1;
|
||||||
|
import 's02.dart' as s2;
|
||||||
|
import 's03.dart' as s3;
|
||||||
|
import 's04.dart' as s4;
|
||||||
|
import 's05.dart' as s5;
|
||||||
|
|
||||||
|
class P14Page extends StatelessWidget {
|
||||||
|
const P14Page({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const DemoShower(
|
||||||
|
srcCodeDir: 'draw/p14',
|
||||||
|
|
||||||
|
demos: [
|
||||||
|
s1.Paper(),
|
||||||
|
s2.Paper(),
|
||||||
|
s3.Paper(),
|
||||||
|
s4.Paper(),
|
||||||
|
s5.Paper(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
packages/idraw/lib/p14/s01.dart
Normal file
62
packages/idraw/lib/p14/s01.dart
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
// 使用CustomPaint
|
||||||
|
painter: PaperPainter(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
|
||||||
|
Offset p1 = Offset(100, 100);
|
||||||
|
Offset p2 = Offset(120, -60);
|
||||||
|
Paint _helpPaint = Paint();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.orange
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 2;
|
||||||
|
|
||||||
|
Path path = Path();
|
||||||
|
path.quadraticBezierTo(p1.dx, p1.dy, p2.dx, p2.dy);
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
_drawHelp(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawHelp(Canvas canvas) {
|
||||||
|
_helpPaint
|
||||||
|
..color = Colors.purple
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeCap = StrokeCap.round;
|
||||||
|
canvas.drawPoints(PointMode.lines,[Offset.zero, p1, p1,p2], _helpPaint..strokeWidth=1);
|
||||||
|
canvas.drawPoints(PointMode.points, [Offset.zero, p1, p1, p2],
|
||||||
|
_helpPaint..strokeWidth = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
131
packages/idraw/lib/p14/s02.dart
Normal file
131
packages/idraw/lib/p14/s02.dart
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
import 'touch_info.dart';
|
||||||
|
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatefulWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PaperState createState() => _PaperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaperState extends State<Paper> {
|
||||||
|
final TouchInfo touchInfo = TouchInfo();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
touchInfo.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onPanDown: _onPanDown,
|
||||||
|
onPanUpdate: _onPanUpdate,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: PaperPainter(repaint: touchInfo),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPanDown(DragDownDetails details) {
|
||||||
|
if (touchInfo.points.length < 3) {
|
||||||
|
touchInfo.addPoint(details.localPosition);
|
||||||
|
}else{
|
||||||
|
judgeZone(details.localPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _onPanUpdate(DragUpdateDetails details) {
|
||||||
|
judgeZone(details.localPosition,update: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
///判断出是否在某点的半径为r圆范围内
|
||||||
|
bool judgeCircleArea(Offset src, Offset dst, double r) =>
|
||||||
|
(src - dst).distance <= r;
|
||||||
|
|
||||||
|
//判断哪个点被选中
|
||||||
|
void judgeZone(Offset src,{bool update =false}) {
|
||||||
|
for (int i = 0; i < touchInfo.points.length; i++) {
|
||||||
|
if (judgeCircleArea(src, touchInfo.points[i], 15)) {
|
||||||
|
touchInfo.selectIndex = i;
|
||||||
|
if(update){
|
||||||
|
touchInfo.updatePoint(i, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
|
||||||
|
Paint _helpPaint = Paint()
|
||||||
|
..color = Colors.purple
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeCap = StrokeCap.round;
|
||||||
|
|
||||||
|
final TouchInfo repaint;
|
||||||
|
|
||||||
|
PaperPainter({ required this.repaint}) : super(repaint: repaint);
|
||||||
|
List<Offset> pos = [];
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
pos = repaint.points
|
||||||
|
.map((e) => e.translate(-size.width / 2, -size.height / 2))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
Path path = Path();
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.orange
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 2;
|
||||||
|
if (pos.length < 3) {
|
||||||
|
canvas.drawPoints(PointMode.points, pos, _helpPaint..strokeWidth = 8);
|
||||||
|
} else {
|
||||||
|
path.moveTo(pos[0].dx, pos[0].dy);
|
||||||
|
path.quadraticBezierTo(pos[1].dx, pos[1].dy, pos[2].dx, pos[2].dy);
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
_drawHelp(canvas);
|
||||||
|
_drawSelectPos(canvas,size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawHelp(Canvas canvas) {
|
||||||
|
_helpPaint..color = Colors.purple;
|
||||||
|
canvas.drawPoints(PointMode.polygon, pos, _helpPaint..strokeWidth = 1);
|
||||||
|
canvas.drawPoints(PointMode.points, pos, _helpPaint..strokeWidth = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawSelectPos(Canvas canvas,Size size) {
|
||||||
|
Offset? selectPos = repaint.selectPoint;
|
||||||
|
if (selectPos == null) return;
|
||||||
|
selectPos = selectPos.translate(-size.width / 2, -size.height / 2);
|
||||||
|
canvas.drawCircle(
|
||||||
|
selectPos,
|
||||||
|
10,
|
||||||
|
_helpPaint
|
||||||
|
..color = Colors.green
|
||||||
|
..strokeWidth = 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PaperPainter oldDelegate) =>
|
||||||
|
oldDelegate.repaint != repaint;
|
||||||
|
}
|
||||||
127
packages/idraw/lib/p14/s03.dart
Normal file
127
packages/idraw/lib/p14/s03.dart
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
import 'touch_info.dart';
|
||||||
|
|
||||||
|
class Paper extends StatefulWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PaperState createState() => _PaperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaperState extends State<Paper> {
|
||||||
|
final TouchInfo touchInfo = TouchInfo();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
touchInfo.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onPanDown: _onPanDown,
|
||||||
|
onPanUpdate: _onPanUpdate,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: PaperPainter(repaint: touchInfo),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPanDown(DragDownDetails details) {
|
||||||
|
if (touchInfo.points.length < 4) {
|
||||||
|
touchInfo.addPoint(details.localPosition);
|
||||||
|
}else{
|
||||||
|
judgeZone(details.localPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _onPanUpdate(DragUpdateDetails details) {
|
||||||
|
judgeZone(details.localPosition,update: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
///判断出是否在某点的半径为r圆范围内
|
||||||
|
bool judgeCircleArea(Offset src, Offset dst, double r) =>
|
||||||
|
(src - dst).distance <= r;
|
||||||
|
|
||||||
|
//判断哪个点被选中
|
||||||
|
void judgeZone(Offset src,{bool update =false}) {
|
||||||
|
for (int i = 0; i < touchInfo.points.length; i++) {
|
||||||
|
if (judgeCircleArea(src, touchInfo.points[i], 15)) {
|
||||||
|
touchInfo.selectIndex = i;
|
||||||
|
if(update){
|
||||||
|
touchInfo.updatePoint(i, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
|
||||||
|
Paint _helpPaint = Paint()
|
||||||
|
..color = Colors.purple
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeCap = StrokeCap.round;
|
||||||
|
|
||||||
|
final TouchInfo repaint;
|
||||||
|
|
||||||
|
PaperPainter({required this.repaint}) : super(repaint: repaint);
|
||||||
|
List<Offset> pos = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
pos = repaint.points
|
||||||
|
.map((e) => e.translate(-size.width / 2, -size.height / 2))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
Path path = Path();
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.orange
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 2;
|
||||||
|
if (pos.length < 4) {
|
||||||
|
canvas.drawPoints(PointMode.points, pos, _helpPaint..strokeWidth = 8);
|
||||||
|
} else {
|
||||||
|
path.moveTo(pos[0].dx, pos[0].dy);
|
||||||
|
path.cubicTo(pos[1].dx, pos[1].dy, pos[2].dx, pos[2].dy, pos[3].dx, pos[3].dy);
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
_drawHelp(canvas);
|
||||||
|
_drawSelectPos(canvas,size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawHelp(Canvas canvas) {
|
||||||
|
_helpPaint..color = Colors.purple;
|
||||||
|
canvas.drawPoints(PointMode.polygon, pos, _helpPaint..strokeWidth = 1);
|
||||||
|
canvas.drawPoints(PointMode.points, pos, _helpPaint..strokeWidth = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawSelectPos(Canvas canvas,Size size) {
|
||||||
|
Offset? selectPos = repaint.selectPoint;
|
||||||
|
if (selectPos == null) return;
|
||||||
|
selectPos = selectPos.translate(-size.width / 2, -size.height / 2);
|
||||||
|
canvas.drawCircle(
|
||||||
|
selectPos,
|
||||||
|
10,
|
||||||
|
_helpPaint
|
||||||
|
..color = Colors.green
|
||||||
|
..strokeWidth = 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PaperPainter oldDelegate) =>
|
||||||
|
oldDelegate.repaint != repaint;
|
||||||
|
}
|
||||||
170
packages/idraw/lib/p14/s04.dart
Normal file
170
packages/idraw/lib/p14/s04.dart
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
import 'touch_info.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatefulWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PaperState createState() => _PaperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaperState extends State<Paper> {
|
||||||
|
final TouchInfo touchInfo = TouchInfo();
|
||||||
|
|
||||||
|
//单位圆(即半径为1)控制线长
|
||||||
|
final rate = 0.551915024494;
|
||||||
|
double _radius = 150;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
touchInfo.setPoints(_initPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
touchInfo.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Offset> _initPoints() {
|
||||||
|
final List<Offset> pos = [];
|
||||||
|
//第一段线
|
||||||
|
pos.add(Offset(0, rate) * _radius);
|
||||||
|
pos.add(Offset(1 - rate, 1) * _radius);
|
||||||
|
pos.add(Offset(1, 1) * _radius);
|
||||||
|
//第二段线
|
||||||
|
pos.add(Offset(1 + rate, 1) * _radius);
|
||||||
|
pos.add(Offset(2, rate) * _radius);
|
||||||
|
pos.add(Offset(2, 0) * _radius);
|
||||||
|
//第三段线
|
||||||
|
pos.add(Offset(2, -rate) * _radius);
|
||||||
|
pos.add(Offset(1 + rate, -1) * _radius);
|
||||||
|
pos.add(Offset(1, -1) * _radius);
|
||||||
|
//第四段线
|
||||||
|
pos.add(Offset(1 - rate, -1) * _radius);
|
||||||
|
pos.add(Offset(0, -rate) * _radius);
|
||||||
|
pos.add(Offset(0, 0));
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder:(_,cts)=> GestureDetector(
|
||||||
|
onPanDown: (details)=>_onPanDown(details,cts.biggest),
|
||||||
|
onPanUpdate: (details)=>_onPanUpdate(details,cts.biggest),
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: PaperPainter(repaint: touchInfo),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPanDown(DragDownDetails details,Size size) {
|
||||||
|
print("=====${details}===========${touchInfo.points.length}}");
|
||||||
|
if (touchInfo.points.length < 4) {
|
||||||
|
touchInfo.addPoint(details.localPosition);
|
||||||
|
} else {
|
||||||
|
judgeZone(details.localPosition,size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPanUpdate(DragUpdateDetails details,Size size) {
|
||||||
|
judgeZone(details.localPosition,size, update: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
///判断出是否在某点的半径为r圆范围内
|
||||||
|
bool judgeCircleArea(Offset src, Offset dst, double r) =>
|
||||||
|
(src - dst).distance <= r;
|
||||||
|
|
||||||
|
//判断哪个点被选中
|
||||||
|
void judgeZone(Offset src, Size size,{bool update = false}) {
|
||||||
|
src= src.translate(-size.width/2, -size.height/2);
|
||||||
|
for (int i = 0; i < touchInfo.points.length; i++) {
|
||||||
|
if (judgeCircleArea(src, touchInfo.points[i], 15)) {
|
||||||
|
touchInfo.selectIndex = i;
|
||||||
|
if (update) {
|
||||||
|
touchInfo.updatePoint(i, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
|
||||||
|
Paint _helpPaint = Paint()
|
||||||
|
..color = Colors.purple
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeCap = StrokeCap.round;
|
||||||
|
|
||||||
|
final TouchInfo repaint;
|
||||||
|
|
||||||
|
PaperPainter({required this.repaint}) : super(repaint: repaint);
|
||||||
|
List<Offset> pos = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
pos = repaint.points;
|
||||||
|
|
||||||
|
Path path = Path();
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.orange
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 2;
|
||||||
|
path.moveTo(0, 0);
|
||||||
|
for (int i = 0; i < pos.length / 3; i++) {
|
||||||
|
path.cubicTo(pos[3 * i + 0].dx, pos[3 * i + 0].dy, pos[3 * i + 1].dx,
|
||||||
|
pos[3 * i + 1].dy, pos[3 * i + 2].dx, pos[3 * i + 2].dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
_drawHelp(canvas);
|
||||||
|
_drawSelectPos(canvas, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawHelp(Canvas canvas) {
|
||||||
|
|
||||||
|
_helpPaint..strokeWidth = 1..color=Colors.purple;
|
||||||
|
canvas.drawLine(pos[0], pos[11], _helpPaint);
|
||||||
|
canvas.drawLine(pos[1], pos[2], _helpPaint);
|
||||||
|
canvas.drawLine(pos[2], pos[3], _helpPaint);
|
||||||
|
canvas.drawLine(pos[4], pos[5], _helpPaint);
|
||||||
|
canvas.drawLine(pos[5], pos[6], _helpPaint);
|
||||||
|
canvas.drawLine(pos[7], pos[8], _helpPaint);
|
||||||
|
canvas.drawLine(pos[8], pos[9], _helpPaint);
|
||||||
|
canvas.drawLine(pos[10], pos[11], _helpPaint);
|
||||||
|
canvas.drawLine(pos[11], pos[0], _helpPaint);
|
||||||
|
canvas.drawPoints(PointMode.points, pos, _helpPaint..strokeWidth = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawSelectPos(Canvas canvas, Size size) {
|
||||||
|
Offset? selectPos = repaint.selectPoint;
|
||||||
|
if (selectPos == null) return;
|
||||||
|
|
||||||
|
canvas.drawCircle(selectPos, 10,
|
||||||
|
_helpPaint..color = Colors.green..strokeWidth = 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PaperPainter oldDelegate) =>
|
||||||
|
oldDelegate.repaint != repaint;
|
||||||
|
}
|
||||||
132
packages/idraw/lib/p14/s05.dart
Normal file
132
packages/idraw/lib/p14/s05.dart
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
// 使用CustomPaint
|
||||||
|
painter: PaperPainter(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
|
||||||
|
|
||||||
|
List<Offset> points1 = [
|
||||||
|
Offset(0, 20),
|
||||||
|
Offset(40, 40) ,
|
||||||
|
Offset(80, -20),
|
||||||
|
Offset(120, -40),
|
||||||
|
Offset(160, -80),
|
||||||
|
Offset(200, -20),
|
||||||
|
Offset(240, -40),
|
||||||
|
];
|
||||||
|
List<Offset> points2 = [
|
||||||
|
Offset(0, 0),
|
||||||
|
Offset(40, -20) ,
|
||||||
|
Offset(80, -40),
|
||||||
|
Offset(120, -80),
|
||||||
|
Offset(160, -40),
|
||||||
|
Offset(200, 20),
|
||||||
|
Offset(240, 40),
|
||||||
|
];
|
||||||
|
List<Offset> helpPoints = [
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
Paint _helpPaint = Paint();
|
||||||
|
|
||||||
|
Path _linePath = Path();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.red
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1;
|
||||||
|
|
||||||
|
Path path = Path();
|
||||||
|
addBezierPathWithPoints(path, points2);
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
|
||||||
|
addBezierPathWithPoints(_linePath, points1);
|
||||||
|
canvas.drawPath(_linePath, paint..color=Colors.orange);
|
||||||
|
|
||||||
|
_drawHelp(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addBezierPathWithPoints(Path path, List<Offset> points) {
|
||||||
|
for (int i = 0; i < points.length - 1; i++) {
|
||||||
|
Offset current = points[i];
|
||||||
|
Offset next = points[i+1];
|
||||||
|
if (i == 0) {
|
||||||
|
path.moveTo(current.dx, current.dy);
|
||||||
|
// 控制点
|
||||||
|
double ctrlX = current.dx + (next.dx - current.dx) / 2;
|
||||||
|
double ctrlY = next.dy;
|
||||||
|
path.quadraticBezierTo(ctrlX, ctrlY, next.dx, next.dy);
|
||||||
|
} else if (i < points.length - 2) {
|
||||||
|
// 控制点 1
|
||||||
|
double ctrl1X = current.dx + (next.dx - current.dx) / 2;
|
||||||
|
double ctrl1Y = current.dy;
|
||||||
|
// 控制点 2
|
||||||
|
double ctrl2X = ctrl1X;
|
||||||
|
double ctrl2Y = next.dy;
|
||||||
|
path.cubicTo(ctrl1X,ctrl1Y,ctrl2X,ctrl2Y,next.dx,next.dy);
|
||||||
|
}else{
|
||||||
|
// 控制点
|
||||||
|
double ctrlX = (next.dx - current.dx) / 2;
|
||||||
|
double ctrlY = 0;
|
||||||
|
path.relativeQuadraticBezierTo(ctrlX, ctrlY, next.dx-current.dx, next.dy-current.dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawHelp(Canvas canvas) {
|
||||||
|
|
||||||
|
_helpPaint
|
||||||
|
..style = PaintingStyle.stroke;
|
||||||
|
points1.forEach((element) {
|
||||||
|
canvas.drawCircle(element, 2, _helpPaint..strokeWidth=1..color=Colors.orange);
|
||||||
|
});
|
||||||
|
|
||||||
|
points2.forEach((element) {
|
||||||
|
canvas.drawCircle(element, 2, _helpPaint..strokeWidth=1..color=Colors.red);
|
||||||
|
});
|
||||||
|
|
||||||
|
// canvas.drawPoints(PointMode.polygon, points1, _helpPaint..strokeWidth=0.5..color=Colors.red);// _drawHelp(canvas);
|
||||||
|
// canvas.drawPoints(PointMode.polygon, points2, _helpPaint..strokeWidth=0.5..color=Colors.red);// _drawHelp(canvas);
|
||||||
|
// canvas.drawPoints(PointMode.polygon, helpPoints, _helpPaint..strokeWidth=0.5..color=Colors.red);// _drawHelp(canvas);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// _helpPaint
|
||||||
|
// ..color = Colors.purple
|
||||||
|
// ..style = PaintingStyle.stroke
|
||||||
|
// ..strokeCap = StrokeCap.round;
|
||||||
|
// canvas.drawPoints(PointMode.lines, [Offset.zero, p1, p1, p2],
|
||||||
|
// _helpPaint..strokeWidth = 1);
|
||||||
|
// canvas.drawPoints(PointMode.points, [Offset.zero, p1, p1, p2],
|
||||||
|
// _helpPaint..strokeWidth = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
45
packages/idraw/lib/p14/touch_info.dart
Normal file
45
packages/idraw/lib/p14/touch_info.dart
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/11/4
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class TouchInfo extends ChangeNotifier {
|
||||||
|
List<Offset> _points = [];
|
||||||
|
int _selectIndex = -1;
|
||||||
|
|
||||||
|
void setPoints(List<Offset> points) {
|
||||||
|
_points = points;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int get selectIndex => _selectIndex;
|
||||||
|
|
||||||
|
List<Offset> get points => _points;
|
||||||
|
|
||||||
|
set selectIndex(int value) {
|
||||||
|
assert(value != null);
|
||||||
|
if (_selectIndex == value) return;
|
||||||
|
|
||||||
|
_selectIndex = value;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPoint(Offset point) {
|
||||||
|
points.add(point);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updatePoint(int index, Offset point) {
|
||||||
|
points[index] = point;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
_points.clear();
|
||||||
|
_selectIndex = -1;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset? get selectPoint => _selectIndex == -1 ? null : _points[_selectIndex];
|
||||||
|
}
|
||||||
1
packages/idraw/lib/p15/p15.dart
Normal file
1
packages/idraw/lib/p15/p15.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export 'p15_page.dart';
|
||||||
29
packages/idraw/lib/p15/p15_page.dart
Normal file
29
packages/idraw/lib/p15/p15_page.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:components/components.dart';
|
||||||
|
import 's01.dart' as s1;
|
||||||
|
import 's02.dart' as s2;
|
||||||
|
import 's03.dart' as s3;
|
||||||
|
import 's04.dart' as s4;
|
||||||
|
import 's05.dart' as s5;
|
||||||
|
import 's06.dart' as s6;
|
||||||
|
|
||||||
|
class P15Page extends StatelessWidget {
|
||||||
|
const P15Page({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const DemoShower(
|
||||||
|
srcCodeDir: 'draw/p15',
|
||||||
|
|
||||||
|
demos: [
|
||||||
|
s1.Paper(),
|
||||||
|
s2.Paper(),
|
||||||
|
s3.Paper(),
|
||||||
|
s4.Paper(),
|
||||||
|
s5.Paper(),
|
||||||
|
s6.Paper(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
68
packages/idraw/lib/p15/s01.dart
Normal file
68
packages/idraw/lib/p15/s01.dart
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
// 使用CustomPaint
|
||||||
|
painter: PaperPainter(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
Paint _helpPaint = Paint();
|
||||||
|
|
||||||
|
double waveWidth = 80;
|
||||||
|
double wrapHeight=0;
|
||||||
|
|
||||||
|
double waveHeight = 40;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
Path path = Path();
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.orange
|
||||||
|
..style = PaintingStyle.fill
|
||||||
|
..strokeWidth = 2;
|
||||||
|
|
||||||
|
path.relativeQuadraticBezierTo( waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo( waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo( waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo( waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
_drawHelp(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawHelp(Canvas canvas) {
|
||||||
|
_helpPaint
|
||||||
|
..color = Colors.purple
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeCap = StrokeCap.round;
|
||||||
|
canvas.drawPoints(PointMode.polygon,[Offset.zero, Offset(waveWidth / 2, -waveHeight * 2), Offset(waveWidth , 0)], _helpPaint..strokeWidth=1);
|
||||||
|
canvas.drawPoints(PointMode.points, [Offset.zero, Offset(waveWidth / 2, -waveHeight * 2), Offset(waveWidth , 0)],
|
||||||
|
_helpPaint..strokeWidth = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
69
packages/idraw/lib/p15/s02.dart
Normal file
69
packages/idraw/lib/p15/s02.dart
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
// 使用CustomPaint
|
||||||
|
painter: PaperPainter(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
Paint _helpPaint = Paint();
|
||||||
|
|
||||||
|
double waveWidth = 80;
|
||||||
|
double wrapHeight =100;
|
||||||
|
double waveHeight = 40;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
Path path = Path();
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.orange
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 2;
|
||||||
|
|
||||||
|
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(-2*waveWidth, 0);
|
||||||
|
path.moveTo(0, 0);
|
||||||
|
path.relativeQuadraticBezierTo(waveWidth/2, -waveHeight*2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(waveWidth/2, waveHeight*2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(waveWidth/2, -waveHeight*2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(waveWidth/2, waveHeight*2, waveWidth, 0);
|
||||||
|
path.close();
|
||||||
|
canvas.drawPath(path, paint..style=PaintingStyle.fill);
|
||||||
|
canvas.restore();
|
||||||
|
|
||||||
|
_drawHelp(canvas);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawHelp(Canvas canvas) {
|
||||||
|
_helpPaint
|
||||||
|
..color = Colors.purple
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeCap = StrokeCap.round;
|
||||||
|
canvas.drawRect(Rect.fromPoints(Offset(0,-100), Offset(160,100)), _helpPaint..strokeWidth=2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
96
packages/idraw/lib/p15/s03.dart
Normal file
96
packages/idraw/lib/p15/s03.dart
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
|
||||||
|
class Paper extends StatefulWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PaperState createState() => _PaperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaperState extends State<Paper> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 500),
|
||||||
|
vsync: this,
|
||||||
|
)..repeat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: PaperPainter(_controller),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
Paint _helpPaint = Paint();
|
||||||
|
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
PaperPainter(this.repaint) : super(repaint: repaint);
|
||||||
|
|
||||||
|
double waveWidth = 80;
|
||||||
|
double wrapHeight = 100;
|
||||||
|
double waveHeight = 20;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
Path path = Path();
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.orange
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 2;
|
||||||
|
|
||||||
|
canvas.save();
|
||||||
|
// canvas.translate(-2*waveWidth, 0);
|
||||||
|
canvas.translate(-2 * waveWidth + 2 * waveWidth * repaint.value, 0);
|
||||||
|
path.moveTo(0, 0);
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeLineTo(0, wrapHeight);
|
||||||
|
path.relativeLineTo(-waveWidth * 2 * 2.0, 0);
|
||||||
|
path.close();
|
||||||
|
canvas.drawPath(path, paint..style = PaintingStyle.fill);
|
||||||
|
canvas.restore();
|
||||||
|
|
||||||
|
_drawHelp(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawHelp(Canvas canvas) {
|
||||||
|
_helpPaint
|
||||||
|
..color = Colors.purple
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeCap = StrokeCap.round;
|
||||||
|
canvas.drawRect(Rect.fromPoints(Offset(0, -100), Offset(160, 100)),
|
||||||
|
_helpPaint..strokeWidth = 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PaperPainter oldDelegate) =>
|
||||||
|
oldDelegate.repaint != repaint;
|
||||||
|
}
|
||||||
106
packages/idraw/lib/p15/s04.dart
Normal file
106
packages/idraw/lib/p15/s04.dart
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
import 'touch_info.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatefulWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PaperState createState() => _PaperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaperState extends State<Paper> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 500),
|
||||||
|
vsync: this,
|
||||||
|
)..repeat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: PaperPainter(CurveTween(curve: Curves.easeInOutQuad).animate(_controller)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Coordinate coordinate = Coordinate();
|
||||||
|
Paint _helpPaint = Paint();
|
||||||
|
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
PaperPainter(this.repaint) : super(repaint: repaint);
|
||||||
|
|
||||||
|
double waveWidth = 80;
|
||||||
|
double wrapHeight = 100;
|
||||||
|
double waveHeight = 20;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
coordinate.paint(canvas, size);
|
||||||
|
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
canvas.clipRect((Rect.fromCenter(
|
||||||
|
center: Offset( waveWidth, 0),width: waveWidth*2,height: 200.0)));
|
||||||
|
Path path = Path();
|
||||||
|
Paint paint = Paint()
|
||||||
|
..color = Colors.orange
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 2;
|
||||||
|
|
||||||
|
canvas.save();
|
||||||
|
// canvas.translate(-2*waveWidth, 0);
|
||||||
|
canvas.translate(-2 * waveWidth + 2 * waveWidth * repaint.value, 0);
|
||||||
|
path.moveTo(0, 0);
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeLineTo(0, wrapHeight);
|
||||||
|
path.relativeLineTo(-waveWidth * 2 * 2.0, 0);
|
||||||
|
path.close();
|
||||||
|
canvas.drawPath(path, paint..style = PaintingStyle.fill);
|
||||||
|
canvas.restore();
|
||||||
|
|
||||||
|
_drawHelp(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawHelp(Canvas canvas) {
|
||||||
|
_helpPaint
|
||||||
|
..color = Colors.purple
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeCap = StrokeCap.round;
|
||||||
|
canvas.drawRect(Rect.fromPoints(Offset(0, -100), Offset(160, 100)),
|
||||||
|
_helpPaint..strokeWidth = 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PaperPainter oldDelegate) =>
|
||||||
|
oldDelegate.repaint != repaint;
|
||||||
|
}
|
||||||
97
packages/idraw/lib/p15/s05.dart
Normal file
97
packages/idraw/lib/p15/s05.dart
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatefulWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PaperState createState() => _PaperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaperState extends State<Paper> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
vsync: this,
|
||||||
|
)
|
||||||
|
..repeat()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: PaperPainter(
|
||||||
|
CurveTween(curve: Curves.linear).animate(_controller)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
PaperPainter(this.repaint) : super(repaint: repaint);
|
||||||
|
|
||||||
|
double waveWidth = 80;
|
||||||
|
double wrapHeight = 100;
|
||||||
|
double waveHeight = 10;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
canvas.clipRect((Rect.fromCenter(
|
||||||
|
center: Offset(waveWidth, 0), width: waveWidth * 2, height: 200.0)));
|
||||||
|
|
||||||
|
Paint paint = Paint();
|
||||||
|
|
||||||
|
Path path = getWavePath();
|
||||||
|
canvas.translate(-4 * waveWidth + 2 * waveWidth * repaint.value, 0);
|
||||||
|
canvas.drawPath(path, paint..color = Colors.orange);
|
||||||
|
|
||||||
|
canvas.translate(2*waveWidth* repaint.value, 0);
|
||||||
|
canvas.drawPath(path, paint..color = Colors.orange.withAlpha(88));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Path getWavePath() {
|
||||||
|
Path path = Path();
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeQuadraticBezierTo(
|
||||||
|
waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
path.relativeLineTo(0, wrapHeight);
|
||||||
|
path.relativeLineTo(-waveWidth * 3 * 2.0, 0);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PaperPainter oldDelegate) =>
|
||||||
|
oldDelegate.repaint != repaint;
|
||||||
|
}
|
||||||
192
packages/idraw/lib/p15/s06.dart
Normal file
192
packages/idraw/lib/p15/s06.dart
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../components/coordinate_pro.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/5/1
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(child: Wrap(
|
||||||
|
spacing: 30,
|
||||||
|
runSpacing: 30,
|
||||||
|
children: List.generate(12, (v) => 0.1 * v+0.1)
|
||||||
|
.map((e) => TolyWaveLoading(
|
||||||
|
isOval: (e*10).toInt().isEven, // 是否椭圆裁切
|
||||||
|
progress: 0.5, // 进度
|
||||||
|
waveHeight: 3, //波浪高
|
||||||
|
color: [Colors.blue,Colors.red,Colors.green][(e*10).toInt()%3], //颜色
|
||||||
|
)).toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TolyWaveLoading extends StatefulWidget {
|
||||||
|
// 波高
|
||||||
|
final double waveHeight;
|
||||||
|
|
||||||
|
// 进度
|
||||||
|
final double progress;
|
||||||
|
|
||||||
|
// 颜色
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
// 尺寸
|
||||||
|
final Size size;
|
||||||
|
|
||||||
|
// 底波透明度
|
||||||
|
final int secondAlpha;
|
||||||
|
|
||||||
|
// 边线宽
|
||||||
|
final double strokeWidth;
|
||||||
|
|
||||||
|
// 圆角半径
|
||||||
|
final double borderRadius;
|
||||||
|
|
||||||
|
// 是否是椭圆
|
||||||
|
final bool isOval;
|
||||||
|
final Duration duration;
|
||||||
|
|
||||||
|
final Curve curve;
|
||||||
|
|
||||||
|
const TolyWaveLoading(
|
||||||
|
{Key? key,
|
||||||
|
this.waveHeight = 5,
|
||||||
|
this.progress = 0.5,
|
||||||
|
this.duration = const Duration(seconds: 1),
|
||||||
|
this.size = const Size(100, 100),
|
||||||
|
this.color = Colors.green,
|
||||||
|
this.secondAlpha = 88,
|
||||||
|
this.strokeWidth = 3,
|
||||||
|
this.curve = Curves.linear,
|
||||||
|
this.borderRadius = 20,
|
||||||
|
this.isOval = false})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_TolyWaveLoadingState createState() => _TolyWaveLoadingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TolyWaveLoadingState extends State<TolyWaveLoading>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: widget.duration,
|
||||||
|
vsync: this,
|
||||||
|
)..repeat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CustomPaint(
|
||||||
|
size: widget.size,
|
||||||
|
painter: PaperPainter(
|
||||||
|
waveHeight: widget.waveHeight,
|
||||||
|
secondAlpha: widget.secondAlpha,
|
||||||
|
color: widget.color,
|
||||||
|
borderRadius: widget.borderRadius,
|
||||||
|
isOval: widget.isOval,
|
||||||
|
progress: widget.progress,
|
||||||
|
strokeWidth: widget.strokeWidth,
|
||||||
|
repaint: CurveTween(curve: widget.curve).animate(_controller)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaperPainter extends CustomPainter {
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
PaperPainter({
|
||||||
|
required this.repaint,
|
||||||
|
required this.waveHeight,
|
||||||
|
required this.color,
|
||||||
|
required this.progress,
|
||||||
|
required this.secondAlpha,
|
||||||
|
required this.borderRadius,
|
||||||
|
required this.isOval,
|
||||||
|
required this.strokeWidth,
|
||||||
|
}) : super(repaint: repaint);
|
||||||
|
|
||||||
|
final double waveHeight;
|
||||||
|
final double progress;
|
||||||
|
final Color color;
|
||||||
|
final double strokeWidth;
|
||||||
|
final int secondAlpha;
|
||||||
|
final double borderRadius;
|
||||||
|
final bool isOval;
|
||||||
|
Path path = Path();
|
||||||
|
Paint _mainPaint = Paint();
|
||||||
|
Path _mainPath = Path();
|
||||||
|
double waveWidth = 0;
|
||||||
|
double wrapHeight = 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
// 由于 使用 repaint 触发更新 path 和 _mainPath 不会重新创建
|
||||||
|
// 而导致刷新时不断为 path 和 _mainPath 添加路径,导致路径非常庞大,越来越卡,而掉帧
|
||||||
|
// 处理方案一: 绘制前 重置 path 或者
|
||||||
|
// 处理方案二: 不将 path 设为成员变量,每次绘制都新建 Path 对象,这样会造成大量 Path 对象创建,测试发现两种方案结果差不多。
|
||||||
|
path.reset();
|
||||||
|
_mainPath.reset();
|
||||||
|
|
||||||
|
waveWidth = size.width / 2;
|
||||||
|
wrapHeight = size.height;
|
||||||
|
|
||||||
|
_mainPaint..strokeWidth = strokeWidth..style = PaintingStyle.stroke..color = color;
|
||||||
|
|
||||||
|
if (!isOval) {
|
||||||
|
path.addRRect(RRect.fromRectXY(Offset(0, 0) & size, borderRadius, borderRadius));
|
||||||
|
canvas.clipPath(path);
|
||||||
|
canvas.drawPath(path,_mainPaint);
|
||||||
|
}
|
||||||
|
if (isOval) {
|
||||||
|
path.addOval(Offset(0, 0) & size);
|
||||||
|
canvas.clipPath(path);
|
||||||
|
canvas.drawPath(path, _mainPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.translate(-4 * waveWidth + 2 * waveWidth * repaint.value, wrapHeight + waveHeight);
|
||||||
|
drawWave(canvas);
|
||||||
|
canvas.drawPath(_mainPath, _mainPaint..style = PaintingStyle.fill..color = color);
|
||||||
|
|
||||||
|
canvas.translate(2 * waveWidth * repaint.value, 0);
|
||||||
|
drawWave(canvas);
|
||||||
|
canvas.drawPath(_mainPath, _mainPaint..color = color.withAlpha(88));
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawWave(Canvas canvas) {
|
||||||
|
_mainPath.moveTo(0, 0);
|
||||||
|
_mainPath.relativeLineTo(0, -wrapHeight * progress);
|
||||||
|
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, -waveHeight * 2, waveWidth, 0);
|
||||||
|
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
|
||||||
|
_mainPath.relativeLineTo(0, wrapHeight);
|
||||||
|
_mainPath.relativeLineTo(-waveWidth * 3 * 2.0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PaperPainter oldDelegate) =>
|
||||||
|
oldDelegate.repaint != repaint|| oldDelegate.waveHeight != waveHeight||
|
||||||
|
oldDelegate.progress != progress|| oldDelegate.color != color||
|
||||||
|
oldDelegate.strokeWidth != strokeWidth|| oldDelegate.isOval != isOval||
|
||||||
|
oldDelegate.secondAlpha != secondAlpha|| oldDelegate.borderRadius != borderRadius;
|
||||||
|
}
|
||||||
|
|
||||||
45
packages/idraw/lib/p15/touch_info.dart
Normal file
45
packages/idraw/lib/p15/touch_info.dart
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/11/4
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class TouchInfo extends ChangeNotifier {
|
||||||
|
List<Offset> _points = [];
|
||||||
|
int _selectIndex = -1;
|
||||||
|
|
||||||
|
void setPoints(List<Offset> points) {
|
||||||
|
_points = points;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int get selectIndex => _selectIndex;
|
||||||
|
|
||||||
|
List<Offset> get points => _points;
|
||||||
|
|
||||||
|
set selectIndex(int value) {
|
||||||
|
assert(value != null);
|
||||||
|
if (_selectIndex == value) return;
|
||||||
|
|
||||||
|
_selectIndex = value;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPoint(Offset point) {
|
||||||
|
points.add(point);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updatePoint(int index, Offset point) {
|
||||||
|
points[index] = point;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
_points.clear();
|
||||||
|
_selectIndex = -1;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset? get selectPoint => _selectIndex == -1 ? null : _points[_selectIndex];
|
||||||
|
}
|
||||||
1
packages/idraw/lib/p16/p16.dart
Normal file
1
packages/idraw/lib/p16/p16.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export 'p16_page.dart';
|
||||||
29
packages/idraw/lib/p16/p16_page.dart
Normal file
29
packages/idraw/lib/p16/p16_page.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:components/components.dart';
|
||||||
|
import 's01.dart' as s1;
|
||||||
|
import 's02.dart' as s2;
|
||||||
|
import 's03.dart' as s3;
|
||||||
|
import 's04.dart' as s4;
|
||||||
|
import 's05.dart' as s5;
|
||||||
|
import 's06.dart' as s6;
|
||||||
|
|
||||||
|
class P16Page extends StatelessWidget {
|
||||||
|
const P16Page({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const DemoShower(
|
||||||
|
srcCodeDir: 'draw/p16',
|
||||||
|
|
||||||
|
demos: [
|
||||||
|
s1.Paper(),
|
||||||
|
s2.Paper(),
|
||||||
|
s3.Paper(),
|
||||||
|
s4.Paper(),
|
||||||
|
s5.Paper(),
|
||||||
|
s6.Paper(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
172
packages/idraw/lib/p16/s01.dart
Normal file
172
packages/idraw/lib/p16/s01.dart
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
// import 'dart:ui' as ui;
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/11/5
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: const ICharts(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ICharts extends StatelessWidget {
|
||||||
|
const ICharts({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(alignment: Alignment.topCenter, children: [
|
||||||
|
Container(
|
||||||
|
width: 350,
|
||||||
|
height: 250,
|
||||||
|
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: ChartPainter(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top:8.0),
|
||||||
|
child: Text(
|
||||||
|
"捷特数学成绩统计图 - 2040 年",
|
||||||
|
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double _kScaleHeight = 8; // 刻度高
|
||||||
|
const double _kBarPadding = 10; // 柱状图前间隔
|
||||||
|
|
||||||
|
class ChartPainter extends CustomPainter {
|
||||||
|
final TextPainter _textPainter =
|
||||||
|
TextPainter(textDirection: TextDirection.ltr);
|
||||||
|
|
||||||
|
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||||
|
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||||
|
|
||||||
|
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||||
|
|
||||||
|
Path axisPath = Path();
|
||||||
|
Paint axisPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1;
|
||||||
|
|
||||||
|
Paint gridPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..color = Colors.grey
|
||||||
|
..strokeWidth = 0.5;
|
||||||
|
Paint fillPaint = Paint()..color = Colors.red;
|
||||||
|
|
||||||
|
double xStep = 0; // x 间隔
|
||||||
|
double yStep = 0; // y 间隔
|
||||||
|
|
||||||
|
double maxData = 0; // 数据最大值
|
||||||
|
|
||||||
|
ChartPainter() {
|
||||||
|
maxData = yData.reduce(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
// canvas.drawRect(
|
||||||
|
// Offset.zero & size, Paint()..color = Colors.black.withAlpha(22));
|
||||||
|
canvas.translate(0, size.height);
|
||||||
|
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||||
|
|
||||||
|
axisPath.moveTo(-_kScaleHeight, 0);
|
||||||
|
axisPath.relativeLineTo(size.width, 0);
|
||||||
|
axisPath.moveTo(0, _kScaleHeight);
|
||||||
|
axisPath.relativeLineTo(0, -size.height);
|
||||||
|
canvas.drawPath(axisPath, axisPaint);
|
||||||
|
|
||||||
|
drawYText(canvas, size);
|
||||||
|
drawXText(canvas, size);
|
||||||
|
drawBarChart(canvas, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawXText(Canvas canvas, Size size) {
|
||||||
|
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||||
|
_drawAxisText(canvas, xData[i],
|
||||||
|
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawBarChart(Canvas canvas, Size size) {
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
canvas.drawRect(
|
||||||
|
Rect.fromLTWH(_kBarPadding, 0, xStep - 2 * _kBarPadding,
|
||||||
|
-(yData[i] / maxData * (size.height - _kScaleHeight)))
|
||||||
|
.translate(-xStep, 0),
|
||||||
|
fillPaint);
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawYText(Canvas canvas, Size size) {
|
||||||
|
canvas.save();
|
||||||
|
yStep = (size.height - _kScaleHeight) / 5;
|
||||||
|
double numStep = maxData / 5;
|
||||||
|
for (int i = 0; i <= 5; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||||
|
|
||||||
|
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||||
|
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||||
|
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawAxisText(Canvas canvas, String str,
|
||||||
|
{Color color = Colors.black,
|
||||||
|
bool x = false,
|
||||||
|
Alignment alignment = Alignment.centerRight,
|
||||||
|
Offset offset = Offset.zero}) {
|
||||||
|
TextSpan text = TextSpan(
|
||||||
|
text: str,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: color,
|
||||||
|
));
|
||||||
|
|
||||||
|
_textPainter.text = text;
|
||||||
|
_textPainter.layout(); // 进行布局
|
||||||
|
|
||||||
|
Size size = _textPainter.size;
|
||||||
|
|
||||||
|
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||||
|
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||||
|
_textPainter.paint(canvas, offsetPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
197
packages/idraw/lib/p16/s02.dart
Normal file
197
packages/idraw/lib/p16/s02.dart
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
// import 'dart:ui' as ui;
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/11/5
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: const ICharts(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ICharts extends StatefulWidget {
|
||||||
|
const ICharts({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_IChartsState createState() => _IChartsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin{
|
||||||
|
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 800),
|
||||||
|
vsync: this,
|
||||||
|
)..forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(alignment: Alignment.topCenter, children: [
|
||||||
|
Container(
|
||||||
|
width: 350,
|
||||||
|
height: 250,
|
||||||
|
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: ChartPainter(repaint: _controller),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top:8.0),
|
||||||
|
child: Text(
|
||||||
|
"捷特数学成绩统计图 - 2040 年",
|
||||||
|
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double _kScaleHeight = 8; // 刻度高
|
||||||
|
const double _kBarPadding = 10; // 柱状图前间隔
|
||||||
|
|
||||||
|
class ChartPainter extends CustomPainter {
|
||||||
|
final TextPainter _textPainter =
|
||||||
|
TextPainter(textDirection: TextDirection.ltr);
|
||||||
|
|
||||||
|
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||||
|
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||||
|
|
||||||
|
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||||
|
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
|
||||||
|
Path axisPath = Path();
|
||||||
|
Paint axisPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1;
|
||||||
|
|
||||||
|
Paint gridPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..color = Colors.grey
|
||||||
|
..strokeWidth = 0.5;
|
||||||
|
Paint fillPaint = Paint()..color = Colors.red;
|
||||||
|
|
||||||
|
double xStep = 0; // x 间隔
|
||||||
|
double yStep = 0; // y 间隔
|
||||||
|
|
||||||
|
double maxData = 0; // 数据最大值
|
||||||
|
|
||||||
|
ChartPainter({required this.repaint}):super(repaint: repaint) {
|
||||||
|
maxData = yData.reduce(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
|
||||||
|
canvas.translate(0, size.height);
|
||||||
|
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||||
|
|
||||||
|
axisPath.moveTo(-_kScaleHeight, 0);
|
||||||
|
axisPath.relativeLineTo(size.width, 0);
|
||||||
|
axisPath.moveTo(0, _kScaleHeight);
|
||||||
|
axisPath.relativeLineTo(0, -size.height);
|
||||||
|
canvas.drawPath(axisPath, axisPaint);
|
||||||
|
|
||||||
|
drawYText(canvas, size);
|
||||||
|
drawXText(canvas, size);
|
||||||
|
drawBarChart(canvas,size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawXText(Canvas canvas, Size size) {
|
||||||
|
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||||
|
_drawAxisText(canvas, xData[i],
|
||||||
|
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawBarChart(Canvas canvas, Size size) {
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||||
|
canvas.drawRect(
|
||||||
|
Rect.fromLTWH(
|
||||||
|
_kBarPadding, 0, xStep-2*_kBarPadding, dataHeight*repaint.value)
|
||||||
|
.translate(-xStep, 0),
|
||||||
|
fillPaint);
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawYText(Canvas canvas, Size size) {
|
||||||
|
canvas.save();
|
||||||
|
yStep = (size.height - _kScaleHeight) / 5;
|
||||||
|
double numStep = maxData / 5;
|
||||||
|
for (int i = 0; i <= 5; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||||
|
|
||||||
|
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||||
|
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||||
|
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawAxisText(Canvas canvas, String str,
|
||||||
|
{Color color = Colors.black,
|
||||||
|
bool x = false,
|
||||||
|
Alignment alignment = Alignment.centerRight,
|
||||||
|
Offset offset = Offset.zero}) {
|
||||||
|
TextSpan text = TextSpan(
|
||||||
|
text: str,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: color,
|
||||||
|
));
|
||||||
|
|
||||||
|
_textPainter.text = text;
|
||||||
|
_textPainter.layout(); // 进行布局
|
||||||
|
|
||||||
|
Size size = _textPainter.size;
|
||||||
|
|
||||||
|
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||||
|
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||||
|
_textPainter.paint(canvas, offsetPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
215
packages/idraw/lib/p16/s03.dart
Normal file
215
packages/idraw/lib/p16/s03.dart
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
// import 'dart:ui' as ui;
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/11/5
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: const ICharts(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ICharts extends StatefulWidget {
|
||||||
|
const ICharts({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_IChartsState createState() => _IChartsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
vsync: this,
|
||||||
|
)
|
||||||
|
..forward()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(alignment: Alignment.topCenter, children: [
|
||||||
|
Container(
|
||||||
|
width: 350,
|
||||||
|
height: 250,
|
||||||
|
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: ChartPainter(repaint: _controller),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"捷特数学成绩统计图 - 2040 年",
|
||||||
|
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double _kScaleHeight = 8; // 刻度高
|
||||||
|
const double _kBarPadding = 10; // 柱状图前间隔
|
||||||
|
|
||||||
|
class ChartPainter extends CustomPainter {
|
||||||
|
final TextPainter _textPainter =
|
||||||
|
TextPainter(textDirection: TextDirection.ltr);
|
||||||
|
|
||||||
|
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||||
|
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||||
|
|
||||||
|
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||||
|
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
Path axisPath = Path();
|
||||||
|
Paint axisPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1;
|
||||||
|
|
||||||
|
Paint gridPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..color = Colors.grey
|
||||||
|
..strokeWidth = 0.5;
|
||||||
|
Paint fillPaint = Paint()..color = Colors.red;
|
||||||
|
Paint linePaint = Paint()
|
||||||
|
..color = Colors.red
|
||||||
|
..strokeCap=StrokeCap.round
|
||||||
|
..style = PaintingStyle.stroke;
|
||||||
|
|
||||||
|
double xStep = 0; // x 间隔
|
||||||
|
double yStep = 0; // y 间隔
|
||||||
|
|
||||||
|
double maxData = 0; // 数据最大值
|
||||||
|
|
||||||
|
final List<Offset> line = []; // 折线点位信息
|
||||||
|
|
||||||
|
ChartPainter({required this.repaint}) : super(repaint: repaint) {
|
||||||
|
maxData = yData.reduce(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||||
|
yStep = (size.height - _kScaleHeight) / 5;
|
||||||
|
|
||||||
|
canvas.translate(0, size.height);
|
||||||
|
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||||
|
axisPath.moveTo(-_kScaleHeight, 0);
|
||||||
|
axisPath.relativeLineTo(size.width, 0);
|
||||||
|
axisPath.moveTo(0, _kScaleHeight);
|
||||||
|
axisPath.relativeLineTo(0, -size.height);
|
||||||
|
canvas.drawPath(axisPath, axisPaint);
|
||||||
|
|
||||||
|
drawYText(canvas, size);
|
||||||
|
drawXText(canvas, size);
|
||||||
|
collectPoints(canvas, size);
|
||||||
|
drawLineChart(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawXText(Canvas canvas, Size size) {
|
||||||
|
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||||
|
_drawAxisText(canvas, xData[i],
|
||||||
|
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void collectPoints(Canvas canvas, Size size) {
|
||||||
|
line.clear();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||||
|
line.add(Offset(xStep * i-xStep/2, dataHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawLineChart(Canvas canvas){
|
||||||
|
canvas.drawPoints(PointMode.points, line, linePaint..strokeWidth=5);
|
||||||
|
|
||||||
|
Offset p1 = line[0];
|
||||||
|
Path path = Path()..moveTo(p1.dx, p1.dy);
|
||||||
|
for (var i = 1; i < line.length; i++) {
|
||||||
|
path.lineTo(line[i].dx, line[i].dy);
|
||||||
|
}
|
||||||
|
linePaint..strokeWidth=1;
|
||||||
|
PathMetrics pms = path.computeMetrics();
|
||||||
|
pms.forEach((pm) {
|
||||||
|
canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), linePaint);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawYText(Canvas canvas, Size size) {
|
||||||
|
canvas.save();
|
||||||
|
double numStep = maxData / 5;
|
||||||
|
for (int i = 0; i <= 5; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||||
|
|
||||||
|
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||||
|
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||||
|
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawAxisText(Canvas canvas, String str,
|
||||||
|
{Color color = Colors.black,
|
||||||
|
bool x = false,
|
||||||
|
Alignment alignment = Alignment.centerRight,
|
||||||
|
Offset offset = Offset.zero}) {
|
||||||
|
TextSpan text = TextSpan(
|
||||||
|
text: str,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: color,
|
||||||
|
));
|
||||||
|
|
||||||
|
_textPainter.text = text;
|
||||||
|
_textPainter.layout(); // 进行布局
|
||||||
|
|
||||||
|
Size size = _textPainter.size;
|
||||||
|
|
||||||
|
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||||
|
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||||
|
_textPainter.paint(canvas, offsetPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||||
|
|
||||||
|
}
|
||||||
237
packages/idraw/lib/p16/s04.dart
Normal file
237
packages/idraw/lib/p16/s04.dart
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
// import 'dart:ui' as ui;
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/11/5
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: const ICharts(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ICharts extends StatefulWidget {
|
||||||
|
const ICharts({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_IChartsState createState() => _IChartsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
vsync: this,
|
||||||
|
)
|
||||||
|
..forward()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(alignment: Alignment.topCenter, children: [
|
||||||
|
Container(
|
||||||
|
width: 350,
|
||||||
|
height: 250,
|
||||||
|
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: ChartPainter(repaint: _controller),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"捷特数学成绩统计图 - 2040 年",
|
||||||
|
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double _kScaleHeight = 8; // 刻度高
|
||||||
|
const double _kBarPadding = 10; // 柱状图前间隔
|
||||||
|
|
||||||
|
class ChartPainter extends CustomPainter {
|
||||||
|
final TextPainter _textPainter =
|
||||||
|
TextPainter(textDirection: TextDirection.ltr);
|
||||||
|
|
||||||
|
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||||
|
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||||
|
|
||||||
|
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||||
|
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
Path axisPath = Path();
|
||||||
|
Paint axisPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1;
|
||||||
|
|
||||||
|
Paint gridPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..color = Colors.grey
|
||||||
|
..strokeWidth = 0.5;
|
||||||
|
Paint fillPaint = Paint()..color = Colors.red;
|
||||||
|
Paint linePaint = Paint()
|
||||||
|
..color = Colors.orange
|
||||||
|
..strokeCap=StrokeCap.round
|
||||||
|
..style = PaintingStyle.stroke;
|
||||||
|
|
||||||
|
double xStep = 0; // x 间隔
|
||||||
|
double yStep = 0; // y 间隔
|
||||||
|
|
||||||
|
double maxData = 0; // 数据最大值
|
||||||
|
|
||||||
|
final List<Offset> line = []; // 折线点位信息
|
||||||
|
|
||||||
|
ChartPainter({required this.repaint}) : super(repaint: repaint) {
|
||||||
|
maxData = yData.reduce(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||||
|
yStep = (size.height - _kScaleHeight) / 5;
|
||||||
|
|
||||||
|
canvas.translate(0, size.height);
|
||||||
|
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||||
|
axisPath.moveTo(-_kScaleHeight, 0);
|
||||||
|
axisPath.relativeLineTo(size.width, 0);
|
||||||
|
axisPath.moveTo(0, _kScaleHeight);
|
||||||
|
axisPath.relativeLineTo(0, -size.height);
|
||||||
|
canvas.drawPath(axisPath, axisPaint);
|
||||||
|
|
||||||
|
drawYText(canvas, size);
|
||||||
|
drawXText(canvas, size);
|
||||||
|
collectPoints(canvas, size);
|
||||||
|
drawLineChart(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawXText(Canvas canvas, Size size) {
|
||||||
|
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||||
|
_drawAxisText(canvas, xData[i],
|
||||||
|
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void collectPoints(Canvas canvas, Size size) {
|
||||||
|
line.clear();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||||
|
line.add(Offset(xStep * i-xStep/2, dataHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawLineChart(Canvas canvas){
|
||||||
|
canvas.drawPoints(PointMode.points, line, linePaint..strokeWidth=5);
|
||||||
|
Path path = Path();
|
||||||
|
addBezierPathWithPoints(path, line);
|
||||||
|
linePaint..strokeWidth=1;
|
||||||
|
PathMetrics pms = path.computeMetrics();
|
||||||
|
pms.forEach((pm) {
|
||||||
|
canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), linePaint);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawYText(Canvas canvas, Size size) {
|
||||||
|
canvas.save();
|
||||||
|
double numStep = maxData / 5;
|
||||||
|
for (int i = 0; i <= 5; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||||
|
|
||||||
|
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||||
|
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||||
|
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addBezierPathWithPoints(Path path, List<Offset> points) {
|
||||||
|
for (int i = 0; i < points.length - 1; i++) {
|
||||||
|
Offset current = points[i];
|
||||||
|
Offset next = points[i+1];
|
||||||
|
if (i == 0) {
|
||||||
|
path.moveTo(current.dx, current.dy);
|
||||||
|
// 控制点
|
||||||
|
double ctrlX = current.dx + (next.dx - current.dx) / 2;
|
||||||
|
double ctrlY = next.dy;
|
||||||
|
path.quadraticBezierTo(ctrlX, ctrlY, next.dx, next.dy);
|
||||||
|
} else if (i < points.length - 2) {
|
||||||
|
// 控制点 1
|
||||||
|
double ctrl1X = current.dx + (next.dx - current.dx) / 2;
|
||||||
|
double ctrl1Y = current.dy;
|
||||||
|
// 控制点 2
|
||||||
|
double ctrl2X = ctrl1X;
|
||||||
|
double ctrl2Y = next.dy;
|
||||||
|
path.cubicTo(ctrl1X,ctrl1Y,ctrl2X,ctrl2Y,next.dx,next.dy);
|
||||||
|
}else{
|
||||||
|
// 控制点
|
||||||
|
double ctrlX = (next.dx - current.dx) / 2;
|
||||||
|
double ctrlY = 0;
|
||||||
|
path.relativeQuadraticBezierTo(ctrlX, ctrlY, next.dx-current.dx, next.dy-current.dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawAxisText(Canvas canvas, String str,
|
||||||
|
{Color color = Colors.black,
|
||||||
|
bool x = false,
|
||||||
|
Alignment alignment = Alignment.centerRight,
|
||||||
|
Offset offset = Offset.zero}) {
|
||||||
|
TextSpan text = TextSpan(
|
||||||
|
text: str,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: color,
|
||||||
|
));
|
||||||
|
|
||||||
|
_textPainter.text = text;
|
||||||
|
_textPainter.layout(); // 进行布局
|
||||||
|
|
||||||
|
Size size = _textPainter.size;
|
||||||
|
|
||||||
|
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||||
|
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||||
|
_textPainter.paint(canvas, offsetPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||||
|
|
||||||
|
}
|
||||||
232
packages/idraw/lib/p16/s05.dart
Normal file
232
packages/idraw/lib/p16/s05.dart
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
// import 'dart:ui' as ui;
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/11/5
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: const ICharts(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ICharts extends StatefulWidget {
|
||||||
|
const ICharts({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_IChartsState createState() => _IChartsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
vsync: this,
|
||||||
|
)
|
||||||
|
..forward()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(alignment: Alignment.topCenter, children: [
|
||||||
|
Container(
|
||||||
|
width: 350,
|
||||||
|
height: 250,
|
||||||
|
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: ChartPainter(repaint: _controller),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"捷特数学成绩统计图 - 2040 年",
|
||||||
|
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double _kScaleHeight = 8; // 刻度高
|
||||||
|
const double _kBarPadding = 10; // 柱状图前间隔
|
||||||
|
|
||||||
|
class ChartPainter extends CustomPainter {
|
||||||
|
final TextPainter _textPainter =
|
||||||
|
TextPainter(textDirection: TextDirection.ltr);
|
||||||
|
|
||||||
|
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||||
|
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||||
|
|
||||||
|
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||||
|
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
Path axisPath = Path();
|
||||||
|
Paint axisPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1;
|
||||||
|
|
||||||
|
Paint gridPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..color = Colors.grey
|
||||||
|
..strokeWidth = 0.5;
|
||||||
|
Paint fillPaint = Paint()..color = Colors.red;
|
||||||
|
Paint linePaint = Paint()
|
||||||
|
..color = Colors.red
|
||||||
|
..strokeCap=StrokeCap.round
|
||||||
|
..style = PaintingStyle.stroke;
|
||||||
|
|
||||||
|
double xStep = 0; // x 间隔
|
||||||
|
double yStep = 0; // y 间隔
|
||||||
|
|
||||||
|
double maxData = 0; // 数据最大值
|
||||||
|
|
||||||
|
final List<Offset> line = []; // 折线点位信息
|
||||||
|
|
||||||
|
ChartPainter({required this.repaint}) : super(repaint: repaint) {
|
||||||
|
maxData = yData.reduce(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||||
|
yStep = (size.height - _kScaleHeight) / 5;
|
||||||
|
|
||||||
|
canvas.translate(0, size.height);
|
||||||
|
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||||
|
axisPath.moveTo(-_kScaleHeight, 0);
|
||||||
|
axisPath.relativeLineTo(size.width, 0);
|
||||||
|
axisPath.moveTo(0, _kScaleHeight);
|
||||||
|
axisPath.relativeLineTo(0, -size.height);
|
||||||
|
canvas.drawPath(axisPath, axisPaint);
|
||||||
|
|
||||||
|
drawYText(canvas, size);
|
||||||
|
drawXText(canvas, size);
|
||||||
|
drawBarChart(canvas,size);
|
||||||
|
collectPoints(canvas, size);
|
||||||
|
drawLineChart(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawXText(Canvas canvas, Size size) {
|
||||||
|
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||||
|
_drawAxisText(canvas, xData[i],
|
||||||
|
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void collectPoints(Canvas canvas, Size size) {
|
||||||
|
line.clear();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||||
|
line.add(Offset(xStep * i-xStep/2, dataHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawBarChart(Canvas canvas, Size size) {
|
||||||
|
fillPaint..color=Colors.lightBlue;
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
for (int i = 0; i < xData.length; i++) {
|
||||||
|
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||||
|
canvas.drawRect(
|
||||||
|
Rect.fromLTWH(
|
||||||
|
_kBarPadding, 0, xStep-2*_kBarPadding, dataHeight*repaint.value)
|
||||||
|
.translate(-xStep, 0),
|
||||||
|
fillPaint);
|
||||||
|
canvas.translate(xStep, 0);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void drawLineChart(Canvas canvas){
|
||||||
|
canvas.drawPoints(PointMode.points, line, linePaint..strokeWidth=5);
|
||||||
|
|
||||||
|
Offset p1 = line[0];
|
||||||
|
Path path = Path()..moveTo(p1.dx, p1.dy);
|
||||||
|
for (var i = 1; i < line.length; i++) {
|
||||||
|
path.lineTo(line[i].dx, line[i].dy);
|
||||||
|
}
|
||||||
|
linePaint..strokeWidth=1;
|
||||||
|
PathMetrics pms = path.computeMetrics();
|
||||||
|
pms.forEach((pm) {
|
||||||
|
canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), linePaint);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawYText(Canvas canvas, Size size) {
|
||||||
|
canvas.save();
|
||||||
|
double numStep = maxData / 5;
|
||||||
|
for (int i = 0; i <= 5; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||||
|
|
||||||
|
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||||
|
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||||
|
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawAxisText(Canvas canvas, String str,
|
||||||
|
{Color color = Colors.black,
|
||||||
|
bool x = false,
|
||||||
|
Alignment alignment = Alignment.centerRight,
|
||||||
|
Offset offset = Offset.zero}) {
|
||||||
|
TextSpan text = TextSpan(
|
||||||
|
text: str,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: color,
|
||||||
|
));
|
||||||
|
|
||||||
|
_textPainter.text = text;
|
||||||
|
_textPainter.layout(); // 进行布局
|
||||||
|
|
||||||
|
Size size = _textPainter.size;
|
||||||
|
|
||||||
|
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||||
|
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||||
|
_textPainter.paint(canvas, offsetPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||||
|
|
||||||
|
}
|
||||||
254
packages/idraw/lib/p16/s06.dart
Normal file
254
packages/idraw/lib/p16/s06.dart
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
// import 'dart:ui' as ui;
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// create by 张风捷特烈 on 2020/11/5
|
||||||
|
/// contact me by email 1981462002@qq.com
|
||||||
|
/// 说明:
|
||||||
|
class Paper extends StatelessWidget {
|
||||||
|
const Paper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: const ICharts(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ICharts extends StatefulWidget {
|
||||||
|
const ICharts({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_IChartsState createState() => _IChartsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
vsync: this,
|
||||||
|
)
|
||||||
|
..forward()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(alignment: Alignment.topCenter, children: [
|
||||||
|
Container(
|
||||||
|
width: 400,
|
||||||
|
height: 300,
|
||||||
|
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: ChartPainter(repaint: _controller),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"捷特 3 月支出统计图 - 2040 年",
|
||||||
|
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double _kScaleHeight = 8; // 刻度高
|
||||||
|
const double _kBarPadding = 10; // 柱状图前间隔
|
||||||
|
const double _kPiePadding = 20; // 饼状图边距
|
||||||
|
|
||||||
|
class ChartPainter extends CustomPainter {
|
||||||
|
final TextPainter _textPainter =
|
||||||
|
TextPainter(textDirection: TextDirection.ltr);
|
||||||
|
|
||||||
|
final List<double> yData = [0.12, 0.25, 0.1, 0.18, 0.15, 0.2];
|
||||||
|
final List<Color> colors = [
|
||||||
|
Colors.red,
|
||||||
|
Colors.orangeAccent,
|
||||||
|
Colors.blue,
|
||||||
|
Colors.green,
|
||||||
|
Colors.purple,
|
||||||
|
Colors.pink
|
||||||
|
];
|
||||||
|
final List<String> xData = ["学习资料", "伙食费", "话费", "游玩", "游戏", "其他"];
|
||||||
|
|
||||||
|
final Animation<double> repaint;
|
||||||
|
|
||||||
|
Path axisPath = Path();
|
||||||
|
Paint axisPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1;
|
||||||
|
|
||||||
|
Paint gridPaint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..color = Colors.grey
|
||||||
|
..strokeWidth = 0.5;
|
||||||
|
Paint fillPaint = Paint()..color = Colors.red;
|
||||||
|
Paint linePaint = Paint()
|
||||||
|
..color = Colors.red
|
||||||
|
..strokeCap = StrokeCap.round
|
||||||
|
..style = PaintingStyle.stroke;
|
||||||
|
|
||||||
|
double radius = 0; // 饼图半径
|
||||||
|
double yStep = 0; // y 间隔
|
||||||
|
|
||||||
|
double maxData = 0; // 数据最大值
|
||||||
|
|
||||||
|
final List<Offset> line = []; // 折线点位信息
|
||||||
|
|
||||||
|
ChartPainter({required this.repaint}) : super(repaint: repaint) {
|
||||||
|
maxData = yData.reduce(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
radius = size.shortestSide / 2 - _kPiePadding;
|
||||||
|
|
||||||
|
canvas.translate(size.width / 2, size.height / 2);
|
||||||
|
canvas.rotate(-pi / 2);
|
||||||
|
|
||||||
|
Path clipPath = Path();
|
||||||
|
clipPath.lineTo(radius, 0);
|
||||||
|
clipPath.arcTo(
|
||||||
|
Rect.fromCenter(center: Offset.zero, width: radius * 4, height: radius * 4),
|
||||||
|
0, 2 * pi * repaint.value, false);
|
||||||
|
clipPath.close();
|
||||||
|
if(repaint.value!=1.0){
|
||||||
|
canvas.clipPath(clipPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
drawPieChart(canvas);
|
||||||
|
drawInfo(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawInfo(Canvas canvas) {
|
||||||
|
for (int i = 0; i < yData.length; i++) {
|
||||||
|
Color color = colors[i % colors.length];
|
||||||
|
|
||||||
|
canvas.save();
|
||||||
|
canvas.rotate(2 * pi * yData[i] / 2);
|
||||||
|
_drawAxisText(canvas, "${(yData[i] * 100).toStringAsFixed(1)}%",
|
||||||
|
color: Colors.white,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
offset: Offset(radius / 2 + 5, 0));
|
||||||
|
|
||||||
|
Path showPath = Path();
|
||||||
|
showPath.moveTo(radius, 0);
|
||||||
|
showPath.relativeLineTo(15, 0);
|
||||||
|
showPath.relativeLineTo(5, 10);
|
||||||
|
canvas.drawPath(
|
||||||
|
showPath,
|
||||||
|
linePaint..color = color,
|
||||||
|
);
|
||||||
|
|
||||||
|
_drawAxisText(canvas, xData[i],
|
||||||
|
color: color,
|
||||||
|
fontSize: 9,
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
offset: Offset(radius + 5, 18));
|
||||||
|
canvas.restore();
|
||||||
|
|
||||||
|
canvas.rotate(2 * pi * yData[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawPieChart(Canvas canvas) {
|
||||||
|
for (int i = 0; i < yData.length; i++) {
|
||||||
|
Color color = colors[i % colors.length];
|
||||||
|
Path path = Path();
|
||||||
|
path.lineTo(radius, 0);
|
||||||
|
path.arcTo(
|
||||||
|
Rect.fromCenter(
|
||||||
|
center: Offset.zero, width: radius * 2, height: radius * 2),
|
||||||
|
0,
|
||||||
|
2 * pi * yData[i],
|
||||||
|
false);
|
||||||
|
path.close();
|
||||||
|
canvas.drawPath(
|
||||||
|
path,
|
||||||
|
fillPaint
|
||||||
|
..style = PaintingStyle.fill
|
||||||
|
..color = color);
|
||||||
|
canvas.rotate(2 * pi * yData[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawLineChart(Canvas canvas) {
|
||||||
|
canvas.drawPoints(PointMode.points, line, linePaint..strokeWidth = 5);
|
||||||
|
|
||||||
|
Offset p1 = line[0];
|
||||||
|
Path path = Path()..moveTo(p1.dx, p1.dy);
|
||||||
|
for (var i = 1; i < line.length; i++) {
|
||||||
|
path.lineTo(line[i].dx, line[i].dy);
|
||||||
|
}
|
||||||
|
linePaint..strokeWidth = 1;
|
||||||
|
PathMetrics pms = path.computeMetrics();
|
||||||
|
pms.forEach((pm) {
|
||||||
|
canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), linePaint);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawYText(Canvas canvas, Size size) {
|
||||||
|
canvas.save();
|
||||||
|
double numStep = maxData / 5;
|
||||||
|
for (int i = 0; i <= 5; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||||
|
|
||||||
|
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||||
|
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||||
|
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||||
|
canvas.translate(0, -yStep);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _drawAxisText(Canvas canvas, String str,
|
||||||
|
{Color color = Colors.black,
|
||||||
|
double fontSize = 11,
|
||||||
|
bool x = false,
|
||||||
|
Alignment alignment = Alignment.centerRight,
|
||||||
|
Offset offset = Offset.zero}) {
|
||||||
|
TextSpan text = TextSpan(
|
||||||
|
text: str,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: fontSize,
|
||||||
|
color: color,
|
||||||
|
));
|
||||||
|
|
||||||
|
_textPainter.text = text;
|
||||||
|
_textPainter.layout(); // 进行布局
|
||||||
|
|
||||||
|
Size size = _textPainter.size;
|
||||||
|
|
||||||
|
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||||
|
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||||
|
_textPainter.paint(canvas, offsetPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
1
packages/idraw/lib/p17/p17.dart
Normal file
1
packages/idraw/lib/p17/p17.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export 'p17_page.dart';
|
||||||
21
packages/idraw/lib/p17/p17_page.dart
Normal file
21
packages/idraw/lib/p17/p17_page.dart
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:components/components.dart';
|
||||||
|
import 's01.dart' as s1;
|
||||||
|
import 's02.dart' as s2;
|
||||||
|
|
||||||
|
class P17Page extends StatelessWidget {
|
||||||
|
const P17Page({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const DemoShower(
|
||||||
|
srcCodeDir: 'draw/p17',
|
||||||
|
|
||||||
|
demos: [
|
||||||
|
s1.Paper(),
|
||||||
|
// s2.Paper(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user