GMap Вращение подшипника в плавном движении (избегайте рывков при изменении значений подшипника)

Я хочу повернуть GMap, изменив значение угла азимута, чтобы камера вращалась вокруг центральной точки (360-градусный один полный круг). Когда мы меняем азимут, возникает эффект смягчения в начальной и конечной точках камеры. Как я могу контролировать/изменить это, чтобы сделать вращение плавным при изменении значений Bearing (чтобы повернуть карту на 360 градусов, плавная анимация)?

Требуется это для всех языков, так как кажется, что эффект смягчения отличается в разных языковых библиотеках. например Swift, Android, PHP, JS, Node.js, React.

Пример Swift (работает нормально в Linear Animation):

Обратите внимание, что изначально у анимации были рывки и в iOS, но когда мы использовали CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear вместе с ее свойствами CATransaction, анимация GMap превратилась в плавную анимацию. так что теперь, если вы видите код ниже, изменение значения Bearing не создает рывкового эффекта (из-за эффекта плавности в анимации GMap). Я также ищу подходящее решение для Android и Web.

//Move the map around current location, first loop
let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
CATransaction.begin()
CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
CATransaction.setAnimationTimingFunction(timingFunction)
CATransaction.setCompletionBlock({
    //Move the map around current location, second loop
    let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    CATransaction.begin()
    CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
    CATransaction.setAnimationTimingFunction(timingFunction)
    CATransaction.setCompletionBlock({
        //Move the map around current location, third loop
        let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        CATransaction.begin()
        CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
        CATransaction.setAnimationTimingFunction(timingFunction)
        CATransaction.setCompletionBlock({
            UIView.animate(withDuration: 0.5, animations: {
                self.findingYourLocation.alpha = 0.0
            })
            //TODO: Set nearest branch
            // Zoom in one zoom level
            let zoomCamera = GMSCameraUpdate.zoomIn()
            self.mapView.animate(with: zoomCamera)

            // Center the camera on UBL Branch when animation finished
            //let nearestBranch = CLLocationCoordinate2D(latitude: 24.850751, longitude: 67.016589)
            let nearestBranch = CLLocationCoordinate2D.init(latitude: 24.806849, longitude: 67.038734)
            let nearestBranchCam = GMSCameraUpdate.setTarget(nearestBranch)



            CATransaction.begin()

            let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
            CATransaction.setAnimationTimingFunction(timingFunction)
            CATransaction.setCompletionBlock({
                self.nextButton.alpha = 1.0
            })
            self.mapView.animate(with: nearestBranchCam)
            self.mapView.animate(toZoom: 15)
            self.mapView.animate(toBearing: 0)
            self.mapView.animate(toViewingAngle: 0)

            CATransaction.commit()

        })
        self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
        CATransaction.commit()

    })
    self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
    CATransaction.commit()

})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransaction.commit()

Пример кода Android (есть проблема):

Пример/пример кода для Android можно найти здесь: https://issuetracker.google.com/issues/71738889

Который также включает файл .apk, видео .mp4 примера выходных данных приложения. Который ясно показывает рывки при изменении значения Bearing при вращении карты на 360 градусов.


person Nah    schedule 06.01.2018    source источник
comment
Немного погуглив, вы, возможно, захотите установить свой заголовок, чтобы изменить вращение карты; map.setHeading(<current heading> + <angle of rotation>). Дайте мне знать, если это сработает!   -  person JillevdW    schedule 03.04.2018
comment
спасибо за ответ, я хочу повернуть этот вид карты: developers.google. com/maps/documentation/android-api/, а не изображения. Буду признателен, если вы подготовите демонстрационный пример.   -  person Nah    schedule 03.04.2018
comment
Спасибо, что показали все ваши голоса по этому вопросу. Google наконец принял во внимание эту проблему и добавит эту функцию, если вы нажмете значок звездочка, чтобы показать свой интерес: issuetracker.google.com/u/1/issues/71738889   -  person Nah    schedule 18.05.2018
comment
Наконец, команда Google недавно выпустила поддержку вышеуказанной функции. Проверьте приведенную выше ссылку на средство отслеживания проблем, чтобы узнать подробности решения проблемы.   -  person Nah    schedule 25.05.2021


Ответы (4)


Было бы довольно трудно прочитать это как ответ в качестве комментария; это взято из документации Google.

