diff --git a/assets/app.db b/assets/app.db index 0955a802..5e5ef44d 100644 Binary files a/assets/app.db and b/assets/app.db differ diff --git a/assets/images/painterImg.jpeg b/assets/images/painterImg.jpeg new file mode 100644 index 00000000..b602c1b4 Binary files /dev/null and b/assets/images/painterImg.jpeg differ diff --git a/lib/components/full_screen_code_dialog.dart b/lib/components/full_screen_code_dialog.dart index 44af351e..1d7da872 100644 --- a/lib/components/full_screen_code_dialog.dart +++ b/lib/components/full_screen_code_dialog.dart @@ -20,6 +20,7 @@ class _FullScreenCodeDialogState extends State { @override void didChangeDependencies() { + print('widget.filePath=======${widget.filePath}'); getExampleCode(context,'${widget.filePath}', DefaultAssetBundle.of(context)) .then((String code) { if (mounted) { diff --git a/lib/resources/widget_name_to_icon.dart b/lib/resources/widget_name_to_icon.dart index 95dff598..644d145d 100644 --- a/lib/resources/widget_name_to_icon.dart +++ b/lib/resources/widget_name_to_icon.dart @@ -78,6 +78,9 @@ class WidgetName2Icon { "IconData":Icons.date_range, "IconThemeData":Icons.insert_comment, "Canvas":Icons.edit, + "PainterPath":Icons.gesture, + "CircleProgressBarPainter":Icons.av_timer, + "PainterSketch":Icons.touch_app, "Material":Icons.android, "MaterialApp":Icons.android, "MaterialButton":Icons.speaker, diff --git a/lib/utils/provider.dart b/lib/utils/provider.dart index 35a354c7..643addfa 100644 --- a/lib/utils/provider.dart +++ b/lib/utils/provider.dart @@ -59,6 +59,7 @@ class Provider { //Get a location using getDatabasesPath String databasesPath = await getDatabasesPath(); String path = join(databasesPath, 'flutter.db'); + print(path); try { db = await openDatabase(path); } catch (e) { diff --git a/lib/widgets/elements/Media/Canvas/Canvas/demo.dart b/lib/widgets/elements/Media/Canvas/Canvas/demo.dart new file mode 100644 index 00000000..24b779af --- /dev/null +++ b/lib/widgets/elements/Media/Canvas/Canvas/demo.dart @@ -0,0 +1,203 @@ +/** + * Created with Android Studio. + * User: ryan + * Date: 2019/1/20 + * Time: 上午11:34 + * email: zhu.yan@alibaba-inc.com + * tartget: Canvas 的示例 + */ +import 'package:flutter/material.dart'; +import 'dart:ui'; +import 'dart:ui' as ui; +import 'dart:typed_data'; +import 'package:flutter/services.dart' show rootBundle; + +CustomPaint graph; +var image; + +class CustomViewPage extends StatefulWidget { + + final String type; + CustomViewPage({this.type='drawLine'}) : super(); + + @override + State createState() => CustomViewPageState(); +} + +class CustomViewPageState extends State + with SingleTickerProviderStateMixin { + + static Future getImage(String asset) async { + ByteData data = await rootBundle.load(asset); + Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List()); + FrameInfo fi = await codec.getNextFrame(); + return fi.image; + } + + @override + void initState() { + super.initState(); + getImage("assets/images/painterImg.jpeg").then((data) { + setState(() { + image = data; + }); + }); + } + + @override + Widget build(BuildContext context) { + graph = CustomPaint( + painter: DrawPainter(type:widget.type) + ); + return Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.width * 0.6, + margin: EdgeInsets.all(10.0), + //padding: EdgeInsets.all(10.0), + child: graph + //child:Center(child: graph) + ); + } + + + @override + void reassemble() { + super.reassemble(); + } + + @override + void dispose() { + super.dispose(); + } +} + +///新建类继承于CustomPainter并且实现CustomPainter里面的paint()和shouldRepaint方法 +class DrawPainter extends CustomPainter { + Paint painter; + final type; + + DrawPainter ({this.type}){ + // Paint painter = Paint() + // ..color = Colors.blueAccent //画笔颜色 + // ..strokeCap = StrokeCap.round //画笔笔触类型 + // ..isAntiAlias = true //是否启动抗锯齿 + // ..blendMode = BlendMode.exclusion //颜色混合模式 + // ..style = PaintingStyle.fill //绘画风格,默认为填充 + // ..colorFilter = ColorFilter.mode(Colors.blueAccent,BlendMode.exclusion) //颜色渲染模式,一般是矩阵效果来改变的,但是flutter中只能使用颜色混合模式 + // ..maskFilter = MaskFilter.blur(BlurStyle.inner, 3.0) //模糊遮罩效果,flutter中只有这个 + // ..filterQuality = FilterQuality.high //颜色渲染模式的质量 + // ..strokeWidth = 15.0 ;//画笔的宽度 + + painter = new Paint() + ..color = Colors.blueAccent + ..strokeCap = StrokeCap.round + ..isAntiAlias = true + ..strokeWidth = 5.0 + ..filterQuality = FilterQuality.high + ..style = PaintingStyle.stroke; + } + ///Flutter中负责View绘制的地方,使用传递来的canvas和size即可完成对目标View的绘制 + + @override + void paint(Canvas canvas, Size size) { + switch(type) { + case 'drawPoints': + const List points1 = [Offset(20.0, 0.0), Offset(100.0, 50.0), Offset(150.0, 0.0),Offset(300.0, 0.0)]; + const List points2 = [Offset(20.0, 100.0), Offset(100.0, 100.0), Offset(150.0, 100.0), Offset(300.0, 100.0)]; + const List points3 = [Offset(20.0, 150.0), Offset(100.0, 150.0), Offset(150.0, 180.0), Offset(300.0, 150.0)]; + //绘制点 + canvas.drawPoints( + ///PointMode的枚举类型有三个,points(点),lines(线,隔点连接),polygon(线,相邻连接) + PointMode.points, + points1, + painter..color = Colors.redAccent // 这里可以追加修改 painter 属性 + ..strokeWidth = 10.0 + ); + canvas.drawPoints( + ///PointMode的枚举类型有三个,points(点),lines(线,隔点连接),polygon(线,相邻连接) + PointMode.lines, + points2, + painter..color = Colors.orange // 这里可以追加修改 painter 属性 + ..strokeWidth = 10.0 + ); + canvas.drawPoints( + ///PointMode的枚举类型有三个,points(点),lines(线,隔点连接),polygon(线,相邻连接) + PointMode.polygon, + points3, + painter..color = Colors.blue // 这里可以追加修改 painter 属性 + ..strokeWidth = 10.0 + ); + break; + case 'drawLine': + //绘制直线 + canvas.drawLine(Offset(20.0, 0.0), Offset(size.width*0.8, 200), painter ..color = Colors.redAccent); + break; + case 'rawCircle': + //绘制圆 参数(圆心,半径,画笔) + canvas.drawCircle( + Offset(size.width/2, 100.0), + 100.0, + painter + ..color = Colors.greenAccent + ..style = PaintingStyle.stroke //绘画风格改为stroke + ); + break; + case 'drawOval': + // 绘制椭圆 + // 使用左上和右下角坐标来确定矩形的大小和位置,椭圆是在这个矩形之中内切的形状 + Rect rect1 = Rect.fromPoints(Offset(0.0, 0.0), Offset(size.width, 200.0)); + canvas.drawOval(rect1, painter ..color = Colors.indigo); + break; + case 'drawArc': + // 绘制圆弧 + // Rect来确认圆弧的位置,还需要开始的弧度、结束的弧度、是否使用中心点绘制、以及paint弧度 + const PI = 3.1415926; + Rect rect1 = Rect.fromCircle(center: Offset(20, 50.0), radius: 100.0); + canvas.drawArc(rect1, 0.0, PI / 2, false, painter ..color = Colors.pink); + + Rect rect2 = Rect.fromCircle(center: Offset(size.width*0.6, 50.0), radius: 100.0); + canvas.drawArc(rect2, 0.0, PI / 2, true, painter ..color = Colors.deepPurple); + break; + case 'drawRRect': + /// fromPoints(Offset a, Offset b) + /// 使用左上和右下角坐标来确定矩形的大小和位置 + /// fromCircle({ Offset center, double radius }) + /// 使用圆的圆心点坐标和半径和确定外切矩形的大小和位置 + /// fromLTRB(double left, double top, double right, double bottom) + /// 使用矩形左边的X坐标、矩形顶部的Y坐标、矩形右边的X坐标、矩形底部的Y坐标来确定矩形的大小和位置 + /// fromLTWH(double left, double top, double width, double height) + /// 使用矩形左边的X坐标、矩形顶部的Y坐标矩形的宽高来确定矩形的大小和位置 + // 用Rect构建一个边长50,中心点坐标为50,100的矩形 + Rect rect1 = Rect.fromCircle(center: Offset(80.0, 100.0), radius: 50.0); + Rect rect2 = Rect.fromCircle(center: Offset(250.0, 100.0), radius: 50.0); + // 根据上面的矩形,构建一个圆角矩形 + RRect rrect1 = RRect.fromRectAndRadius(rect1, Radius.circular(0.0)); + canvas.drawRRect(rrect1, painter); + RRect rrect2 = RRect.fromRectAndRadius(rect2, Radius.circular(20.0)); + canvas.drawRRect(rrect2, painter); + break; + case 'drawDRRect': + //绘制两个矩形 + Rect rect1 = Rect.fromCircle(center: Offset(size.width/2, 100.0), radius: 60.0); + Rect rect2 = Rect.fromCircle(center: Offset(size.width/2, 100.0), radius: 40.0); + //分别绘制外部圆角矩形和内部的圆角矩形 + RRect outer = RRect.fromRectAndRadius(rect1, Radius.circular(30.0)); + RRect inner = RRect.fromRectAndRadius(rect2, Radius.circular(5.0)); + canvas.drawDRRect(outer, inner, painter ..color = Colors.lime); + break; + case 'drawImage': + // canvas.drawImage(image, Offset(0.0, 0.0), painter); + final src = Rect.fromLTWH(0.0, 0.0, 684.0, 442.0); + final dst = Rect.fromLTWH(0.0, 0.0, size.width, size.height); + canvas.drawImageRect(image, src, dst, painter); + break; + } + //canvas.drawColor(Colors.red, BlendMode.colorDodge); + } + + ///控制自定义View是否需要重绘的,返回false代表这个View在构建完成后不需要重绘。 + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return false; + } +} diff --git a/lib/widgets/elements/Media/Canvas/Canvas/index.dart b/lib/widgets/elements/Media/Canvas/Canvas/index.dart new file mode 100644 index 00000000..c56588c6 --- /dev/null +++ b/lib/widgets/elements/Media/Canvas/Canvas/index.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_go/components/widget_demo.dart'; +import './demo.dart' as demoBoxs; + +const Text = ''' +### **简介** +> 用于操作图形的界面; +- canvas 对象用于创建图片对象,这些对象本身可以与 SceneBuilder 一起用于构建场景; +'''; +const Text1 = ''' +### **基本用法** +- 它可以使用“平移”、“缩放”、“旋转”、“倾斜”和“变换”方法进行修改; +- 可以使用 clipRect、clipCorrect 和 clipPath 方法进行修改; +- 可以使用由 save、savelayer和 restore 方法管理的堆栈来保存和还原当前的转换和剪辑。 +- 以下是绘制点,线,面的基本用法 +'''; + +const Text2 = ''' +> 绘制点 +- 绘制点有三种模式, points(点),lines(线,隔点连接),polygon(线,相邻连接) +'''; + +const Text3 = ''' +> 绘制直线 +'''; + +const Text4 = ''' +> 绘制圆 +'''; + +const Text5 = ''' +> 绘制椭圆 +- 使用左上和右下角坐标来确定矩形的大小和位置,椭圆是在这个矩形之中内切的形状 +'''; + +const Text6 = ''' +> 绘制圆弧 +- Rect 来确认圆弧的位置,还需要开始的弧度、结束的弧度、是否使用中心点绘制、以及 paint 弧度 +'''; + +const Text7 = ''' +> 绘制矩形,圆角矩形 +- 用 Rect构建矩形 +- 根据上面的矩形,构建一个圆角矩形 +'''; + +const Text8 = ''' +> 绘制两个相套矩形 +'''; + +const Text9 = ''' +> 绘制图片到canvas +'''; + +class Demo extends StatefulWidget { + static const String routeName = '/element/Media/Canvas/PainterPath'; + + _DemoState createState() => _DemoState(); +} + +class _DemoState extends State { + @override + Widget build(BuildContext context) { + return WidgetDemo( + title: 'Canvas', + codeUrl: 'elements/Media/Canvas/Canvas/demo.dart', + contentList: [ + Text, + Text1, + Text2, + demoBoxs.CustomViewPage(type:'drawPoints'), + Text3, + demoBoxs.CustomViewPage(type:'drawLine'), + Text4, + demoBoxs.CustomViewPage(type:'rawCircle'), + Text5, + demoBoxs.CustomViewPage(type:'drawOval'), + Text6, + demoBoxs.CustomViewPage(type:'drawArc'), + Text7, + demoBoxs.CustomViewPage(type:'drawRRect'), + Text8, + demoBoxs.CustomViewPage(type:'drawDRRect'), + Text9, + demoBoxs.CustomViewPage(type:'drawImage') + ], + docUrl: 'https://docs.flutter.io/flutter/dart-ui/Canvas-class.html', + ); + } +} diff --git a/lib/widgets/elements/Media/Canvas/CircleProgressBarPainter/demo.dart b/lib/widgets/elements/Media/Canvas/CircleProgressBarPainter/demo.dart new file mode 100644 index 00000000..ce87e4cc --- /dev/null +++ b/lib/widgets/elements/Media/Canvas/CircleProgressBarPainter/demo.dart @@ -0,0 +1,103 @@ +/** + * Created with Android Studio. + * User: ryan + * Date: 2019/1/20 + * Time: 上午11:34 + * email: zhu.yan@alibaba-inc.com + * tartget: CircleProgressBarPainter 的示例 + */ +import 'dart:ui'; +import 'package:flutter/material.dart'; + +class CustomViewPage extends StatefulWidget { + @override + State createState() => CustomViewPageState(); +} + +class CustomViewPageState extends State + with SingleTickerProviderStateMixin { + Animation _doubleAnimation; + AnimationController _controller; + CurvedAnimation curvedAnimation; + + @override + void initState() { + super.initState(); + _controller = + AnimationController(vsync: this, duration: Duration(seconds: 2)); + curvedAnimation = + CurvedAnimation(parent: _controller, curve: Curves.decelerate); + _doubleAnimation = Tween(begin: 0.0, end: 360.0).animate(_controller); + + _controller.addListener(() { + this.setState(() {}); + }); + onAnimationStart(); + } + + @override + Widget build(BuildContext context) { + return Container( + width: 100.0, + height: 100.0, + margin: EdgeInsets.all(8.0), + child: CustomPaint( + child: Center( + child: Text((_doubleAnimation.value / 3.6).round().toString())), + painter: CircleProgressBarPainter(_doubleAnimation.value) + ), + ); + } + + void onAnimationStart() { + _controller.forward(from: 0.0); + } + + @override + void reassemble() { + super.reassemble(); + onAnimationStart(); + } + + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } +} + +class CircleProgressBarPainter extends CustomPainter { + Paint _paintBackground; + Paint _paintFore; + final double pi = 3.1415926; + var jindu; + + CircleProgressBarPainter(this.jindu) { + _paintBackground = Paint() + ..color = Colors.grey + ..strokeCap = StrokeCap.round + ..style = PaintingStyle.stroke + ..strokeWidth = 10.0 + ..isAntiAlias = true; + _paintFore = Paint() + ..color = Colors.red + ..strokeCap = StrokeCap.round + ..style = PaintingStyle.stroke + ..strokeWidth = 10.0 + ..isAntiAlias = true; + } + @override + void paint(Canvas canvas, Size size) { + canvas.drawCircle(Offset(size.width / 2, size.height / 2), size.width / 2,_paintBackground); + Rect rect = Rect.fromCircle( + center: Offset(size.width / 2, size.height / 2), + radius: size.width / 2, + ); + canvas.drawArc(rect, 0.0, jindu * 3.14 / 180, false, _paintFore); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return false; + } +} \ No newline at end of file diff --git a/lib/widgets/elements/Media/Canvas/CircleProgressBarPainter/index.dart b/lib/widgets/elements/Media/Canvas/CircleProgressBarPainter/index.dart new file mode 100644 index 00000000..df054258 --- /dev/null +++ b/lib/widgets/elements/Media/Canvas/CircleProgressBarPainter/index.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_go/components/widget_demo.dart'; +import './demo.dart' as demoBoxs; + +const Text = ''' +### **简介** +> 操作图形的界面; + +'''; +const Text1 = ''' +### **基本用法** +- canvas + Animation 实现一个 loading 效果; +'''; + + +class Demo extends StatefulWidget { + static const String routeName = '/element/Media/Canvas/CircleProgressBarPainter'; + + _DemoState createState() => _DemoState(); +} + +class _DemoState extends State { + @override + Widget build(BuildContext context) { + return WidgetDemo( + title: 'Canvas', + codeUrl: 'elements/Media/Canvas/CircleProgressBarPainter/demo.dart', + contentList: [ + Text, + Text1, + demoBoxs.CustomViewPage() + ], + docUrl: 'https://docs.flutter.io/flutter/dart-ui/Canvas-class.html', + ); + } +} + diff --git a/lib/widgets/elements/Media/Canvas/PainterPath/demo.dart b/lib/widgets/elements/Media/Canvas/PainterPath/demo.dart new file mode 100644 index 00000000..150da6b2 --- /dev/null +++ b/lib/widgets/elements/Media/Canvas/PainterPath/demo.dart @@ -0,0 +1,180 @@ +/** + * Created with Android Studio. + * User: ryan + * Date: 2019/1/20 + * Time: 上午11:34 + * email: zhu.yan@alibaba-inc.com + * tartget: PainterPath 的示例 + */ +import 'dart:ui'; +import 'package:flutter/material.dart'; +CustomPaint graph; + +class CustomViewPage extends StatefulWidget { + + final String type; + CustomViewPage({this.type='simpleline'}) : super(); + + @override + State createState() => CustomViewPageState(); +} + +class CustomViewPageState extends State + with SingleTickerProviderStateMixin { + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + graph = CustomPaint( + painter: DrawPainter(type:widget.type) + ); + return Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.width * 0.6, + margin: EdgeInsets.all(50.0), + //padding: EdgeInsets.all(10.0), + child: graph + //child:Center(child: graph) + ); + } + + + @override + void reassemble() { + super.reassemble(); + } + + @override + void dispose() { + super.dispose(); + } +} + +///新建类继承于CustomPainter并且实现CustomPainter里面的paint()和shouldRepaint方法 +class DrawPainter extends CustomPainter { + Paint painter; + final type; + + DrawPainter ({this.type}){ + // Paint painter = Paint() + // ..color = Colors.blueAccent //画笔颜色 + // ..strokeCap = StrokeCap.round //画笔笔触类型 + // ..isAntiAlias = true //是否启动抗锯齿 + // ..blendMode = BlendMode.exclusion //颜色混合模式 + // ..style = PaintingStyle.fill //绘画风格,默认为填充 + // ..colorFilter = ColorFilter.mode(Colors.blueAccent,BlendMode.exclusion) //颜色渲染模式,一般是矩阵效果来改变的,但是flutter中只能使用颜色混合模式 + // ..maskFilter = MaskFilter.blur(BlurStyle.inner, 3.0) //模糊遮罩效果,flutter中只有这个 + // ..filterQuality = FilterQuality.high //颜色渲染模式的质量 + // ..strokeWidth = 15.0 ;//画笔的宽度 + + painter = new Paint() + ..color = Colors.blueAccent + ..strokeCap = StrokeCap.round + ..isAntiAlias = true + ..strokeWidth = 5.0 + ..style = PaintingStyle.stroke; + } + ///Flutter中负责View绘制的地方,使用传递来的canvas和size即可完成对目标View的绘制 + + @override + void paint(Canvas canvas, Size size) { + //canvas.drawColor(Colors.red, BlendMode.colorDodge); + Path path = new Path(); + drawThisPath(canvas, size, path); + path.close(); + canvas.drawPath(path, painter); + } + + void drawThisPath(Canvas canvas, Size size, Path path,) { + switch(type) { + case 'simpleline': + //新建了一个path,然后将路径起始点移动到坐标(100,100)的位置 + Path path = new Path()..moveTo(0.0, 0.0); + path.lineTo(200.0, 200.0); + canvas.drawPath(path, painter); + break; + case 'polyline': + Path path = new Path()..moveTo(100.0, 10.0); + + path.lineTo(200.0, 150.0); + path.lineTo(100.0, 200.0); + + canvas.drawPath(path, painter); + break; + case 'Besizerline2': + Path path = new Path()..moveTo(0.0, 0.0); + Rect rect1 = Rect.fromCircle(center: Offset(50.0, 100.0), radius: 60.0); + path.arcTo(rect1, 0.0, 3.14, false); + canvas.drawPath(path, painter); + + Rect rect2 = Rect.fromCircle(center: Offset(200.0, 100.0), radius: 60.0); + path.arcTo(rect2, 0.0, 3.14*2, true); + canvas.drawPath(path, painter); + break; + case 'Besizerline3': + var width = size.width; + var height = 300; + Path path = new Path()..moveTo(width / 2, height / 4); + path.cubicTo((width * 6) / 7, height / 9, (width * 13) / 13, + (height * 2) / 5, width / 2, (height * 7) / 12); + canvas.drawPath(path, painter + // ..style = PaintingStyle.fill + // ..color = Colors.red + ); + + Path path2 = new Path(); + path2.moveTo(width / 2, height / 4); + path2.cubicTo(width / 7, height / 9, width / 21, (height * 2) / 5, + width / 2, (height * 7) / 12); + canvas.drawPath(path2, painter); + break; + case 'drawArc': + // 绘制圆弧 + // Rect来确认圆弧的位置,还需要开始的弧度、结束的弧度、是否使用中心点绘制、以及paint弧度 + const PI = 3.1415926; + Rect rect1 = Rect.fromCircle(center: Offset(size.width/2, 0.0), radius: 100.0); + canvas.drawArc(rect1, 0.0, PI / 2, false, painter ..color = Colors.pink); + + Rect rect2 = Rect.fromCircle(center: Offset(size.width/2, 150.0), radius: 100.0); + canvas.drawArc(rect2, 0.0, PI / 2, true, painter ..color = Colors.deepPurple); + break; + case 'drawRRect': + /// fromPoints(Offset a, Offset b) + /// 使用左上和右下角坐标来确定矩形的大小和位置 + /// fromCircle({ Offset center, double radius }) + /// 使用圆的圆心点坐标和半径和确定外切矩形的大小和位置 + /// fromLTRB(double left, double top, double right, double bottom) + /// 使用矩形左边的X坐标、矩形顶部的Y坐标、矩形右边的X坐标、矩形底部的Y坐标来确定矩形的大小和位置 + /// fromLTWH(double left, double top, double width, double height) + /// 使用矩形左边的X坐标、矩形顶部的Y坐标矩形的宽高来确定矩形的大小和位置 + // 用Rect构建一个边长50,中心点坐标为50,100的矩形 + Rect rect1 = Rect.fromCircle(center: Offset(50.0, 50.0), radius: 50.0); + Rect rect2 = Rect.fromCircle(center: Offset(200.0, 50.0), radius: 50.0); + // 根据上面的矩形,构建一个圆角矩形 + RRect rrect1 = RRect.fromRectAndRadius(rect1, Radius.circular(0.0)); + canvas.drawRRect(rrect1, painter); + RRect rrect2 = RRect.fromRectAndRadius(rect2, Radius.circular(20.0)); + canvas.drawRRect(rrect2, painter); + break; + case 'drawDRRect': + //绘制两个矩形 + Rect rect1 = Rect.fromCircle(center: Offset(size.width/2, 100.0), radius: 60.0); + Rect rect2 = Rect.fromCircle(center: Offset(size.width/2, 100.0), radius: 40.0); + //分别绘制外部圆角矩形和内部的圆角矩形 + RRect outer = RRect.fromRectAndRadius(rect1, Radius.circular(30.0)); + RRect inner = RRect.fromRectAndRadius(rect2, Radius.circular(5.0)); + canvas.drawDRRect(outer, inner, painter ..color = Colors.lime); + break; + } + } + + ///控制自定义View是否需要重绘的,返回false代表这个View在构建完成后不需要重绘。 + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return false; + } +} diff --git a/lib/widgets/elements/Media/Canvas/PainterPath/index.dart b/lib/widgets/elements/Media/Canvas/PainterPath/index.dart new file mode 100644 index 00000000..ae837e31 --- /dev/null +++ b/lib/widgets/elements/Media/Canvas/PainterPath/index.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_go/components/widget_demo.dart'; +import './demo.dart' as demoBoxs; + +//const Text = ''' +//### **简介** +//> 在 canvas 上绘制时使用的样式说明; +//- canvas 上的大多数API都使用一个绘画对象来描述用于该操作的样式。 +//'''; +const Text = ''' +### **简介** +> 在 canvas 上绘制的图案; +- canvas + paint 的应用。 +'''; + +const Text1 = ''' +### **基本用法** +- canvas 的 painter 的自定义绘制线的方法; +'''; + +const Text2 = ''' +> 绘制简单直线 +'''; + +const Text3 = ''' +> 绘制折线 +'''; + +const Text4 = ''' +> 二阶贝塞尔曲线 +'''; + +const Text5 = ''' +> 三阶贝塞尔曲线 +'''; + + +class Demo extends StatefulWidget { + static const String routeName = '/element/Media/Canvas/Canvas'; + + _DemoState createState() => _DemoState(); +} + +class _DemoState extends State { + @override + Widget build(BuildContext context) { + return WidgetDemo( + title: 'PainterPath', + codeUrl: 'elements/Media/Canvas/PainterPath/demo.dart', + contentList: [ + Text, + Text1, + Text2, + demoBoxs.CustomViewPage(type:'simpleline'), + Text3, + demoBoxs.CustomViewPage(type:'polyline'), + Text4, + demoBoxs.CustomViewPage(type:'Besizerline2'), + Text5, + demoBoxs.CustomViewPage(type:'Besizerline3'), + ], + docUrl: 'https://docs.flutter.io/flutter/dart-ui/Paint-class.html', + ); + } +} diff --git a/lib/widgets/elements/Media/Canvas/PainterSketch/demo.dart b/lib/widgets/elements/Media/Canvas/PainterSketch/demo.dart new file mode 100644 index 00000000..52b5f856 --- /dev/null +++ b/lib/widgets/elements/Media/Canvas/PainterSketch/demo.dart @@ -0,0 +1,213 @@ +/** + * Created with Android Studio. + * User: ryan + * Date: 2019/1/20 + * Time: 上午11:34 + * email: zhu.yan@alibaba-inc.com + * tartget: PainterSketchDome 的示例 + */ + +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; + +class PainterSketchDome extends StatefulWidget { + PainterSketchDome({Key key, this.title}) : super(key: key); + + final String title; + + @override + _PainterSketchDomeState createState() => new _PainterSketchDomeState(); +} + +class _PainterSketchDomeState extends State { + + List lines = []; + List nowPoints = []; + Color nowColor = Colors.redAccent; + + void moveGestureDetector(DragUpdateDetails detail){ + RenderBox box = context.findRenderObject(); + final Offset xy = box.globalToLocal(detail.globalPosition);// 重要需要转换以下坐标位置 + Offset p = Offset(xy.dx, xy.dy - 60); + //Offset p = Offset(detail.globalPosition.dx, detail.globalPosition.dy - 60); + setState(() { + nowPoints.add(p); + }); + } + + void newGestureDetector(DragStartDetails detail) { + if (nowPoints.length != 0) { + LinePoints l = LinePoints(new List.from(nowPoints), nowColor); + lines.add(l); + nowPoints.clear(); + } + RenderBox box = context.findRenderObject(); + final Offset xy = box.globalToLocal(detail.globalPosition);// 重要需要转换以下坐标位置 + Offset p = Offset(xy.dx, xy.dy - 60); + //Offset p = Offset(detail.globalPosition.dx, detail.globalPosition.dy - 60); + setState(() { + nowPoints.add(p); + }); + } + + void changeColor (Color c){ + if (nowPoints.length != 0) { + LinePoints l = LinePoints(new List.from(nowPoints), nowColor); + lines.add(l); + } + setState(() { + nowPoints.clear(); + nowColor = c; + }); + } + + List colors = [ + Colors.redAccent, + Colors.pink, + Colors.greenAccent, + Colors.blueAccent, + Colors.amber, + Colors.purpleAccent, + Colors.deepPurpleAccent, + Colors.lightBlueAccent, + Colors.lightGreenAccent, + Colors.cyanAccent,]; + + void _tapClear(){ + setState(() { + lines.clear(); + nowPoints.clear(); + }); + } + + @override + Widget build(BuildContext context) { + List pallet = []; + for (int i = 0; i < colors.length; i++) { + Color c = colors[i]; + pallet.add(ColorPallet(color: c,changeColor: changeColor,isSelect: c==nowColor,)); + } + + return SizedBox( + width: MediaQuery.of(context).size.width * 0.9, + height: MediaQuery.of(context).size.height * 0.6, + child:new Scaffold( + primary: false, + body: new Container( + decoration: BoxDecoration( + color: Colors.white + ), + child:new Flex( + direction: Axis.vertical, + children: [ + Container( + decoration:BoxDecoration( + color: Colors.black12 + ), + child: ListView( + scrollDirection: Axis.horizontal, + children: pallet + , + ), + height: 60.0, + ), + Expanded( + child: AspectRatio( + aspectRatio: 1.0, + child: GestureDetector( + child: CustomPaint( + painter: PaintCanvas(lines,nowPoints,nowColor), + ), + onHorizontalDragUpdate: moveGestureDetector, + onVerticalDragUpdate: moveGestureDetector, + onHorizontalDragStart: newGestureDetector, + onVerticalDragStart: newGestureDetector, + ), + ), + ) + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _tapClear, + backgroundColor: Colors.redAccent, + foregroundColor: Colors.white, + child: Icon(Icons.delete), + ), + ) + ); + } +} + +class PaintCanvas extends CustomPainter{ + + final List lines; + final List nowPoints; + final Color nowColor; + + PaintCanvas(this.lines, this.nowPoints, this.nowColor); + + @override + void paint(Canvas canvas, Size size) { + Paint p = new Paint() + ..color = Colors.redAccent + ..strokeCap = StrokeCap.round + ..strokeWidth = 5.0; + canvas.save(); + for (int i = 0; i < lines.length; i++) { + LinePoints l = lines[i]; + for (int j = 1; j < l.points.length; j++){ + Offset p1 = l.points[j - 1]; + Offset p2 = l.points[j]; + p.color = l.lineColor; + canvas.drawLine(p1, p2, p); + } + } + for (int i = 1; i < nowPoints.length; i++){ + Offset p1 = nowPoints[i - 1]; + Offset p2 = nowPoints[i]; + p.color = nowColor; + canvas.drawLine(p1, p2, p); + } + + canvas.restore(); + } + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return true; + } +} + +class LinePoints{ + final List points; + final Color lineColor; + LinePoints(this.points, this.lineColor); +} + +class ColorPallet extends StatelessWidget { + final Color color; + final Function changeColor; + const ColorPallet({Key key, this.color, this.changeColor, this.isSelect}) : super(key: key); + final bool isSelect; + + void onPressed(){ + changeColor(color); + } + + @override + Widget build(BuildContext context) { + return new RawMaterialButton( + onPressed: onPressed, + constraints: BoxConstraints(minWidth: 60.0,minHeight: 50.0), + child: new Container( + margin: EdgeInsets.only(top: 5.0,bottom: 5.0), + width: 50.0, + height: 50.0, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.all(Radius.circular(25.0)), + border: Border.all(color: Colors.white,width: isSelect?3.0:0.0) + ), + )) ; + } +} \ No newline at end of file diff --git a/lib/widgets/elements/Media/Canvas/PainterSketch/index.dart b/lib/widgets/elements/Media/Canvas/PainterSketch/index.dart new file mode 100644 index 00000000..f6a744e8 --- /dev/null +++ b/lib/widgets/elements/Media/Canvas/PainterSketch/index.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_go/components/widget_demo.dart'; +import './demo.dart' as demoBoxs; + +const Text = ''' +### **简介** +> 操作图形的界面; + +'''; +const Text1 = ''' +### **基本用法** +- canvas + paint + GestureDetector 实现一个 简易的画板; +'''; + + +class Demo extends StatefulWidget { + static const String routeName = '/element/Media/Canvas/PainterSketch'; + + _DemoState createState() => _DemoState(); +} + +class _DemoState extends State { + @override + Widget build(BuildContext context) { + return WidgetDemo( + title: 'Canvas', + codeUrl: 'elements/Media/Canvas/PainterSketch/demo.dart', + contentList: [ + Text, + Text1, + demoBoxs.PainterSketchDome() + ], + docUrl: 'https://docs.flutter.io/flutter/dart-ui/Paint-class.html', + ); + } +} + diff --git a/lib/widgets/elements/Media/Canvas/index.dart b/lib/widgets/elements/Media/Canvas/index.dart index e3e60ec0..d3c73227 100644 --- a/lib/widgets/elements/Media/Canvas/index.dart +++ b/lib/widgets/elements/Media/Canvas/index.dart @@ -1 +1,31 @@ -// import 'package:flutter/material.dart'; +import 'package:flutter_go/model/widget.dart'; +import "package:flutter/material.dart"; + +import 'PainterSketch/index.dart' as PainterSketch; +import 'Canvas/index.dart' as Canvas; +import 'PainterPath/index.dart' as PainterPath; +import 'CircleProgressBarPainter/index.dart' as CircleProgressBarPainter; + + +List widgetPoints = [ + WidgetPoint( + name: 'PainterSketch', + routerName: PainterSketch.Demo.routeName, + buildRouter: (BuildContext context) => PainterSketch.Demo(), + ), + WidgetPoint( + name: 'Canvas', + routerName: Canvas.Demo.routeName, + buildRouter: (BuildContext context) => Canvas.Demo(), + ), + WidgetPoint( + name: 'PainterPath', + routerName: PainterPath.Demo.routeName, + buildRouter: (BuildContext context) => PainterPath.Demo(), + ), + WidgetPoint( + name: 'CircleProgressBarPainter', + routerName: CircleProgressBarPainter.Demo.routeName, + buildRouter: (BuildContext context) => CircleProgressBarPainter.Demo(), + ) +]; diff --git a/lib/widgets/elements/Media/index.dart b/lib/widgets/elements/Media/index.dart index c11673ed..3933301f 100644 --- a/lib/widgets/elements/Media/index.dart +++ b/lib/widgets/elements/Media/index.dart @@ -6,10 +6,12 @@ */ import 'Image/index.dart' as Image; import 'Icon/index.dart' as Icon; +import 'Canvas/index.dart' as Canvas; List getWidgets() { List result = []; result.addAll(Image.widgetPoints); result.addAll(Icon.widgetPoints); + result.addAll(Canvas.widgetPoints); return result; } \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index b929ba36..80a965eb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -159,6 +159,10 @@ flutter: - lib/widgets/elements/Media/Image/paintImage/paint_image_demo.dart - lib/widgets/elements/Media/Image/precacheImage/precache_image_demo.dart - lib/widgets/elements/Media/Image/RawImage/raw_image_demo.dart + - lib/widgets/elements/Media/Canvas/Canvas/demo.dart + - lib/widgets/elements/Media/Canvas/CircleProgressBarPainter/demo.dart + - lib/widgets/elements/Media/Canvas/PainterPath/demo.dart + - lib/widgets/elements/Media/Canvas/PainterSketch/demo.dart - lib/widgets/themes/Material/MaterialApp/demo.dart - lib/widgets/themes/Material/MaterialButton/demo.dart - lib/widgets/themes/Material/MaterialColor/demo.dart