所以,我想展示一个计时器。下面是我想要实现的简单设计。随着时间逐渐减少,汽车应该绕赛道行驶。我目前不知道如何实施它。还有一个问题是,汽车绕圈行驶时,车面应该旋转。如果有人过去做过类似的事情,请告诉我。任何指南/教程将不胜感激。
添加包:path_drawing
并尝试运行此代码。目前,我使用计时器来更新汽车的位置,您可以根据您的要求进行操作。
汽车图像已添加到资产文件夹中。 本例中使用的图像
import 'dart:async';
import 'dart:math';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_drawing/path_drawing.dart' as pd;
class CustomRoadWithCar extends StatefulWidget {
const CustomRoadWithCar({super.key});
@override
State<CustomRoadWithCar> createState() => _CustomRoadWithCarState();
}
class _CustomRoadWithCarState extends State<CustomRoadWithCar> {
Timer? _timer;
int _elapsedSeconds = 0;
// Variable to control the movement of the car and path fill
double _carProgress = 0.0;
ui.Image? image;
@override
void initState() {
super.initState();
loadImageFromAsset('assets/car.png');
startTimer();
}
void startTimer() {
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
setState(() {
_elapsedSeconds++;
// Calculate the progress based on elapsed seconds
_carProgress = _elapsedSeconds / 59.0;
// Check if the elapsed time has reached 59 seconds
if (_elapsedSeconds >= 59) {
// Stop the timer
_timer?.cancel();
}
});
});
}
@override
void dispose() {
// Cancel the timer when the widget is disposed
_timer?.cancel();
super.dispose();
}
// Load an image from assets and convert it to a ui.Image object
Future<void> loadImageFromAsset(String path) async {
final ByteData data = await rootBundle.load(path);
final Uint8List bytes = data.buffer.asUint8List();
final ui.Codec codec = await ui.instantiateImageCodec(bytes);
final ui.FrameInfo frameInfo = await codec.getNextFrame();
final ui.Image loadedImage = frameInfo.image;
setState(() {
image = loadedImage; // Set the loaded image as the state
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Circle Border Drawing'),
),
body: Center(
child: Stack(
children: [
//grey color road
CustomPaint(
size: const Size(
200, 200), // Set the size of the CustomPaint widget
painter: RoadPainter(25.0), // Set the border width
),
//to be filled by blue color
CustomPaint(
size: const Size(
200, 200), // Set the size of the CustomPaint widget
painter: CircleBorderPainter(
_carProgress, // Pass the current progress to the painter
25.0,
image,
const Color(0xff243347)),
),
Text("$_elapsedSeconds")
],
),
),
);
}
}
class CircleBorderPainter extends CustomPainter {
final double carProgress; // Progress of the car and path fill (0.0 to 1.0)
final double borderWidth;
final ui.Image? image;
final Color fillColor;
CircleBorderPainter(
this.carProgress, this.borderWidth, this.image, this.fillColor);
@override
void paint(Canvas canvas, Size size) {
final double radius = size.width / 2;
final Paint paint = Paint()
..color = fillColor
..style = PaintingStyle.stroke
..strokeWidth = borderWidth
..strokeCap = StrokeCap.round;
// Calculate the arc angle based on progress
double sweepAngle = carProgress * 2 * pi;
final center = size.center(Offset.zero);
// Draw the arc up to the current progress
Rect rect = Rect.fromCircle(center: center, radius: radius);
canvas.drawArc(rect, -pi / 2, sweepAngle, false, paint);
// Calculate the car's position along the arc based on progress
double carAngle = -pi / 2 + sweepAngle;
double carX = size.width / 2 + radius * cos(carAngle);
double carY = size.height / 2 + radius * sin(carAngle);
Offset carPosition = Offset(carX, carY);
DashedCirclePainter dashedCirclePainter = DashedCirclePainter(
strokeWidth: 1.0,
color: Colors.white,
dashPattern: [10.0, 5.0], // Dash length and gap length
);
dashedCirclePainter.paint(canvas, size, center, radius);
// Draw the car image at the calculated position
if (image != null) {
// Desired image width set to 24
double desiredImageWidth = 24;
// Calculate the image aspect ratio
double imageAspectRatio =
image!.width.toDouble() / image!.height.toDouble();
// Calculate the height based on the desired width and aspect ratio
double desiredImageHeight = desiredImageWidth / imageAspectRatio;
// Save the canvas state
canvas.save();
// Translate the canvas to the car position
canvas.translate(carPosition.dx, carPosition.dy);
// Rotate the canvas based on the car's angle
canvas.rotate(carAngle);
// Draw the car image at the car position
canvas.drawImageRect(
image!,
Rect.fromLTWH(0, 0, image!.width.toDouble(), image!.height.toDouble()),
Rect.fromCenter(
center: Offset.zero,
width: desiredImageWidth,
height: desiredImageHeight),
Paint(),
);
// Restore the canvas state
canvas.restore();
}
}
@override
bool shouldRepaint(CircleBorderPainter oldDelegate) {
return oldDelegate.carProgress != carProgress ||
oldDelegate.borderWidth != borderWidth ||
oldDelegate.image != image;
}
}
class RoadPainter extends CustomPainter {
final double borderWidth;
RoadPainter(this.borderWidth);
@override
void paint(Canvas canvas, Size size) {
// Paint for the base road
final Paint roadPaint = Paint()
..color = Colors.grey // Grey color for the road
..style = PaintingStyle.stroke
..strokeWidth = borderWidth;
// Calculate the radius and center of the canvas
final double radius = size.width / 2;
final Offset center = size.center(Offset.zero);
// Draw the base circle (road) with specified border width
canvas.drawCircle(center, radius, roadPaint);
DashedCirclePainter dashedCirclePainter = DashedCirclePainter(
strokeWidth: 1.0,
color: Colors.white,
dashPattern: [10.0, 5.0], // Dash length and gap length
);
dashedCirclePainter.paint(canvas, size, center, radius);
}
@override
bool shouldRepaint(RoadPainter oldDelegate) {
return oldDelegate.borderWidth != borderWidth;
}
}
class DashedCirclePainter {
final double strokeWidth;
final Color color;
final List<double> dashPattern;
DashedCirclePainter({
required this.strokeWidth,
required this.color,
required this.dashPattern,
});
void paint(Canvas canvas, Size size, Offset center, double radius) {
// Paint for the red dashed circle
final Paint dashedCirclePaint = Paint()
..color = color // Color for the dashed circle
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth;
// Create a Path for the red dashed circle
Path dashedCirclePath = Path();
dashedCirclePath.addOval(Rect.fromCircle(center: center, radius: radius));
// Draw the dashed red circle using dashPath function
canvas.drawPath(
pd.dashPath(
dashedCirclePath,
dashArray: pd.CircularIntervalList<double>(dashPattern),
),
dashedCirclePaint,
);
}
}
希望有帮助...