Рассмотрим этот код:

CameraPosition cameraPosition = new CameraPosition.Builder()
    .target(MOUNTAIN_VIEW)      // Sets the center of the map to Mountain View
    .zoom(17)                   // Sets the zoom
    .bearing(90)                // Sets the orientation of the camera to east
    .tilt(30)                   // Sets the tilt of the camera to 30 degrees
    .build();                   // Creates a CameraPosition from the builder
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

Этот код создает новую позицию камеры, и это именно то, что вы пытаетесь изменить: азимут камеры. Итак, если вы создадите новую позицию камеры следующим образом:

CameraPosition cameraPosition = new CameraPosition.Builder()
    .bearing(50)
    .build();

а затем анимируйте камеру в это положение:

map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

Это должно делать свое дело. Чтобы дать дополнительную информацию о том, что вам нужно будет использовать в качестве подшипника:

азимут 90 градусов приводит к тому, что на карте направление вверх указывает точно на восток.

Удачи.

person JillevdW    schedule 03.04.2018
comment
Цените ваши усилия, но если вы запустите его, это не будет плавная линейная анимация. Будут рывки из-за эффекта easing в начале и в конце анимации. Когда вы измените значение Bearing на дальнейшее вращение (чтобы завершить цикл 360 градусов), вы увидите количество рывков. Это главная проблема. - person Nah; 03.04.2018
comment
@MuhammadHannan, если у вас есть проблемы с тем, как работает функция animateCamera Карты, вы можете попытаться переопределить ее, но я думаю, что вы погружаетесь в очень глубокую кроличью нору. Удачи! - person JillevdW; 03.04.2018
comment
Возможно, вы правы, но я хочу убрать тот рывок, который появляется во время анимации карты (когда мы меняем значение азимута), который, вероятно, является эффектом замедления в анимации. Мне удалось удалить их в приложении iOS, применив / применив линейную анимацию, но не могу управлять в JS и Android. - person Nah; 04.04.2018
comment
@MuhammadHannan, можете ли вы прислать мне ссылки/данные о том, как вы внедрили линейную анимацию? Затем я рассмотрю JS и Android сторону вещей. - person JillevdW; 05.04.2018
comment
Я добавил swift пример в свой вопрос. Я могу отправить вам видео с iOS образцом анимации, если требуется, в качестве рабочего доказательства, если требуется (но не знаю, как поделиться видео 6 МБ) - person Nah; 05.04.2018
comment
@MuhammadHannan, если я правильно понимаю, вы используете собственный API анимации, чтобы разделить анимацию на три равные анимации с линейной интерполяцией. На Android я обычно использую AnimatorSet для работы с анимацией. в состоянии воспроизвести желаемое поведение с этим. - person JillevdW; 05.04.2018
comment
Я не использовал AnimatorSet, поэтому было бы замечательно, если бы вы могли указать его использование в моем конкретном случае. В приведенном выше примере показана только анимация поворота (которая должна быть плавной), и после 2, 3 или 5 поворотов мы возвращаем камеру к 90-градусному обзору с высоты птичьего полета, поэтому нам нужно управлять и этой частью (я не предоставил эту часть код в приведенном выше примере), но цель та же, чтобы иметь плавную анимацию при изменении камеры/азимута. - person Nah; 05.04.2018
comment
например все еще жду. - person Nah; 10.04.2018
comment
@MuhammadHannan Я не могу вдаваться в подробности, но что вы можете попробовать, так это создать объекты ObjectAnimator, скажем, ObjectAnimator.ofFloat(_,_,_), и когда вы создадите все нужные анимации, вы можете добавить их к объекту AnimatorSet с помощью animatorSetObj.play(objectAnimatorObj) или если вы иметь несколько animatorSetObj.playTogether(objectAnimatorObj1, objectAnimatorObj2). - person JillevdW; 10.04.2018
comment
у меня проблема, я хочу, чтобы направление местоположения всегда было направлено на север, если местоположение изменяется влево, тогда оно должно выровнять карту по направлению к северу, как в режиме вождения Google Maps, - person Wahdat Jan; 16.04.2019

Я собираюсь написать это как еще один ответ, так как я хотел бы потратить время на написание стены текста, в то время как я хотел бы, чтобы другой ответ был как можно короче, поскольку он все еще может помочь другим людям с подобным проблема.

