Flutter повторно использует преобразование Matrix4 для InteractiveViewer на экранах разных размеров

Мне нужно применить преобразование Matrix4 к моему изображению, завернутому в InteractiveViewer. Изображения всегда имеют соотношение 3:4.

Он работает нормально на исходном устройстве, которое изменяет Matrix4 (панорамирование/масштабирование), проблема в том, что когда я отправляю значения Matrix4 на другое устройство (например, планшет), чтобы загрузить то же изображение и повторно использовать преобразование Matrix4, это не то же самое, поэтому я подозревал, что это может быть из-за размеров экрана.

Matrix4 отправляется как строковое сообщение с использованием String.fromCharCodes(matrix4.storage.buffer.asUint8List()).

Я попробовал отправить значение масштаба и перевести смещение отдельно, чтобы использовать Transform.scale() и Transform.translate(), но это работает не очень хорошо.

Мой макет выглядит следующим образом:

Stack(
        alignment: Alignment.bottomCenter,
        children: [
          AspectRatio(
            aspectRatio: 9/16,
            child: LayoutBuilder(
              builder: (context, constraints) {
                return ClipRect(
                  child: SizedBox(
                    width: constraints.maxWidth,
                    height: constraints.maxHeight,
                    child: InteractiveViewer(
                      transformationController: _controller,
                      child: Image.network('https://picsum.photos/seed/picsum/200/300'),
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      );

Мой вопрос: как я могу повторно использовать одно и то же преобразование Matrix4 для получения одного и того же результата независимо от устройств и размеров экрана?

@pskink Извините за неясность, изображения всегда имеют соотношение 3:4, а страница представляет собой виджет AspectRatio с соотношением сторон 9:16. Я могу определить положение события касания, чтобы увеличить изображение в точном месте на каждом устройстве, отправив смещение, например (dx/constraints.maxWidth)(dy/constraints.maxHeight), и получить его на другом устройстве, например (constraints.maxWidth * dx)(constraints.maxHeight * dy), используя метод из ссылки .

Brown 28.05.2024 18:40

Поэтому, когда я масштабирую/панорамирую изображение, я не знаю, как масштабировать матрицу перед отправкой и как уменьшить ее в зависимости от размеров экрана другого устройства. Достижимо ли это с помощью матрицы4?

Brown 28.05.2024 18:42

Большое спасибо за направление, к сожалению, у меня пока ничего не получилось, у меня проблемы с масштабным коэффициентом, позвонив getMaxScaleOnAxis, у вас уже есть последняя шкала, примененная к InteractiveViewer, зачем нам нужно умножать ее на коэффициент (0,3 в вашем образец) на удаленной стороне? Когда я попытался изменить ваш образец, чтобы использовать масштабный коэффициент, полученный из InteractiveViewer.onInteractionUpdate (scale*ScaleUpdateDetails.scale), результат был другим.

Brown 29.05.2024 05:58

Вот демо-версия моего телефона и планшета: ссылка

Brown 29.05.2024 06:15
0.3 был просто примерным фактором, проверьте мою обновленную суть: теперь это больше похоже на ваш случай AspectRatio 9:16 - масштаб такой: scale: scale * remoteSize.width / localSize.width
pskink 29.05.2024 06:23

я сделал это немного проще: теперь localSize.width не нужен на удаленной стороне (это часть scale), также вычисление матрицы теперь стало проще, проверьте мою окончательную суть

pskink 29.05.2024 07:30

Что-то не так, на этот раз я точно следую вашей сути: при увеличении масштаба на локальной стороне фотография на удаленной стороне уменьшается до крошечной точки. Я попробовал запустить пример кода из вашей сути на телефоне и планшете, используя жестко запрограммированное значение, результат также неудовлетворительный.

Brown 29.05.2024 08:09

Спасибо за продолжение, теперь я вижу, единственная разница заключалась в том, что мой InteractiveViewer был constrained: true вместо неограниченного. Когда я превратил его в ложное, оно РАБОТАЕТ отлично. Это в основном отвечает на мой вопрос, но неограниченное изображение изначально слишком сильно увеличено, и, поскольку начального свойства масштаба нет, я думаю, мне придется проделать некоторые трюки. Спасибо, чувак, ты спасаешь жизни. Не могли бы вы опубликовать свое решение выше как отдельный ответ, чтобы я мог его принять!

Brown 29.05.2024 10:45

«и поскольку нет свойства начального масштаба» - тогда используйте transformationController: _controller, который изначально масштабируется, и если хотите, не стесняйтесь опубликовать собственный ответ

pskink 29.05.2024 10:52

@pskink Не хочу вас снова беспокоить, похоже, у InteractiveViewer есть немало проблем, связанных с начальным масштабом, происходящим здесь github. Итак, я попытался вернуться к constrained: true, получить смещениеX и смещениеY из локальной матрицы, разделить их на localSize.width и localSize.height и отправить их вместо привязки, на удаленной стороне я получаю, умножая их на remoteSize.width и remoteSize.height, но пока безуспешно. Как вы думаете, это можно сделать с помощью constrained: true?

Brown 29.05.2024 14:30

«Как вы думаете, это можно сделать с помощью constrained: true?» - я так не думаю, с constrained: true довольно сложно контролировать, как рисуется ребенок, а если constrained: false вы можете полностью контролировать это, то в чем проблема с вычислением начального значения TranformationController? вы не знаете размер ребенка (вашего изображения)?

pskink 29.05.2024 16:52

Я знаю размер моего изображения, проблема снова в размерах экрана: такие устройства, как планшет, могут отображать все изображение целиком, тогда как телефоны должны уменьшаться, чтобы соответствовать размеру constrained: true, в таких случаях местоположение больше не является точным. Например: когда я размещаю маркер. Если я просто применю начальную шкалу на всех устройствах, то на некоторых будет так: ссылка. Итак, я думаю, что если я смогу извлечь смещение из матрицы и сопоставить его с локальной позицией, возможно, я смогу синхронизироваться с удаленной стороной (например, когда я применяю касание для масштабирования определенной области). Но надежды пока нет.

Brown 29.05.2024 17:18

Если у вас есть размер интерактивного средства просмотра (поскольку вы используете конструктор макетов) и размер изображения, то рассчитать исходную матрицу легко: gist.github.com/pskink/6ef88df64d7764fd0efcd60aa618f0c0

pskink 29.05.2024 17:29

Вот и все, похоже, я все-таки выберу constrained: false. Большое спасибо за ваши указания, вы действительно спасли мне день.

Brown 29.05.2024 18:20

Я обязательно это проверю, спасибо, приятель

Brown 02.06.2024 05:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
15
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вся заслуга принадлежит @pskink

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

С локальной стороны получите масштаб и смещение привязки, как показано ниже:

final scale = _controller.getMaxScaleOnAxis() / localSize.width;
final anchor = _controller.toScene(Offset.zero);

А на удаленной стороне примените масштаб и перевод:

_remoteController.value = Matrix4.identity()
    ..scale(scale * remoteSize.width)
    ..translate(-anchor.dx, -anchor.dy);

localSize и remoteSize можно получить из LayoutBuilder, например:

Size(constraints.maxWidth, constraints.maxHeight)

Примечание. Вышеупомянутое работает только при наличии InteractiveViewerconstrained: false. Если вы хотите масштабировать исходную матрицу изображения, вы можете перейти по этой теме: github

Другие вопросы по теме