import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:lszlgl/base/base_lifecycle_state.dart'; import 'dart:ui' as ui; import 'package:lszlgl/model/rsp/stock_points_rsp.dart'; import 'package:lszlgl/network/my_api.dart'; class StockPointsWidget extends StatefulWidget { final double width; final double length; final double height; final double kWidth; final double kHeight; const StockPointsWidget( {super.key, required this.width, required this.length, required this.height, required this.kWidth, required this.kHeight}); @override State createState() => _StockPointsWidgetState(); } class _StockPointsWidgetState extends BaseLifecycleState { List? listData; double kLength = 0; // 画布长度 double bili = 0; // 实际坐标米数 转换到屏幕上的坐标点 比例 double sWidth = 0; @override void onInit() { // 强制横屏 SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight, ]); getStockPoints(); } @override void onDestroy() { SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); } void getStockPoints() async { var res = await MyApi.get().stockPoints( width: widget.width, length: widget.length, height: widget.height, // partitionSize: 200, randomOffset: true, offsetRange: 0.5, ); if(widget.width<=30){ kLength = (widget.length / widget.width) * widget.kWidth; bili = widget.kWidth / widget.width; sWidth = widget.kWidth; }else{ kLength = (widget.length / widget.width) * widget.kHeight; bili = widget.kHeight / widget.width; sWidth = widget.kHeight; } setState(() { listData = res.data; }); } @override Widget build(BuildContext context) { return myScaffold( child: Column( children: [ myAppBar(title: '扦样布点示意图',toolbarHeight: 32), Expanded( child: Container( color: Colors.white, width: double.infinity, child: listData != null ? SingleChildScrollView( padding: const EdgeInsets.symmetric(vertical: 20,horizontal: 10), child: Column( mainAxisSize: MainAxisSize.min, children: [ CustomPaint( size: Size(sWidth, kLength), painter: CustomXYPainter(bili: bili, xyzList: listData!), ), // const SizedBox(height: 12), Text('房式仓 ${widget.width}m * ${widget.length}m',style:const TextStyle(fontSize: 22),), const SizedBox(height: 42), CustomPaint( size: Size((widget.kWidth/3)*2, (widget.kWidth/3)*2), painter: CustomZPainter(xyzList: listData!,height: widget.height), ), const SizedBox(height: 12), Text('房式仓分层取样示意图-高度${widget.height}m',style:const TextStyle(fontSize: 22)), ], ), ) :const Center(child: CircularProgressIndicator()), ) ), ], ) ); } } class CustomXYPainter extends CustomPainter { final double bili; final List xyzList; CustomXYPainter({super.repaint, required this.bili, required this.xyzList}); @override void paint(Canvas canvas, Size size) { Paint p = Paint(); p.style = PaintingStyle.stroke; p.strokeWidth = 1.6; p.color = Colors.black; // 实际仓库 Rect rect = Rect.fromLTRB(0, 0, size.width, size.height); canvas.drawRect(rect, p); // 内部灰色 0.5米 扦样区域 p.strokeWidth = 1; p.color = Colors.grey; double pad = 0.5 * bili; Rect rectSmall = Rect.fromLTWH(pad, pad, size.width - bili, size.height - bili); canvas.drawRect(rectSmall, p); StockPointsRsp first = xyzList.first; // int c = first.partitionsY!.toInt(); int c = first.partitionY!.toInt(); if(c>1){ // y方向分区 for(int i=1; i< c; i++){ canvas.drawLine(Offset(first.partitionWidth! *i *bili , 0), Offset(first.partitionWidth! *i *bili, size.height), p); } } // 随机点 List pl = []; for (int i = 0; i < xyzList.length; i++) { StockPointsRsp point = xyzList[i]; double offX = point.x! * bili; double offY = point.y! * bili; pl.add(Offset(offX, offY)); var textPainter = TextPainter( text: TextSpan(text: '$i', style: const TextStyle(fontSize: 8, color: Colors.black)), textDirection: TextDirection.ltr, ); textPainter.layout(); // 进行布局 if (offX + 16 >= size.width - 0.5 * bili) { textPainter.paint(canvas, Offset(offX - 14, offY - 4)); } else { textPainter.paint(canvas, Offset(offX + 4, offY - 4)); } } p.strokeWidth = 4; p.color = Colors.red; canvas.drawPoints(ui.PointMode.points, pl, p); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => this != oldDelegate; } /// class CustomZPainter extends CustomPainter { final List xyzList; final double height; // 仓库高度 CustomZPainter({super.repaint, required this.xyzList, required this.height}); @override void paint(Canvas canvas, Size size) { Paint p = Paint(); p.style = PaintingStyle.stroke; p.strokeWidth = 1.6; p.color = Colors.black; canvas.drawLine(const Offset(0, 0), Offset(size.width, 0), p); canvas.drawLine(const Offset(54, 0), Offset(54, size.height), p); canvas.drawLine(Offset(0, size.height), Offset(size.width, size.height), p); // 右边高度 p.strokeWidth = 1; p.color = Colors.grey; canvas.drawLine(Offset(size.width-20, 0), Offset(size.width-20, size.height), p); var textPainter = TextPainter( text: TextSpan(text: '$height米', style: const TextStyle(fontSize: 10, color: Colors.black)), textDirection: TextDirection.ltr, ); textPainter.layout(); textPainter.paint(canvas, Offset(size.width-12, (size.height/2)-7)); var textPainterBot = TextPainter( text:const TextSpan(text: '地坪', style: TextStyle(fontSize: 10, color: Colors.black)), textDirection: TextDirection.ltr, ); textPainterBot.layout(); textPainterBot.paint(canvas, Offset(size.width+2, size.height-8)); var textPainterTop = TextPainter( text:const TextSpan(text: '粮面', style: TextStyle(fontSize: 10, color: Colors.black)), textDirection: TextDirection.ltr, ); textPainterTop.layout(); textPainterTop.paint(canvas, Offset(size.width+2, -8)); p.strokeCap= StrokeCap.round; p.strokeWidth = 6; p.color = Colors.black; List pl = []; double bili = size.height / height ; List layers = xyzList.first.layers!; layers.sort(); for(int i = 0; i < layers.length; i++){ double lay = layers[i]!; String mi = (height-lay).toStringAsFixed(2); double offY = double.parse((lay *bili).toStringAsFixed(2)); pl.add(Offset(54, offY)); var textPainterTop = TextPainter( text:TextSpan(text: '第${i+1}层$mi米', style:const TextStyle(fontSize: 8, color: Colors.black)), textDirection: TextDirection.ltr, ); textPainterTop.layout(); textPainterTop.paint(canvas, Offset(0, offY-7)); } canvas.drawPoints(ui.PointMode.points, pl, p); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return false; } }