2022-06-27 09:51:30 +08:00
|
|
|
|
import 'dart:async';
|
|
|
|
|
import 'dart:math';
|
2022-06-27 17:37:25 +08:00
|
|
|
|
import 'dart:typed_data';
|
2022-06-27 09:51:30 +08:00
|
|
|
|
|
2022-06-27 17:37:25 +08:00
|
|
|
|
import 'package:fengshui_compass/components/cross_paint.dart';
|
2022-06-27 09:51:30 +08:00
|
|
|
|
import 'package:fengshui_compass/components/my_icon.dart';
|
|
|
|
|
import 'package:fengshui_compass/pages/login_page.dart';
|
2022-06-27 17:37:25 +08:00
|
|
|
|
import 'package:fengshui_compass/states/region.dart';
|
2022-06-27 09:51:30 +08:00
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
import 'package:flutter_serial_port_api/flutter_serial_port_api.dart';
|
2022-07-05 16:44:07 +08:00
|
|
|
|
import 'package:image_picker/image_picker.dart';
|
|
|
|
|
import 'package:path_provider/path_provider.dart';
|
2022-06-27 17:37:25 +08:00
|
|
|
|
import 'package:provider/provider.dart';
|
2022-06-27 09:51:30 +08:00
|
|
|
|
import 'package:stream_transform/stream_transform.dart';
|
|
|
|
|
|
2022-06-27 17:37:25 +08:00
|
|
|
|
import '../components/region_selector.dart';
|
2022-07-05 16:44:07 +08:00
|
|
|
|
import '../states/compass_image.dart';
|
2022-06-27 09:51:30 +08:00
|
|
|
|
import '../utils/recv_parse.dart';
|
|
|
|
|
|
|
|
|
|
class CompassPage extends StatefulWidget {
|
|
|
|
|
const CompassPage({Key key}) : super(key: key);
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
State<StatefulWidget> createState() => _CompassState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _CompassState extends State<CompassPage> {
|
|
|
|
|
// 串口相关
|
|
|
|
|
bool isPortOpened = false;
|
|
|
|
|
SerialPort _serialPort;
|
|
|
|
|
StreamSubscription _subscription;
|
|
|
|
|
|
|
|
|
|
// 传感器状态
|
|
|
|
|
bool isLock = true;
|
|
|
|
|
bool isUpClose = true;
|
|
|
|
|
bool isSideClose = true;
|
|
|
|
|
|
|
|
|
|
double w_x = 0.5;
|
|
|
|
|
double w_y = 0.5;
|
2022-06-27 17:37:25 +08:00
|
|
|
|
|
2022-06-27 09:51:30 +08:00
|
|
|
|
// 与磁北极夹角
|
|
|
|
|
double myaw = 0.0;
|
|
|
|
|
|
|
|
|
|
String distance = "";
|
|
|
|
|
|
|
|
|
|
var lista = [];
|
|
|
|
|
var listb = [];
|
|
|
|
|
var listc = [];
|
|
|
|
|
|
2022-07-05 16:44:07 +08:00
|
|
|
|
//从相册选择的图片名称
|
|
|
|
|
String selectedImageName;
|
|
|
|
|
|
2022-06-27 17:37:25 +08:00
|
|
|
|
void initDevice() {}
|
2022-06-27 09:51:30 +08:00
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void initState() {
|
|
|
|
|
super.initState();
|
|
|
|
|
initPort();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> initPort() async {
|
|
|
|
|
// 20ms接收一次串口数据,防抖,定义接收缓存
|
|
|
|
|
final debounceTransformer = StreamTransformer<Uint8List, dynamic>.fromBind(
|
|
|
|
|
(s) => s.transform(debounceBuffer(const Duration(milliseconds: 20))));
|
|
|
|
|
|
|
|
|
|
if (!isPortOpened) {
|
|
|
|
|
Device theDevice = Device("/dev/ttyS2", "/dev/ttyS2");
|
|
|
|
|
var serialPort = await FlutterSerialPortApi.createSerialPort(
|
|
|
|
|
theDevice, 115200,
|
|
|
|
|
parity: 0, dataBits: 8, stopBit: 1);
|
|
|
|
|
|
|
|
|
|
bool openResult = await serialPort.open();
|
|
|
|
|
setState(() {
|
|
|
|
|
_serialPort = serialPort;
|
|
|
|
|
isPortOpened = openResult;
|
|
|
|
|
});
|
|
|
|
|
await openRange();
|
|
|
|
|
|
|
|
|
|
_subscription = _serialPort.receiveStream
|
|
|
|
|
.transform(debounceTransformer)
|
|
|
|
|
.listen((recv) {
|
|
|
|
|
// recvData - 9E01040100000000000000065E
|
|
|
|
|
String recvData = formatReceivedData(recv);
|
|
|
|
|
print("Receive format: $recvData");
|
|
|
|
|
parsingRecvCom(recvData);
|
|
|
|
|
// 解析收到的结果,得到陀螺、地磁、测距结果
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
await openCompass();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> closePort() async {
|
|
|
|
|
bool closeResult = await _serialPort.close();
|
|
|
|
|
setState(() {
|
|
|
|
|
isPortOpened = !closeResult;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> openCompass() async {
|
|
|
|
|
print("compass open");
|
|
|
|
|
_serialPort
|
|
|
|
|
.write(Uint8List.fromList(hexToUnits("7E01020100000000000000010D0A")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> closeCompass() async {
|
|
|
|
|
print("compass close");
|
|
|
|
|
_serialPort
|
|
|
|
|
.write(Uint8List.fromList(hexToUnits("7E01020000000000000000010D0A")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> openSideLaser() async {
|
|
|
|
|
print("side open");
|
|
|
|
|
_serialPort
|
|
|
|
|
.write(Uint8List.fromList(hexToUnits("7E01010100000000000000010D0A")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> closeSideLaser() async {
|
|
|
|
|
print("side close");
|
|
|
|
|
_serialPort
|
|
|
|
|
.write(Uint8List.fromList(hexToUnits("7E01010000000000000000010D0A")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> openUpLaser() async {
|
|
|
|
|
_serialPort
|
|
|
|
|
.write(Uint8List.fromList(hexToUnits("7e01010300000000000000010d0a")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> closeUpLaser() async {
|
|
|
|
|
_serialPort
|
|
|
|
|
.write(Uint8List.fromList(hexToUnits("7e01010200000000000000010d0a")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> openRange() async {
|
|
|
|
|
_serialPort
|
|
|
|
|
.write(Uint8List.fromList(hexToUnits("7e01040100000000000000010d0a")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> raging() async {
|
|
|
|
|
if (!isLock) {
|
|
|
|
|
switchCompass();
|
|
|
|
|
}
|
|
|
|
|
_serialPort
|
|
|
|
|
.write(Uint8List.fromList(hexToUnits("7e01040200000000000000010d0a")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> switchCompass() async {
|
|
|
|
|
if (isLock) {
|
|
|
|
|
await openCompass();
|
|
|
|
|
} else {
|
|
|
|
|
await closeCompass();
|
|
|
|
|
setState(() {
|
|
|
|
|
w_x = 0.5;
|
|
|
|
|
w_y = 0.5;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
setState(() {
|
|
|
|
|
isLock = !isLock;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loginAction() {
|
|
|
|
|
Navigator.push(
|
2022-06-27 17:37:25 +08:00
|
|
|
|
context, MaterialPageRoute(builder: (context) => LoginPage()));
|
2022-06-27 09:51:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parsingRecvCom(str) {
|
|
|
|
|
if (str.contains("9E010201") &&
|
|
|
|
|
(str.length > (str.indexOf("9E010201") + 50))) {
|
|
|
|
|
var roll_l = hexToInt(str.substring(8, 10));
|
|
|
|
|
var roll_h = hexToInt(str.substring(10, 12));
|
|
|
|
|
var pitch_l = hexToInt(str.substring(12, 14));
|
|
|
|
|
var pitch_h = hexToInt(str.substring(14, 16));
|
|
|
|
|
// var yaw_l = hexToInt(str.substring(16, 18));
|
|
|
|
|
// var yaw_h = hexToInt(str.substring(18, 20));
|
|
|
|
|
|
|
|
|
|
var pos = str.indexOf("9E010301");
|
|
|
|
|
// var mx_h = hexToInt(str.substring(pos+8, pos+10));
|
|
|
|
|
// var mx_l = hexToInt(str.substring(pos+10, pos+12));
|
|
|
|
|
// var my_h = hexToInt(str.substring(pos+12, pos+14));
|
|
|
|
|
|
2022-06-27 17:37:25 +08:00
|
|
|
|
var myaw_flag = hexToInt(str.substring(pos + 14, pos + 16));
|
|
|
|
|
var myaw_h = hexToInt(str.substring(pos + 16, pos + 18));
|
|
|
|
|
var myaw_l = hexToInt(str.substring(pos + 18, pos + 20));
|
2022-06-27 09:51:30 +08:00
|
|
|
|
|
2022-06-27 17:37:25 +08:00
|
|
|
|
var roll_tmp = (roll_h * 256 + roll_l) * 180 / 32768;
|
|
|
|
|
var pitch_tmp = (pitch_h * 256 + pitch_l) * 180 / 32768;
|
2022-06-27 09:51:30 +08:00
|
|
|
|
// var yaw = (yaw_h * 256 + yaw_l) * 180 /32768;
|
|
|
|
|
|
|
|
|
|
// -180~180
|
|
|
|
|
var ff = myaw_flag == 1 ? -1 : 1;
|
2022-06-27 17:37:25 +08:00
|
|
|
|
var temp_myaw = (myaw_h * 256 + myaw_l) * 0.01 * ff + 180;
|
2022-06-27 09:51:30 +08:00
|
|
|
|
|
2022-06-27 17:37:25 +08:00
|
|
|
|
if (roll_tmp > 180) roll_tmp = roll_tmp - 360;
|
|
|
|
|
if (pitch_tmp > 180) pitch_tmp = pitch_tmp - 360;
|
2022-06-27 09:51:30 +08:00
|
|
|
|
|
|
|
|
|
var w_x_tmp = 0.0;
|
|
|
|
|
var w_y_tmp = 0.0;
|
|
|
|
|
|
|
|
|
|
// 倾角<30度
|
2022-06-27 17:37:25 +08:00
|
|
|
|
var w_total = sqrt(
|
|
|
|
|
roll_tmp.abs() * roll_tmp.abs() + pitch_tmp.abs() * pitch_tmp.abs());
|
2022-06-27 09:51:30 +08:00
|
|
|
|
|
|
|
|
|
if (w_total <= 30) {
|
|
|
|
|
w_y_tmp = 0.5 - 0.07 * roll_tmp / 30.0;
|
|
|
|
|
w_x_tmp = 0.5 - 0.07 * pitch_tmp / 30.0;
|
|
|
|
|
} else if (w_total > 30) {
|
|
|
|
|
//todo
|
2022-06-27 17:37:25 +08:00
|
|
|
|
w_y_tmp = 0.5 - 0.07 * w_total / 30.0;
|
2022-06-27 09:51:30 +08:00
|
|
|
|
w_x_tmp = 0.5 - 0.07 * w_total / 30.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// todo 其他情况
|
|
|
|
|
|
|
|
|
|
var meanValue;
|
|
|
|
|
|
|
|
|
|
if (lista.length < 20) {
|
|
|
|
|
lista.add(temp_myaw);
|
|
|
|
|
meanValue = null;
|
|
|
|
|
} else {
|
|
|
|
|
lista.removeAt(0);
|
|
|
|
|
lista.add(temp_myaw);
|
2022-06-27 17:37:25 +08:00
|
|
|
|
meanValue = lista.map((e) => e).reduce((a, b) => a + b) / lista.length;
|
2022-06-27 09:51:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
// print("roll: $roll_tmp pitch: $pitch_tmp");
|
|
|
|
|
// print("w_x: $w_x_tmp, w_y: $w_y_tmp");
|
|
|
|
|
// if (meanValue != null) {
|
|
|
|
|
// myaw = meanValue;
|
|
|
|
|
// } else {
|
|
|
|
|
// myaw = 0;
|
|
|
|
|
// }
|
|
|
|
|
myaw = temp_myaw;
|
|
|
|
|
|
|
|
|
|
w_x = w_x_tmp;
|
|
|
|
|
w_y = w_y_tmp;
|
|
|
|
|
|
|
|
|
|
// 水平仪 0.5+-0.07范围
|
|
|
|
|
// x旋转y在动 y旋转x在动 roll改变y坐标,pitch改变x坐标
|
|
|
|
|
});
|
|
|
|
|
} else if (str.contains("9E010401") &&
|
|
|
|
|
(str.length >= ((str.indexOf("9E010401") + 26)))) {
|
|
|
|
|
var pos = str.indexOf("9E010401");
|
|
|
|
|
int rh = hexToInt(str.substring(pos + 16, pos + 18));
|
|
|
|
|
int rl = hexToInt(str.substring(pos + 18, pos + 20));
|
|
|
|
|
int result = rh * 256 + rl;
|
|
|
|
|
print("测距$result");
|
|
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
distance = (result.toDouble() / 1000).toStringAsFixed(2);
|
|
|
|
|
});
|
|
|
|
|
} else {}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-27 17:37:25 +08:00
|
|
|
|
// 拼接城市
|
|
|
|
|
String spliceCityName(String pname, String cname) {
|
|
|
|
|
if (pname == '') return '未选择城市';
|
|
|
|
|
StringBuffer sb = StringBuffer();
|
|
|
|
|
sb.write(pname);
|
|
|
|
|
if (cname == '') return sb.toString();
|
|
|
|
|
sb.write(' - ');
|
|
|
|
|
sb.write(cname);
|
|
|
|
|
return sb.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// bool strEmpty(String? value) {
|
|
|
|
|
// if (value == null) return true;
|
|
|
|
|
// return value.trim().isEmpty;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
selectRegion() {
|
|
|
|
|
showDialog(
|
|
|
|
|
context: context,
|
|
|
|
|
builder: (BuildContext context) {
|
|
|
|
|
return AlertDialog(
|
2022-06-30 17:01:04 +08:00
|
|
|
|
title: const Text('选择城市校准磁偏角'),
|
2022-06-27 17:37:25 +08:00
|
|
|
|
content: RegionSelector(),
|
|
|
|
|
actions: <Widget>[
|
2022-06-28 16:21:47 +08:00
|
|
|
|
TextButton(
|
|
|
|
|
onPressed: () {
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
},
|
|
|
|
|
child: const Text('关闭')),
|
2022-06-27 17:37:25 +08:00
|
|
|
|
TextButton(
|
|
|
|
|
onPressed: () {
|
|
|
|
|
Provider.of<RegionProvider>(context, listen: false)
|
|
|
|
|
.saveRegion();
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
},
|
|
|
|
|
child: const Text('保存'))
|
|
|
|
|
],
|
|
|
|
|
);
|
|
|
|
|
}).then((value) {
|
|
|
|
|
Provider.of<RegionProvider>(context, listen: false).resetTemp();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-05 16:44:07 +08:00
|
|
|
|
void initCompassImage() async {
|
|
|
|
|
final directory =
|
|
|
|
|
await getApplicationDocumentsDirectory(); // AppData directory
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-27 09:51:30 +08:00
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
return Container(
|
2022-06-27 17:37:25 +08:00
|
|
|
|
decoration: const BoxDecoration(
|
|
|
|
|
image: DecorationImage(
|
|
|
|
|
image: AssetImage("assets/images/bg.png"), fit: BoxFit.cover)),
|
|
|
|
|
child: Scaffold(
|
|
|
|
|
backgroundColor: Colors.transparent,
|
|
|
|
|
appBar: AppBar(
|
2022-06-27 09:51:30 +08:00
|
|
|
|
backgroundColor: Colors.transparent,
|
2022-06-27 17:37:25 +08:00
|
|
|
|
elevation: 0,
|
|
|
|
|
centerTitle: true,
|
|
|
|
|
title: const Text(
|
|
|
|
|
'定盘星',
|
|
|
|
|
style: TextStyle(color: Colors.white),
|
2022-06-27 09:51:30 +08:00
|
|
|
|
),
|
2022-06-27 17:37:25 +08:00
|
|
|
|
leading: IconButton(
|
|
|
|
|
color: Colors.amber,
|
|
|
|
|
icon: Icon(isLock ? MyIcons.icon_mima : MyIcons.icon_jiesuo),
|
|
|
|
|
onPressed: switchCompass,
|
|
|
|
|
),
|
|
|
|
|
actions: [
|
|
|
|
|
//todo
|
|
|
|
|
// 更改背景图
|
|
|
|
|
IconButton(
|
|
|
|
|
color: Colors.amber,
|
|
|
|
|
icon: const Icon(
|
|
|
|
|
Icons.person,
|
|
|
|
|
size: 22,
|
|
|
|
|
),
|
|
|
|
|
onPressed: loginAction,
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
body: SafeArea(
|
|
|
|
|
child: ConstrainedBox(
|
|
|
|
|
constraints: const BoxConstraints(minHeight: 600),
|
2022-07-05 09:46:51 +08:00
|
|
|
|
child: Consumer<RegionProvider>(
|
|
|
|
|
builder: (builder, regionProvider, child) {
|
2022-07-05 16:44:07 +08:00
|
|
|
|
return Consumer<CompassImageProvider>(
|
|
|
|
|
builder: (builder, compassImageProvider, child) {
|
|
|
|
|
return Stack(
|
|
|
|
|
alignment: Alignment.center,
|
|
|
|
|
children: [
|
|
|
|
|
// 罗盘
|
|
|
|
|
Column(
|
|
|
|
|
children: [
|
|
|
|
|
const Padding(padding: EdgeInsets.only(top: 145)),
|
|
|
|
|
Row(
|
|
|
|
|
children: [
|
|
|
|
|
Spacer(flex: 1),
|
|
|
|
|
Container(
|
|
|
|
|
width: 700,
|
|
|
|
|
height: 700,
|
|
|
|
|
child: Stack(
|
|
|
|
|
children: [
|
|
|
|
|
Transform.rotate(
|
|
|
|
|
angle: (myaw + regionProvider.declination) *
|
|
|
|
|
2 *
|
|
|
|
|
pi /
|
|
|
|
|
360,
|
|
|
|
|
child: Image(
|
|
|
|
|
width: 700,
|
|
|
|
|
height: 700,
|
|
|
|
|
// alignment: Alignment.bottomLeft,
|
|
|
|
|
// image: compassImageProvider.rotateImage,
|
|
|
|
|
image: compassImageProvider
|
|
|
|
|
.rotateImage ??
|
|
|
|
|
const AssetImage(
|
|
|
|
|
"assets/images/compass_rotated.png"),
|
|
|
|
|
fit: BoxFit.contain),
|
|
|
|
|
),
|
|
|
|
|
Align(
|
|
|
|
|
alignment: FractionalOffset(w_x, w_y),
|
|
|
|
|
child: const Image(
|
|
|
|
|
image:
|
|
|
|
|
AssetImage("assets/images/water.png"),
|
|
|
|
|
),
|
2022-07-05 09:46:51 +08:00
|
|
|
|
),
|
2022-07-05 16:44:07 +08:00
|
|
|
|
CrossPaint(),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
const Spacer(flex: 1),
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
// 最上面一行, lock azimuth login
|
|
|
|
|
Positioned(
|
|
|
|
|
top: 5,
|
|
|
|
|
child: Column(
|
|
|
|
|
children: [
|
|
|
|
|
const Image(
|
|
|
|
|
width: 15,
|
|
|
|
|
height: 15,
|
|
|
|
|
image: AssetImage("assets/images/arrow.png"),
|
|
|
|
|
fit: BoxFit.contain,
|
|
|
|
|
),
|
|
|
|
|
Text(
|
|
|
|
|
// "${azimuth.toStringAsFixed(2)}",
|
|
|
|
|
(myaw + regionProvider.declination)
|
|
|
|
|
.toStringAsFixed(2),
|
|
|
|
|
style: const TextStyle(
|
|
|
|
|
color: Colors.amber, fontSize: 36),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
)),
|
|
|
|
|
//磁偏角调整按钮
|
|
|
|
|
Positioned(
|
|
|
|
|
top: 5,
|
|
|
|
|
right: 8,
|
|
|
|
|
child: IconButton(
|
|
|
|
|
onPressed: () => selectRegion(),
|
|
|
|
|
icon: const Icon(Icons.settings, color: Colors.amber),
|
|
|
|
|
)),
|
|
|
|
|
Positioned(
|
|
|
|
|
top: 5,
|
|
|
|
|
left: 8,
|
|
|
|
|
child: IconButton(
|
|
|
|
|
onPressed: () {
|
|
|
|
|
ImagePicker()
|
|
|
|
|
.pickImage(source: ImageSource.gallery)
|
|
|
|
|
.then((res) {
|
|
|
|
|
if (res == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compassImageProvider.setSelectedRotateImage(res);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
icon: const Icon(Icons.photo, color: Colors.amber),
|
|
|
|
|
)),
|
|
|
|
|
// 最下面一行,ranging value openlaser
|
|
|
|
|
Positioned(
|
|
|
|
|
bottom: 80,
|
|
|
|
|
left: 50,
|
|
|
|
|
child: IconButton(
|
|
|
|
|
onPressed: raging,
|
|
|
|
|
icon: const Icon(
|
|
|
|
|
MyIcons.icon_celiang,
|
|
|
|
|
size: 34,
|
|
|
|
|
),
|
|
|
|
|
color: Colors.amber)),
|
|
|
|
|
const Positioned(
|
|
|
|
|
width: 180,
|
|
|
|
|
height: 90,
|
|
|
|
|
bottom: 60,
|
|
|
|
|
child: Image(
|
|
|
|
|
image: AssetImage("assets/images/range_input.png"),
|
|
|
|
|
fit: BoxFit.contain,
|
|
|
|
|
)),
|
|
|
|
|
Positioned(
|
|
|
|
|
width: 180,
|
|
|
|
|
height: 90,
|
|
|
|
|
bottom: 60,
|
|
|
|
|
child: Align(
|
|
|
|
|
alignment: Alignment.centerRight,
|
|
|
|
|
child: Padding(
|
|
|
|
|
padding: const EdgeInsets.only(right: 15),
|
|
|
|
|
child: Text(
|
|
|
|
|
"${distance} m",
|
|
|
|
|
style: const TextStyle(
|
|
|
|
|
color: Colors.amber, fontSize: 28),
|
2022-06-27 17:37:25 +08:00
|
|
|
|
),
|
2022-07-05 09:46:51 +08:00
|
|
|
|
),
|
2022-07-05 16:44:07 +08:00
|
|
|
|
)),
|
|
|
|
|
|
|
|
|
|
Positioned(
|
|
|
|
|
bottom: 60,
|
|
|
|
|
right: 40,
|
|
|
|
|
height: 120,
|
|
|
|
|
width: 100,
|
2022-07-05 09:46:51 +08:00
|
|
|
|
child: Column(
|
2022-07-05 16:44:07 +08:00
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
2022-07-05 09:46:51 +08:00
|
|
|
|
children: [
|
2022-07-05 16:44:07 +08:00
|
|
|
|
IconButton(
|
|
|
|
|
color: Colors.amber,
|
|
|
|
|
onPressed: () {
|
|
|
|
|
if (isUpClose) {
|
|
|
|
|
openUpLaser();
|
|
|
|
|
} else {
|
|
|
|
|
closeUpLaser();
|
|
|
|
|
}
|
|
|
|
|
setState(() {
|
|
|
|
|
isUpClose = !isUpClose;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
icon: Icon(
|
|
|
|
|
isUpClose
|
|
|
|
|
? MyIcons.icon_shangdeng
|
|
|
|
|
: MyIcons.icon_shangdnegguanbi,
|
|
|
|
|
size: 36)),
|
|
|
|
|
IconButton(
|
|
|
|
|
color: Colors.amber,
|
|
|
|
|
onPressed: () {
|
|
|
|
|
if (isSideClose) {
|
|
|
|
|
openSideLaser();
|
|
|
|
|
} else {
|
|
|
|
|
closeSideLaser();
|
|
|
|
|
}
|
|
|
|
|
setState(() {
|
|
|
|
|
isSideClose = !isSideClose;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
icon: Icon(
|
|
|
|
|
isSideClose
|
|
|
|
|
? MyIcons.icon_zuoyoudneg
|
|
|
|
|
: MyIcons.icon_zuoyoudengguanbi,
|
|
|
|
|
size: 32,
|
|
|
|
|
))
|
2022-07-05 09:46:51 +08:00
|
|
|
|
],
|
2022-07-05 16:44:07 +08:00
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
],
|
|
|
|
|
);
|
|
|
|
|
});
|
2022-07-05 09:46:51 +08:00
|
|
|
|
},
|
2022-06-27 17:37:25 +08:00
|
|
|
|
),
|
|
|
|
|
)),
|
|
|
|
|
),
|
|
|
|
|
);
|
2022-06-27 09:51:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|