diff --git a/assets/images/anima.webp b/assets/images/anima.webp
new file mode 100644
index 0000000..3efbad4
Binary files /dev/null and b/assets/images/anima.webp differ
diff --git a/assets/images/bg.jpeg b/assets/images/bg.jpeg
new file mode 100644
index 0000000..f4bf605
Binary files /dev/null and b/assets/images/bg.jpeg differ
diff --git a/assets/images/boy.svg b/assets/images/boy.svg
new file mode 100644
index 0000000..5cb95f9
--- /dev/null
+++ b/assets/images/boy.svg
@@ -0,0 +1,43 @@
+
+
\ No newline at end of file
diff --git a/assets/images/draw.webp b/assets/images/draw.webp
new file mode 100644
index 0000000..db266cf
Binary files /dev/null and b/assets/images/draw.webp differ
diff --git a/assets/images/dream.webp b/assets/images/dream.webp
new file mode 100644
index 0000000..e976588
Binary files /dev/null and b/assets/images/dream.webp differ
diff --git a/assets/images/dst.png b/assets/images/dst.png
new file mode 100644
index 0000000..2b58bb3
Binary files /dev/null and b/assets/images/dst.png differ
diff --git a/assets/images/first.webp b/assets/images/first.webp
new file mode 100644
index 0000000..b335fe3
Binary files /dev/null and b/assets/images/first.webp differ
diff --git a/assets/images/flutter.png b/assets/images/flutter.png
new file mode 100644
index 0000000..b891cf3
Binary files /dev/null and b/assets/images/flutter.png differ
diff --git a/assets/images/icon_head.png b/assets/images/icon_head.png
new file mode 100644
index 0000000..e12afaa
Binary files /dev/null and b/assets/images/icon_head.png differ
diff --git a/assets/images/layout.webp b/assets/images/layout.webp
new file mode 100644
index 0000000..392cd6f
Binary files /dev/null and b/assets/images/layout.webp differ
diff --git a/assets/images/rain.png b/assets/images/rain.png
new file mode 100644
index 0000000..2236061
Binary files /dev/null and b/assets/images/rain.png differ
diff --git a/assets/images/regex.webp b/assets/images/regex.webp
new file mode 100644
index 0000000..8034173
Binary files /dev/null and b/assets/images/regex.webp differ
diff --git a/assets/images/render.webp b/assets/images/render.webp
new file mode 100644
index 0000000..dbb6ecc
Binary files /dev/null and b/assets/images/render.webp differ
diff --git a/assets/images/right_chat.png b/assets/images/right_chat.png
new file mode 100644
index 0000000..299edbd
Binary files /dev/null and b/assets/images/right_chat.png differ
diff --git a/assets/images/scroll.webp b/assets/images/scroll.webp
new file mode 100644
index 0000000..3430b79
Binary files /dev/null and b/assets/images/scroll.webp differ
diff --git a/assets/images/shoot.png b/assets/images/shoot.png
new file mode 100644
index 0000000..65f0237
Binary files /dev/null and b/assets/images/shoot.png differ
diff --git a/assets/images/src.png b/assets/images/src.png
new file mode 100644
index 0000000..5c557ac
Binary files /dev/null and b/assets/images/src.png differ
diff --git a/assets/images/sword.png b/assets/images/sword.png
new file mode 100644
index 0000000..82bf71c
Binary files /dev/null and b/assets/images/sword.png differ
diff --git a/assets/images/t.svg b/assets/images/t.svg
new file mode 100644
index 0000000..78c0ceb
--- /dev/null
+++ b/assets/images/t.svg
@@ -0,0 +1,728 @@
+
+
+
diff --git a/assets/images/touch.webp b/assets/images/touch.webp
new file mode 100644
index 0000000..9ecdcfc
Binary files /dev/null and b/assets/images/touch.webp differ
diff --git a/assets/images/wy_200x300.jpg b/assets/images/wy_200x300.jpg
new file mode 100644
index 0000000..ce7c56b
Binary files /dev/null and b/assets/images/wy_200x300.jpg differ
diff --git a/assets/images/wy_300x200.jpg b/assets/images/wy_300x200.jpg
new file mode 100644
index 0000000..82ad407
Binary files /dev/null and b/assets/images/wy_300x200.jpg differ
diff --git a/lib/main.dart b/lib/main.dart
index 6ae6bc5..76cfee1 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -5,13 +5,14 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:window_manager/window_manager.dart';
+import 'navigation/app_navigation.dart';
import 'v12/app.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
setSize();
GoRouter.optionURLReflectsImperativeAPIs = true;
- runApp(UnitApp());
+ runApp(TolyBooksApp());
}
@@ -19,7 +20,7 @@ void setSize() async{
if(kIsWeb||Platform.isAndroid||Platform.isIOS) return;
await windowManager.ensureInitialized();
WindowOptions windowOptions = const WindowOptions(
- size: Size(800, 540),
+ size: Size(1024, 1024*3/4),
minimumSize: Size(600, 400),
center: true,
backgroundColor: Colors.transparent,
diff --git a/lib/navigation/app_navigation.dart b/lib/navigation/app_navigation.dart
new file mode 100644
index 0000000..a28da76
--- /dev/null
+++ b/lib/navigation/app_navigation.dart
@@ -0,0 +1,113 @@
+import 'package:flutter/material.dart';
+import 'package:go_router/go_router.dart';
+import 'package:iroute/components/components.dart';
+import 'package:toly_menu/src/menu.dart';
+import 'package:toly_menu/src/model/menu_state.dart';
+import 'package:toly_menu/toly_menu.dart';
+
+import '../v12/app/navigation/transition/fade_page_transitions_builder.dart';
+import 'router/menus/menu_tree.dart';
+import 'views/top_logo.dart';
+import 'views/top_bar.dart';
+import 'package:iroute/navigation/router/routers/app.dart';
+
+class TolyBooksApp extends StatelessWidget {
+ final GoRouter _router = GoRouter(
+ initialLocation: '/dashboard/view',
+ routes: [appRoute],
+ onException: (BuildContext ctx, GoRouterState state, GoRouter router) {
+ router.go('/404', extra: state.uri.toString());
+ },
+ // redirect: _authRedirect
+ );
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp.router(
+ routerConfig: _router,
+ debugShowCheckedModeBanner: false,
+ title: 'Flutter Demo',
+ theme: ThemeData(
+ fontFamily: "宋体",
+ primarySwatch: Colors.blue,
+ pageTransitionsTheme: const PageTransitionsTheme(builders: {
+ TargetPlatform.android: ZoomPageTransitionsBuilder(),
+ TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
+ TargetPlatform.macOS: FadePageTransitionsBuilder(),
+ TargetPlatform.windows: FadePageTransitionsBuilder(),
+ TargetPlatform.linux: FadePageTransitionsBuilder(),
+ }),
+ ),
+ );
+ }
+}
+
+class BookAppNavigation extends StatefulWidget {
+ final Widget content;
+ const BookAppNavigation({super.key, required this.content});
+
+ @override
+ State createState() => _BookAppNavigationState();
+}
+
+class _BookAppNavigationState extends State {
+ MenuState state = MenuState(
+ expandMenus: ['/dashboard'],
+ activeMenu: '/dashboard/view',
+ items: rootMenu.children);
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Row(
+ children: [
+ DragToMoveWrap(
+ child: Container(
+ color: const Color(0xff001529),
+ width: 210,
+ child: Column(
+ children: [
+ TopLogo(),
+ Expanded(child: TolyMenu(state: state, onSelect: _onSelect)),
+ ],
+ ),
+ ),
+ ),
+ Expanded(
+ child: Column(
+ children: [AppTopBar(), Expanded(child: widget.content)],
+ ),
+ )
+ ],
+ ),
+ );
+ }
+
+ void _onSelect(MenuNode menu) {
+ if (menu.isLeaf) {
+ state = state.copyWith(activeMenu: menu.path);
+ print(menu.path);
+ // print(;
+ context.go(menu.path);
+ } else {
+ List menus = [];
+ String path = menu.path.substring(1);
+ List parts = path.split('/');
+
+ if (parts.isNotEmpty) {
+ String path = '';
+ for (String part in parts) {
+ path += '/$part';
+ menus.add(path);
+ }
+ }
+
+ if (state.expandMenus.contains(menu.path)) {
+ menus.remove(menu.path);
+ }
+
+ state = state.copyWith(expandMenus: menus);
+ }
+ setState(() {});
+ }
+}
diff --git a/lib/navigation/router/menus/anima.dart b/lib/navigation/router/menus/anima.dart
new file mode 100644
index 0000000..ed1105b
--- /dev/null
+++ b/lib/navigation/router/menus/anima.dart
@@ -0,0 +1,78 @@
+Map animaMenus = {
+ 'path' : '/anima',
+ 'label' : '动画-流光幻影',
+ 'children': [
+ {
+ 'path' : '/chapter1',
+ 'label' : '1.欢迎来到 Flutter 动画世界',
+ },
+ {
+ 'path' : '/chapter2',
+ 'label' : '2.基于文字的组件动画初体验',
+ },
+ {
+ 'path' : '/chapter3',
+ 'label' : '3.全面认识 AnimationController 的使用',
+ },
+ {
+ 'path' : '/chapter4',
+ 'label' : '4.认知和自定义 Curve 动画曲线',
+ },
+ {
+ 'path' : '/chapter5',
+ 'label' : '5.认识和自定义 Tween 补间动画',
+ },
+ {
+ 'path' : '/chapter6',
+ 'label' : '6.通过三个案例巩固练习动画使用',
+ },
+ {
+ 'path' : '/chapter7',
+ 'label' : '7.通过 loading 绘制练习动画使用',
+ },
+ {
+ 'path' : '/chapter8',
+ 'label' : '8.Flutter 内置动画组件-显式动画',
+ },
+ {
+ 'path' : '/chapter9',
+ 'label' : '9.显式动画 AnimatedWidget 源码解读',
+ },
+ {
+ 'path' : '/chapter10',
+ 'label' : '10.Flutter 内置动画组件-隐式动画',
+ },
+ {
+ 'path' : '/chapter11',
+ 'label' : '11.隐式动画 ImplicitlyAnimatedWidget 源码解读',
+ },
+ {
+ 'path' : '/chapter12',
+ 'label' : '12.Flutter 内置动画组件 - 其他动画',
+ },
+ {
+ 'path' : '/chapter13',
+ 'label' : '13.Flutter 框架层动画相关类源码分析',
+ },
+ {
+ 'path' : '/chapter14',
+ 'label' : '14.Flutter 框架层动画相关类关系梳理',
+ },
+ {
+ 'path' : '/chapter15',
+ 'label' : '15.AnimationController 源码解读',
+ },
+ {
+ 'path' : '/chapter16',
+ 'label' : '16.Ticker 与 TickerProvider 源码解读',
+ },
+ {
+ 'path' : '/chapter17',
+ 'label' : '17.小试牛刀 - 秒表功能和界面分析',
+ },
+ {
+ 'path' : '/chapter18',
+ 'label' : '18.使用 Ticker 驱动钟表运动',
+ },
+ ]
+};
diff --git a/lib/navigation/router/menus/draw.dart b/lib/navigation/router/menus/draw.dart
new file mode 100644
index 0000000..72b0270
--- /dev/null
+++ b/lib/navigation/router/menus/draw.dart
@@ -0,0 +1,90 @@
+Map drawMenus = {
+ 'path': '/draw',
+ 'label': '绘制-妙笔生花',
+ 'children': [
+ {
+ 'path': '/chapter1',
+ 'label': '1.纯粹的世界',
+ },
+ {
+ 'path': '/chapter2',
+ 'label': '2.认识画笔的属性',
+ },
+ {
+ 'path': '/chapter3',
+ 'label': '3.画布绘制基础操作',
+ },
+ {
+ 'path': '/chapter4',
+ 'label': '4.画布绘制图片文字',
+ },
+ {
+ 'path': '/chapter5',
+ 'label': '5.路径的图形添加',
+ },
+ {
+ 'path': '/chapter6',
+ 'label': '6.路径的操作方法',
+ },
+ {
+ 'path': '/chapter7',
+ 'label': '7.熟悉而陌生的颜色',
+ },
+ {
+ 'path': '/chapter8',
+ 'label': '8.着色器和过滤器',
+ },
+ {
+ 'path': '/chapter9',
+ 'label': '9.世界之基-CustomPainter',
+ },
+ {
+ 'path': '/chapter10',
+ 'label': '10.绘制中使用动画',
+ },
+ {
+ 'path': '/chapter11',
+ 'label': '11.动画器曲线和方法',
+ },
+ {
+ 'path': '/chapter12',
+ 'label': '12.手势在绘制中的使用',
+ },
+ {
+ 'path': '/chapter13',
+ 'label': '13.Path 与曲线拟合',
+ },
+ {
+ 'path': '/chapter14',
+ 'label': '14.认知贝塞尔曲线',
+ },
+ {
+ 'path': '/chapter15',
+ 'label': '15.使用贝塞尔曲线',
+ },
+ {
+ 'path': '/chapter16',
+ 'label': '16.简单统计图表绘制',
+ },
+ {
+ 'path': '/chapter17',
+ 'label': '17.复杂图表绘制',
+ },
+ {
+ 'path': '/chapter18',
+ 'label': '18.粒子物理运动',
+ },
+ {
+ 'path': '/chapter19',
+ 'label': '19.粒子背景效果',
+ },
+ {
+ 'path': '/chapter20',
+ 'label': '20.粒子时钟',
+ },
+ {
+ 'path': '/chapter21',
+ 'label': '21.[番外]数学中的角度知识',
+ }
+ ]
+};
diff --git a/lib/navigation/router/menus/dream.dart b/lib/navigation/router/menus/dream.dart
new file mode 100644
index 0000000..ec4e69b
--- /dev/null
+++ b/lib/navigation/router/menus/dream.dart
@@ -0,0 +1,90 @@
+Map dreamMenus = {
+ 'path' : '/dream',
+ 'label' : '基础-梦始之地',
+ 'children': [
+ {
+ 'path' : '/chapter1',
+ 'label' : '1.欢迎来到 Flutter 梦始之地',
+ },
+ {
+ 'path' : '/chapter2',
+ 'label' : '2.白话引言: 语言、框架和应用',
+ },
+ {
+ 'path' : '/chapter3',
+ 'label' : '3.白话引言: 状态、行为和逻辑',
+ },
+ {
+ 'path' : '/chapter4',
+ 'label' : '4.学会说话 - 语句和量的定义',
+ },
+ {
+ 'path' : '/chapter5',
+ 'label' : '5.封装基础 - 函数方法的定义',
+ },
+ {
+ 'path' : '/chapter6',
+ 'label' : '6.万物基石 - 基本数据类型',
+ },
+ {
+ 'path' : '/chapter7',
+ 'label' : '7.逻辑桥梁 - 流程控制语句',
+ },
+ {
+ 'path' : '/chapter8',
+ 'label' : '8.逻辑血肉 - 运算符的使用',
+ },
+ {
+ 'path' : '/chapter9',
+ 'label' : '9.面向对象 - 定义与使用类',
+ },
+ {
+ 'path' : '/chapter10',
+ 'label' : '10.面向对象 - 类与类间关系',
+ },
+ {
+ 'path' : '/chapter11',
+ 'label' : '11.面向对象 - 封装、继承和多态',
+ },
+ {
+ 'path' : '/chapter12',
+ 'label' : '12.面向对象 - 抽象、接口和混入',
+ },
+ {
+ 'path' : '/chapter13',
+ 'label' : '13.语法集锦 - 类型相关其他语法',
+ },
+ {
+ 'path' : '/chapter14',
+ 'label' : '14.语法集锦 - 语言相关其他语法',
+ },
+ {
+ 'path' : '/chapter15',
+ 'label' : '15.梦始之地 - 计数器项目分析',
+ },
+ {
+ 'path' : '/chapter16',
+ 'label' : '16.梦始之地 - 组件的概念与使用',
+ },
+ {
+ 'path' : '/chapter17',
+ 'label' : '17.小试牛刀 - 秒表功能和界面分析',
+ },
+ {
+ 'path' : '/chapter18',
+ 'label' : '18.小试牛刀 - 界面交互与数据维护',
+ },
+ {
+ 'path' : '/chapter19',
+ 'label' : '19.状态管理 - 主题色与国际化切换',
+ },
+ {
+ 'path' : '/chapter20',
+ 'label' : '20.状态管理 - 局部构建和逻辑分离',
+ },
+ {
+ 'path' : '/chapter21',
+ 'label' : '21.结语 - 离开新手村,继续冒险吧,朋友!',
+ },
+ ]
+};
diff --git a/lib/navigation/router/menus/layout.dart b/lib/navigation/router/menus/layout.dart
new file mode 100644
index 0000000..1806d7f
--- /dev/null
+++ b/lib/navigation/router/menus/layout.dart
@@ -0,0 +1,70 @@
+Map layoutMenus = {
+ 'path' : '/layout',
+ 'label' : '布局-薪火相传',
+ 'children': [
+ {
+ 'path' : '/chapter1',
+ 'label' : '1.欢迎进入 Flutter 布局探索',
+ },
+ {
+ 'path' : '/chapter2',
+ 'label' : '2.从打破紧约束开始说起',
+ },
+ {
+ 'path' : '/chapter3',
+ 'label' : '3.认识常用组件下施加的约束',
+ },
+ {
+ 'path' : '/chapter4',
+ 'label' : '4.探索 Flex 对布局结构的划分',
+ },
+ {
+ 'path' : '/chapter5',
+ 'label' : '5.Flex、Wrap、Stack 组件属性梳理',
+ },
+ {
+ 'path' : '/chapter6',
+ 'label' : '6.常见单子布局组件作用分析',
+ },
+ {
+ 'path' : '/chapter7',
+ 'label' : '7.常见布局实践演练',
+ },
+ {
+ 'path' : '/chapter8',
+ 'label' : '8.探索约束传递与尺寸确定',
+ },
+ {
+ 'path' : '/chapter9',
+ 'label' : '9.探索单子布局组件源码实现(上)',
+ },
+ {
+ 'path' : '/chapter10',
+ 'label' : '10.探索单子布局组件源码实现(下)',
+ },
+ {
+ 'path' : '/chapter11',
+ 'label' : '11.探索 Flex、Wrap、Stack 源码实现',
+ },
+ {
+ 'path' : '/chapter12',
+ 'label' : '12.使用单子与多子自定义布局',
+ },
+ {
+ 'path' : '/chapter13',
+ 'label' : '13.使用 Flow 组件自定义布局',
+ },
+ {
+ 'path' : '/chapter14',
+ 'label' : '14.浮层 Overlay 的使用与定位',
+ },
+ {
+ 'path' : '/chapter15',
+ 'label' : '15.IntrinsicHeight 作用与源码实现',
+ },
+ {
+ 'path' : '/chapter16',
+ 'label' : '16.立于布局体系之上的风采',
+ },
+ ]
+};
diff --git a/lib/navigation/router/menus/menu_tree.dart b/lib/navigation/router/menus/menu_tree.dart
new file mode 100644
index 0000000..9b6b7d0
--- /dev/null
+++ b/lib/navigation/router/menus/menu_tree.dart
@@ -0,0 +1,74 @@
+import 'package:toly_menu/toly_menu.dart';
+
+import 'anima.dart';
+import 'draw.dart';
+import 'dream.dart';
+import 'layout.dart';
+import 'render.dart';
+import 'scroll.dart';
+import 'touch.dart';
+
+Map root = {
+ 'path': '',
+ 'label': '',
+ 'children': [
+ dashboard,
+ drawMenus,
+ layoutMenus,
+ dreamMenus,
+ animaMenus,
+ touchMenus,
+ scrollMenus,
+ renderMenus,
+ ]
+};
+
+Map dashboard = {
+ 'path': '/dashboard',
+ 'label': '面板总览',
+ 'children': [
+ {
+ 'path': '/view',
+ 'label': '小册全集',
+ },
+ {
+ 'path': '/chat',
+ 'label': '读者交流',
+ 'children': [
+ {
+ 'path': '/a',
+ 'label': '第一交流区',
+ },
+ {
+ 'path': '/b',
+ 'label': '第二交流区',
+ },
+ {
+ 'path': '/c',
+ 'label': '第三交流区',
+ },
+ ]
+ },
+ ],
+};
+
+MenuNode get rootMenu => parser(root, -1, '');
+
+MenuNode parser(Map data, int deep, String prefix) {
+ String path = data['path'];
+ String label = data['label'];
+ List