Проблема

Итак, если я правильно понимаю, вы пытаетесь создать приложение с картами Google для разных платформ. Вы столкнулись с проблемой на картах Google (прерывистое движение) и пытаетесь найти решение для всех платформ.

Мои предлагаемые решения

Я разделю это на несколько разделов, потому что вижу разные пути продвижения вперед.

  • Найдите решение для всех платформ.

Это кажется самым простым, но это может быть похоже на проблему XY. Я попытался познакомить вас с некоторыми способами анимации видов, и вы решили проблему в своем приложении для iOS, но в основе того, с чем вы имеете дело, лежит недостаток анимации карт Google при смене направления. Я не уверен, есть ли способ решить эту проблему на каждой платформе, поскольку я не пробовал.

  • Использовать другую карту

Это звучит как большой шаг, и в зависимости от вашего использования вы не хотите этого делать. Тем не менее, я успешно использовал Leaflet (карту JS) с WKWebView на iOS и Android, и все это работало довольно хорошо (очевидно, это также отлично работает в браузере). Имейте в виду, что некоторые другие карты также могут иметь рывковую анимацию.

Подведение итогов

Надеюсь, я дал некоторое представление. Я добавлю к этому ответу, когда мы узнаем что-то новое о проблеме. Не могли бы вы привести минимальный воспроизводимый пример? Так я смогу лучше попробовать. Удачи!

person JillevdW    schedule 16.04.2018
comment
Я предоставил пример кода минимального уровня для Android в ссылке в моем вопросе, вы можете играть на этом. - person Nah; 16.04.2018
comment
@MuhammadHannan В настоящее время я работаю над предоставленным вами проектом Android, чтобы попытаться найти решение. - person JillevdW; 19.04.2018
comment
Будет интересно увидеть решение. - person Nah; 19.04.2018
comment
@MuhammadHannan Мне жаль говорить, что на данный момент я не смог найти решение. Я ищу правильный эквивалент CATransaction, чтобы я мог имитировать поведение, отображаемое в вашем примере iOS. Я продолжу свои поиски. - person JillevdW; 20.04.2018

Перебрав все возможные случаи, я узнал, что GMap не имеет необходимой функции поворота карты на 360 градусов за один раз с пользовательской анимацией. Не знаю, появится ли это в следующей GMap версии API.

На данный момент возможное решение состоит в том, чтобы изменить логику анимации, и вместо вращения на 360 градусов мы можем повернуть, например, на 180 градусов с уменьшенной скоростью анимации (время анимации).

Это позволяет нам предоставить пользователю необходимую карту, окружающую поисковый опыт.

(На данный момент я публикую этот временный ответ и позволяю другим обновлять или публиковать последний ответ в будущем).


Я отправил эту проблему управления анимацией в систему отслеживания проблем GMap, пожалуйста, НАЧНИТЕ эту проблему, чтобы показать свой интерес и отзыв, чтобы команда Google могла окончательно рассмотреть эту функцию. https://issuetracker.google.com/u/1/issues/71738889

person Nah    schedule 25.04.2018

Вот мой подход:

  • наклон = 45f
  • увеличение = 18
  • цель = текущее местоположение
  • подшипник = lastKnownLocation.bearingTo(currentLocation)
  1. Используйте map.animateCamera(); // вместо перемещения камеры
CameraPosition cameraPosition;
        if (currentLocation.distanceTo(lastKnownLocation) > 50) {
            cameraPosition = new CameraPosition.Builder()
                    .target(currentLatLng).zoom(20).tilt(45f).bearing(bearingValue).build();
        } else {
            cameraPosition = new CameraPosition.Builder()
                    .target(currentLatLng).zoom(20).tilt(45f).build();
        }

        map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

Что еще вы должны сделать? Вы должны вызвать этот метод из LocationCallback (откуда вы получаете обновления местоположения), и тогда мы сможем работать без сбоев.

Таким образом, если пользователь двигался (шел пешком или ехал), а расстояние между lastKnownLocation и currentLocation больше 50 метров, тогда мы будем устанавливать только пеленг, в противном случае мы продолжаем изменять только targetLocation.

Таким образом, мы можем показать направление движения, как на картах Google.

person Vijay    schedule 15.05.2021