Требуется реализовать метод displayCars, который отвечает за визуализацию машин на карте. Метод получает массив объектов Car. Каждый объект Car содержит уникальный идентификатор, координаты и угол поворота. Необходимо:
Функция для анимированного отображения автомобилей на карте
Требуется реализовать метод displayCars, который отвечает за визуализацию машин на карте. Метод получает массив объектов Car. Каждый объект Car содержит уникальный идентификатор, координаты и угол поворота. Необходимо:
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Требуется реализовать метод displayCars, который отвечает за визуализацию машин на карте. Метод получает массив объектов Car. Каждый объект Car содержит уникальный идентификатор, координаты и угол поворота. Необходимо:
- добавить новые автомобили, которых ещё нет на карте;
- переместить уже отображённые машины к их новым координатам с плавной анимацией (для этого используется вызов
updatePlacemark); - удалить с карты те автомобили, которые присутствуют в текущем наборе маркеров, но отсутствуют в полученном списке.
Никакой «грубой» реализации без анимации не допускается – нельзя просто удалить все маркеры и заново их добавить.
class MapController {
// можно дописать fields если необходимо
final MapPlugin plugin;
MapController(this.plugin);
void displayCars(List<Car> cars) {
/// Необходимо написать функцию анимированного движения машинок по карте.
/// Анимированное перемещение осуществляется вызовом updatePlacemark
/// Наивное решение без анимации — удалить все ранее добавленные машинки и отобразить новые.
}
// считаем, что функция реализована
Geometry _createGeometry(Car car) {/*...*/}
}
typedef MapPlacemarkId = int;
abstract class MapPlugin {
// считаем, что функция реализована
MapPlacemarkId addPlacemark(Geometry geometry);
// считаем, что функция реализована
void removePlacemark(MapPlacemarkId placemark);
// считаем, что функция реализована
void updatePlacemark(MapPlacemarkId placemark, Geometry geometry);
}
typedef CarId = String;
class Car {
final CarId id;
// getters [coordinate.x], [coordinate.y]
final math.Point<double> coordinate;
final double course;
const Car({
required this.id,
required this.coordinate,
required this.course,
});
}
class Geometry {
final double lat;
final double lon;
final double course;
final String image;
const Geometry({
required this.lat,
required this.lon,
required this.course,
required this.image,
});
}
Решение
Храните соответствие CarId → MapPlacemarkId. Для нового ID создавайте маркер, для существующего вызывайте updatePlacemark, а отсутствующие в новом списке ID удаляйте.
Добавьте поле в MapController и замените тело метода:
final Map<CarId, MapPlacemarkId> _markers = {};
void displayCars(List<Car> cars) {
final current = {for (final car in cars) car.id: car};
for (final car in current.values) {
final geometry = _createGeometry(car);
final marker = _markers[car.id];
if (marker == null) {
_markers[car.id] = plugin.addPlacemark(geometry);
} else {
plugin.updatePlacemark(marker, geometry);
}
}
final removed = _markers.keys
.where((id) => !current.containsKey(id))
.toList();
for (final id in removed) {
plugin.removePlacemark(_markers[id]!);
_markers.remove(id);
}
}
Копия списка удаляемых ID позволяет не менять Map во время обхода её ключей. Пустой список удаляет все маркеры; при повторяющихся ID берётся последняя запись. В среднем обработка занимает O(n + m), где n — новый список, m — число старых маркеров. Анимацию обеспечивает updatePlacemark по условию задачи.