打点优化

This commit is contained in:
mmc
2026-02-25 20:36:46 +08:00
parent 4d3872b576
commit 0b936f50aa
3 changed files with 137 additions and 22 deletions

View File

@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
class CrosshairPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// 十字中心坐标(精准对齐容器中心)
final centerX = size.width / 2;
final centerY = size.height / 2;
// 十字画笔样式(红色醒目,匹配原有定位标风格)
final paint = Paint()
..color = Colors.red
..strokeWidth =
2.0 // 十字线条宽度
..strokeCap = StrokeCap.round; // 线条端点圆润,更美观
// ========== 绘制水平横线(─) ==========
canvas.drawLine(
Offset(0, centerY), // 左端点
Offset(size.width, centerY), // 右端点
paint,
);
// ========== 绘制垂直竖线(│) ==========
canvas.drawLine(
Offset(centerX, 0), // 上端点
Offset(centerX, size.height), // 下端点
paint,
);
// 可选:中心小圆点(强化中心定位)
final centerDotPaint = Paint()
..color = Colors.white
..style = PaintingStyle.fill;
canvas.drawCircle(
Offset(centerX, centerY),
1.5, // 中心圆点半径
centerDotPaint,
);
}
@override
bool shouldRepaint(covariant CrosshairPainter oldDelegate) => false;
}

View File

@@ -0,0 +1,57 @@
import 'dart:math';
import 'package:flutter/material.dart';
class HeadingMarkerPainter extends CustomPainter {
final double headingAngle; // 航向角(度)
HeadingMarkerPainter({required this.headingAngle});
@override
void paint(Canvas canvas, Size size) {
// 中心点坐标(对应SVG的cx=20, cy=20)
final center = Offset(size.width / 2, size.height / 2);
// 圆圈半径(对应SVG的r=10)
final circleRadius = 10.0;
// ========== 1. 绘制绿色半透明圆圈(SVG的circle) ==========
final circlePaint = Paint()
..color = const Color(0xFF1AFA29)
.withOpacity(0.7) // #1afa29 70%透明度
..style = PaintingStyle.fill;
canvas.drawCircle(center, circleRadius, circlePaint);
// 绘制白色描边(SVG的stroke="#fff" stroke-width="2")
final strokePaint = Paint()
..color = Colors.white
..style = PaintingStyle.stroke
..strokeWidth = 2.0;
canvas.drawCircle(center, circleRadius, strokePaint);
// ========== 2. 绘制航向箭头(SVG的path) ==========
// 保存画布状态(旋转后恢复)
canvas.save();
// 平移+旋转:以圆心为旋转中心,根据航向角旋转(对应SVG的transform)
canvas.translate(center.dx, center.dy);
canvas.rotate(headingAngle * pi / 180); // 角度转弧度
// 箭头路径(对应SVG的d="M0,-8 L4,4 L0,1 L-4,4 Z")
final arrowPath = Path()
..moveTo(0, -8) // 顶部顶点
..lineTo(4, 4) // 右侧点
..lineTo(0, 1) // 中下点
..lineTo(-4, 4) // 左侧点
..close(); // 闭合路径
final arrowPaint = Paint()..color = Colors.white;
canvas.drawPath(arrowPath, arrowPaint);
// 恢复画布状态
canvas.restore();
}
@override
bool shouldRepaint(covariant HeadingMarkerPainter oldDelegate) {
// 航向角变化时重新绘制
return oldDelegate.headingAngle != headingAngle;
}
}

View File

@@ -6,6 +6,8 @@ import 'package:geolocator/geolocator.dart';
import 'package:latlong2/latlong.dart';
import 'package:maibu_satabot_v2/features/home/presentation/widgets/BottomDirectionLine.dart';
import 'package:maibu_satabot_v2/features/home/presentation/widgets/common/enum.dart';
import 'package:maibu_satabot_v2/features/home/presentation/widgets/map/CenterLocation.dart';
import 'package:maibu_satabot_v2/features/home/presentation/widgets/map/HeadingPointer.dart';
import 'package:maibu_satabot_v2/features/home/presentation/widgets/startpoint_area.dart';
import '../path_list_pages.dart';
@@ -33,6 +35,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
// ========== 核心新增状态 ==========
List<LatLng> _markedPoints = []; // 存储所有打点坐标
LatLng get _mapCenter => _mapController.center; // 实时获取地图中心坐标
double _headingAngle = 0.0; // 航向角(单位:度)
// =================================
@override
@@ -150,18 +153,26 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
),
/// ========== 新增:中心标与历史打点的虚线连线 ==========
///
/// if (_markedPoints.length >= 2)
PolylineLayer(
polylines: [
for (int i = 0; i < _markedPoints.length - 1; i++)
Polyline(
points: [_markedPoints[i], _markedPoints[i + 1]],
color: Colors.orange.withOpacity(0.5),
strokeWidth: 1.5,
),
],
),
if (_markedPoints.isNotEmpty)
PolylineLayer(
polylines: [
for (var point in _markedPoints)
Polyline(
points: [_mapCenter, point], // 中心标 ↔ 历史打点
color: Colors.orange.withOpacity(
0.5,
), // 降低透明度,模拟虚线视觉效果
strokeWidth: 1.5, // 调细一点,更接近虚线
// 去掉 dashArray,直接用实线
),
Polyline(
points: [_mapCenter, _markedPoints.last],
color: Colors.blue.withOpacity(0.5),
strokeWidth: 1.5,
),
],
),
@@ -171,12 +182,13 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
markers: [
Marker(
point: _currentLatLng!,
width: 20,
height: 20,
child: const Icon(
Icons.my_location,
color: Colors.blue,
size: 30,
width: 40,
height: 40,
child: CustomPaint(
size: const Size(40, 40),
painter: HeadingMarkerPainter(
headingAngle: _headingAngle,
),
),
),
],
@@ -195,6 +207,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 8), // 向下偏移8px(抵消默认的顶部对齐)
// 绿色打点标记
Container(
width: 16,
@@ -226,21 +239,22 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
),
/// ========== 核心:地图正中心固定定位标 ==========
const Positioned(
Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: Center(
child: Icon(
Icons.location_pin, // 定位标图标
color: Colors.red, // 红色醒目
size: 30,
shadows: [BoxShadow(color: Colors.white, blurRadius: 2)],
// 自定义十字标(中心精准对齐地图中心)
child: SizedBox(
width: 16, // 十字整体宽度
height: 16, // 十字整体高度
child: CustomPaint(
painter: CrosshairPainter(), // 自定义十字画笔
),
),
),
),
// 右侧悬浮菜单
Positioned(
height: 336,