import 'dart:math'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../styles/theme.dart'; const _textHeight = 45.0; class Compass2 extends StatelessWidget { static const levelMin = 1; static const levelMax = 5; const Compass2( {super.key, this.compassRadians, required this.mapNorthRadians, this.nextPointRadians, required this.level, required this.showDegrees, required this.diameter, this.nextPointImage, this.nextPointHeight, this.degreeColor, this.plantSrc, }); final double diameter; final int level; /// 指南针方向 final double? compassRadians; /// 地图北的方向 final double mapNorthRadians; /// 下一点方向 final double? nextPointRadians; /// 显示度数 final int showDegrees; final Widget? nextPointImage; final double? nextPointHeight; final Color? degreeColor; final String? plantSrc; @override Widget build(BuildContext context) { return SizedBox( width: diameter, height: diameter, child: Stack( alignment: Alignment.center, children: [ Container( decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.white.withAlpha(125)), width: diameter- _textHeight, height: diameter- _textHeight, ), Transform.rotate(angle: mapNorthRadians, child: SizedBox( width: diameter - _textHeight, height: diameter - _textHeight, child:_Compass(level: level, src: plantSrc), ),), nextPointRadians != null? Transform.rotate(angle: nextPointRadians!, child: SizedBox( width: diameter - _textHeight - diameter * 0.3, height: nextPointHeight?? diameter - _textHeight - diameter * 0.3, child: nextPointImage?? Image.asset('assets/images/im_compass_next_arrow.png', fit: BoxFit.fitHeight), )): const SizedBox(), compassRadians != null? Transform.rotate(angle: compassRadians!, child: SizedBox( width: diameter - _textHeight, height: diameter - _textHeight, child: Image.asset('assets/images/im_compass_arrow.png', height: context.height, width: context.width, fit: BoxFit.fill), ),): const SizedBox(), level < levelMax ? SizedBox( width: diameter, height: diameter, child: _MapNorthArrow(showDegrees, degreeColor), ): const SizedBox(), ], ) ) ; } } class _MapNorthArrow extends StatelessWidget{ const _MapNorthArrow(this.degrees, this.degreeColor); final int degrees; final Color? degreeColor; @override Widget build(BuildContext context) { return Column( children: [ SizedBox( height: _textHeight, child: Column( children:[ Text(' $degrees°', style: TextStyle(fontSize: 12, color: degreeColor??Colors.black)), CustomPaint(painter: _MapNorthArrowPainter(), size: const Size(10, 10),) , ] ), ), const Spacer(), ], ); } } class _MapNorthArrowPainter extends CustomPainter { final painter = Paint() ..color = Colors.black; final path = Path(); @override void paint(Canvas canvas, Size size) { final centerX = size.width/2; path.moveTo(centerX-2, 0); path.lineTo(centerX+2, 0); path.lineTo(centerX, size.height); path.close(); canvas.drawPath(path, painter); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; } class _Compass extends StatelessWidget{ const _Compass({required this.level, required this.src}); final int level; final String? src; @override Widget build(BuildContext context) { String? plantSrc; switch(level){ case 1: plantSrc = 'assets/images/im_compass_1.png'; break; case 2: plantSrc = 'assets/images/im_compass_2.png'; break; case 3: plantSrc = 'assets/images/im_compass_3.png'; break; case 4: plantSrc = 'assets/images/im_compass_4.png'; break; default: break; } if(src != null){ plantSrc = src; } final children = []; if(plantSrc!= null){ children.add( Image.asset(plantSrc, height: context.height, width: context.width, fit: BoxFit.fill) ); } return Stack( children: children, ); } } void main() async { runApp(GetMaterialApp( theme: appThemeData(), home: Container( width: double.infinity, height: double.infinity, color: Colors.white, alignment: Alignment.center, child: Compass2( compassRadians: pi/2, mapNorthRadians: 0, level: 1, nextPointRadians: -pi/2, showDegrees: 100, diameter: 160, )))); }