点击放大后锁定罗盘

This commit is contained in:
cxc
2022-07-20 17:33:21 +08:00
parent 610c9b1750
commit 9e46ff0c30
2 changed files with 218 additions and 52 deletions

View File

@ -1,9 +1,76 @@
import 'dart:async';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class GridClipPaint extends StatelessWidget { // class GridClipPaint extends StatelessWidget {
const GridClipPaint({Key key}) : super(key: key); // const GridClipPaint(
// this.left,
// this.top,
// this.right,
// this.bottom, {
// Key key,
// }) : super(key: key);
//
// // ui.Image image;
// final double left;
// final double top;
// final double right;
// final double bottom;
//
// @override
// Widget build(BuildContext context) {
// ui.Image image;
// return Container(
// color: Colors.transparent,
// alignment: Alignment.center,
// child: CustomPaint(
// // 使用CustomPaint 背景画板
// painter: ClipPainter(image),
// ),
// );
// }
// }
class GridClipPaint extends StatefulWidget {
const GridClipPaint(this.image, this.left, this.top, this.right, this.bottom,
{Key key})
: super(key: key);
final ui.Image image;
final double left;
final double top;
final double right;
final double bottom;
@override
State<GridClipPaint> createState() => _GridClipPaintState();
}
class _GridClipPaintState extends State<GridClipPaint> {
ui.Image image;
@override
void initState() async {
// TODO: implement initState
// final appDataDirectory = await getApplicationDocumentsDirectory();
// File file = File(join(appDataDirectory.path, 'rotate_image'));
super.initState();
}
Future<ui.Image> imageLoader() {
ImageStream imageStream = const AssetImage("assets/images/arrow.png")
.resolve(ImageConfiguration(size: Size(700, 700)));
Completer<ui.Image> imageCompleter = Completer<ui.Image>();
void imageListener(ImageInfo info, bool synchronousCall) {
ui.Image image = info.image;
imageCompleter.complete(image);
imageStream.removeListener(ImageStreamListener(imageListener));
}
imageStream.addListener(ImageStreamListener(imageListener));
return imageCompleter.future;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -12,32 +79,37 @@ class GridClipPaint extends StatelessWidget {
alignment: Alignment.center, alignment: Alignment.center,
child: CustomPaint( child: CustomPaint(
// 使用CustomPaint 背景画板 // 使用CustomPaint 背景画板
painter: ClipPainter(), painter: ClipPainter(image),
), ),
); );
} }
} }
class ClipPainter extends CustomPainter { class ClipPainter extends CustomPainter {
ui.Image image; final ui.Image image;
final double left;
final double top;
final double right;
final double bottom;
ClipPainter(this.image,
{this.left = 0.3, this.top = 0.3, this.right = 0.6, this.bottom = 0.6});
@override @override
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
// 创建画笔 // TODO: implement paint
final Paint paint = Paint(); Paint paint = Paint();
canvas.drawImageRect( canvas.drawImageRect(
image, image,
// Image(image: AssetImage("assets/images/arrow.png")), Rect.fromLTRB(image.width * left, image.height * top,
Rect.fromLTRB(0, 0, 700 / 3, 700 / 3), image.width * right, image.height * bottom),
Rect.fromLTWH(0, 0, 700 / 3, 700 / 3), Rect.fromLTWH(0, 0, size.width, size.height),
paint); paint);
// ..color = Colors.white
// ..strokeWidth = 2;
// 绘制线
// canvas.drawLine(const Offset(-400, 0), const Offset(400, 0), paintLine);
// canvas.drawLine(const Offset(0, 500), const Offset(0, -440), paintLine);
} }
@override @override
bool shouldRepaint(CustomPainter oldDelegate) => false; bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return false;
}
} }

View File

