| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- import 'dart:math';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import '../styles/theme.dart';
- import 'package:sensor/sensor.dart' as sensor;
- class Compass extends StatelessWidget {
- const Compass(
- {super.key,
- required this.compassRadians,
- required this.mapNorthRadians,
- required this.orientation,
- required this.diameter,
- this.nextPointRadians
- });
- final double diameter;
- final double compassRadians;
- final double mapNorthRadians;
- final sensor.Orientation orientation;
- final double? nextPointRadians;
- int getDegrees(){
- var d = (mapNorthRadians-compassRadians)*180~/pi;
- while(d < 0){
- d+=360;
- }
- while(d > 360){
- d-=360;
- }
- return d;
- }
- @override
- Widget build(BuildContext context) {
- return Stack(
- children: [
- Transform.rotate(angle: compassRadians, child: SizedBox(
- width: diameter,
- height: diameter,
- child: CustomPaint(painter: _ArrowPainter()),
- ),),
- Transform.rotate(angle: mapNorthRadians, child: SizedBox(
- width: diameter,
- height: diameter,
- child: CustomPaint(painter: _PlatePainter()),
- )),
- nextPointRadians != null? Transform.rotate(angle: nextPointRadians!, child: SizedBox(
- width: diameter,
- height: diameter,
- child: CustomPaint(painter: _NextPointArrowPainter()),
- )): const SizedBox(),
- SizedBox(
- width: diameter,
- height: diameter,
- child: CustomPaint(painter: _OrientationPainter(orientation)),
- ),
- Container(
- width: diameter,
- alignment: Alignment.topCenter,
- padding: const EdgeInsets.only(top: 30),
- child: Text(' ${getDegrees()}°'))
- ],
- );
- }
- }
- void drawArrow(Canvas canvas, Paint painter, Offset topCenter){
- final path = Path();
- var x = topCenter.dx;
- var y = topCenter.dy;
- path.moveTo(x, y);
- x += 5;
- y +=10;
- path.lineTo(x, y);
- x -= 5;
- y -= 2;
- path.lineTo(x, y);
- x -= 5;
- y += 2;
- path.lineTo(x, y);
- path.close();
- painter.style = PaintingStyle.fill;
- canvas.drawPath(path, painter);
- }
- class _ArrowPainter extends CustomPainter {
- var textPainter = TextPainter();
- final painter = Paint();
- @override
- void paint(Canvas canvas, Size size) {
- var radius = size.height / 2 - 4;
- painter.isAntiAlias = true;
- painter.style = PaintingStyle.stroke;
- painter.color = const Color(0x5eaff59f);
- final center = Offset(size.height / 2, size.width / 2);
- final centerX = center.dx;
- final centerY = center.dy;
- canvas.drawCircle(center, radius, painter);
- radius -= 3;
- painter.style = PaintingStyle.fill;
- painter.color = Colors.white.withAlpha(120);
- canvas.drawCircle(center, radius, painter);
- painter.color = const Color(0xff92b686);
- painter.strokeWidth = 0.5;
- painter.style = PaintingStyle.stroke;
- textPainter = TextPainter(
- textDirection: TextDirection.ltr,
- textAlign: TextAlign.center,
- );
- double angle = 0;
- const padding = 4;
- for (int i = 0; i < 360; i += 5) {
- angle = (i-90) * pi / 180;
- var start = Offset(
- centerX + (radius - padding - 5) * cos(angle),
- centerY + (radius - padding - 5) * sin(angle),
- );
- var end = Offset(
- centerX + (radius - padding) * cos(angle),
- centerY + (radius - padding) * sin(angle),
- );
- if (i % 30 == 0) {
- start = Offset(
- centerX + (radius - padding - 8) * cos(angle),
- centerY + (radius - padding - 8) * sin(angle),
- );
- // String label = "$i";
- // textPainter.text = TextSpan(
- // text: label,
- // style: const TextStyle(
- // color: Colors.black,
- // fontSize: 8,
- // fontWeight: FontWeight.w100,
- // ),
- // );
- // textPainter.layout();
- // Offset labelOffset =
- // Offset(
- // start.dx - 10 * cos(angle) - textPainter.width / 2,
- // start.dy - 10 * sin(angle) - textPainter.height / 2);
- // textPainter.paint(canvas, labelOffset);
- }
- canvas.drawLine(start, end, painter);
- }
- painter.color = Colors.red;
- drawArrow(canvas, painter, Offset(centerX, radius - 40));
- }
- @override
- bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
- }
- class _PlatePainter extends CustomPainter {
- final painter = Paint()
- ..color = const Color(0xff92b686)
- ..style = PaintingStyle.fill;
- @override
- void paint(Canvas canvas, Size size) {
- final centerX = size.width/2;
- final path = Path();
- var x = centerX;
- var y = 20.0;
- path.moveTo(x, y);
- x += 5;
- y = 0;
- path.lineTo(x, y);
- x -= 10;
- path.lineTo(x, y);
- path.close();
- canvas.drawPath(path, painter);
- }
- @override
- bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
- }
- class _NextPointArrowPainter extends CustomPainter {
- final painter = Paint()
- ..color = const Color(0xffffcb00);
- @override
- void paint(Canvas canvas, Size size) {
- final centerX = size.width/2;
- var radius = size.height / 2 - 4;
- drawArrow(canvas, painter, Offset(centerX, radius-40));
- }
- @override
- bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
- }
- class _OrientationPainter extends CustomPainter {
- _OrientationPainter(this.orientation);
- final sensor.Orientation orientation;
- final painter1 = Paint()
- ..color = Colors.grey
- ..style = PaintingStyle.fill
- ..blendMode = BlendMode.xor
- ;
- final painter2 = Paint()
- ..color = const Color(0xff38941b)
- ..style = PaintingStyle.fill
- ;
- @override
- void paint(Canvas canvas, Size size) {
- final centerX = size.width/2;
- final centerY = centerX;
- const radius1 = 10.0;
- const radius2 = radius1+2;
- const maxOffset = 20;
- var d = sqrt(orientation.x * orientation.x + orientation.y * orientation.y);
- var len = d / sqrt(pi/2 * pi/2 + pi/2 * pi/2) * maxOffset;
- var dx = 0.0;
- var dy = 0.0;
- if(d!=0){
- dx = len * (orientation.y / d) / 2;
- dy = len * (orientation.x / d) / 2;
- }
- final c1 = Offset(centerX + dx, centerY + dy);
- final c2 = Offset(centerX - dx, centerY - dy);
- canvas.saveLayer(null, Paint());
- canvas.drawCircle(c2, radius2, painter2);
- canvas.drawCircle(c1, radius1, painter1);
- canvas.restore();
- }
- @override
- bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
- }
- void main() async {
- runApp(GetMaterialApp(
- theme: appThemeData(),
- home: Container(
- width: double.infinity,
- height: double.infinity,
- color: Colors.white,
- alignment: Alignment.center,
- child: Compass(
- diameter: 140,
- compassRadians: 0,
- mapNorthRadians: 0,
- orientation: sensor.Orientation()
- ..x = 45
- ..y = 45,
- ))));
- }
|