@ -1,18 +1,23 @@
import 'dart:async'; import 'dart:async';
import 'dart:io' as io;
import 'dart:math'; import 'dart:math';
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:fengshui_compass/components/cross_paint.dart'; import 'package:fengshui_compass/components/cross_paint.dart';
import 'package:fengshui_compass/components/my_icon.dart'; import 'package:fengshui_compass/components/my_icon.dart';
import 'package:fengshui_compass/pages/login_page.dart'; import 'package:fengshui_compass/pages/login_page.dart';
import 'package:fengshui_compass/states/region.dart'; import 'package:fengshui_compass/states/region.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_serial_port_api/flutter_serial_port_api.dart'; import 'package:flutter_serial_port_api/flutter_serial_port_api.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:stream_transform/stream_transform.dart'; import 'package:stream_transform/stream_transform.dart';
import '../components/grid_clip_paint.dart';
import '../components/region_selector.dart'; import '../components/region_selector.dart';
import '../states/compass_image.dart'; import '../states/compass_image.dart';
import '../utils/recv_parse.dart'; import '../utils/recv_parse.dart';
@ -317,6 +322,9 @@ class _CompassState extends State<CompassPage> {
return result; return result;
} }
double _scale = 1.0; // 放大倍数
Offset _origin = Offset(0.0, 0.0); // 放大原点
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
@ -372,24 +380,31 @@ class _CompassState extends State<CompassPage> {
width: 700, width: 700,
height: 700, height: 700,
child: Stack( child: Stack(
// fit: StackFit.loose,
children: [ children: [
Transform.rotate( ClipRect(
child: Transform.scale(
scale: _scale,
origin: _origin,
child: Transform.rotate(
angle: getCorrectionAngle((myaw + angle: getCorrectionAngle((myaw +
regionProvider.declination)) * regionProvider.declination)) *
2 * 2 *
pi / pi /
360, 360,
child: ClipOval(
child: Image( child: Image(
width: 700, width: 700,
height: 700, height: 700,
// alignment: Alignment.lerp(a, b, t),
// image: compassImageProvider.rotateImage,
image: compassImageProvider image: compassImageProvider
.rotateImage ?? .rotateImage ??
const AssetImage( const AssetImage(
"assets/images/compass_rotated.png"), "assets/images/compass_rotated.png"),
fit: BoxFit.contain), fit: BoxFit.contain),
), ),
),
),
),
Align( Align(
alignment: FractionalOffset(w_x, w_y), alignment: FractionalOffset(w_x, w_y),
child: const Image( child: const Image(
@ -403,35 +418,106 @@ class _CompassState extends State<CompassPage> {
children: List.generate( children: List.generate(
9, 9,
(index) => Container( (index) => Container(
decoration: BoxDecoration( // decoration: BoxDecoration(
border: Border( // border: Border(
bottom: // bottom:
const BorderSide(width: 1), // const BorderSide(width: 1),
right: // right:
const BorderSide(width: 1), // const BorderSide(width: 1),
left: index % 3 == 0 // left: index % 3 == 0
? const BorderSide(width: 1) // ? const BorderSide(width: 1)
: BorderSide.none, // : BorderSide.none,
top: index <= 2 // top: index <= 2
? const BorderSide(width: 1) // ? const BorderSide(width: 1)
: BorderSide.none), // : BorderSide.none),
color: const Color.fromRGBO( // color: const Color.fromRGBO(
233, 233, 233, 0.3)), // 233, 233, 233, 0.3)),
height: 700 / 3, height: 700 / 3,
width: 700 / 3, width: 700 / 3,
child: GestureDetector( child: GestureDetector(
child: Text('grid $index'), // child: Text('grid $index'),
onDoubleTap: () {
setState(() {
_scale = 1.0;
});
},
onTap: () { onTap: () {
Fluttertoast.showToast( if (isLock) {
msg: 'index: $index', return;
backgroundColor: Colors.green, }
textColor: Colors.white, setState(() {
fontSize: 20.0); switch (index) {
case 0:
_origin =
const Offset(-350, -350);
break;
case 1:
_origin =
const Offset(0, -350);
break;
case 2:
_origin =
const Offset(350, -350);
break;
case 3:
_origin =
const Offset(-350, 0);
break;
case 4:
_origin = const Offset(0, 0);
break;
case 5:
_origin =
const Offset(350, 0);
break;
case 6:
_origin =
const Offset(-350, 350);
break;
case 7:
_origin =
const Offset(0, 350);
break;
case 8:
_origin =
const Offset(350, 350);
break;
}
_scale = 3;
switchCompass();
// isLock = true;
});
}, },
), ),
), ),
), ),
),
// ClipRRect(
// borderRadius: BorderRadius.circular(225.0),
// child: Image(
// width: 700,
// height: 700,
// // alignment: Alignment.lerp(a, b, t),
// // image: compassImageProvider.rotateImage,
// image: compassImageProvider
// .rotateImage ??
// const AssetImage(
// "assets/images/compass_rotated.png"),
// fit: BoxFit.contain),
// )
ClipRect(
child: Image(
width: 700,
height: 700,
color: Colors.red,
// alignment: Alignment.lerp(a, b, t),
// image: compassImageProvider.rotateImage,
image: const AssetImage(
"assets/images/compass_rotated.png"),
fit: BoxFit.contain),
clipper: MyClipper(),
) )
// GridClipPaint(0,0,1,2)
], ],
), ),
), ),
@ -605,3 +691,11 @@ class _CompassState extends State<CompassPage> {
); );
} }
} }
class MyClipper extends CustomClipper<Rect> {
@override
Rect getClip(Size size) => Rect.fromLTWH(0.0, 0.0, 100.0, 100.0);
@override
bool shouldReclip(CustomClipper<Rect> oldClipper) => false;
}