Я разработал приложение для Android, в котором вы можете добавлять изображения на экран и перемещать / поворачивать / масштабировать их.Технически, у меня есть родительский макет с фиксированным аспектом, который содержит эти изображения (ImageViews).Они установили ширину и высоту для match_parent.Затем я могу сохранить свои позиции на сервере, который затем могу загрузить на то же или другое устройство.По сути, я просто сохраняю значения матрицы.Однако перевод x / y имеет абсолютные значения (в пикселях), но размеры экрана отличаются, поэтому вместо этого я устанавливаю их в процентах (перевод x делится на ширину родительского элемента, а перевод y делится на высоту родительского элемента).При загрузке изображений я просто умножаю перевод x / y на ширину / высоту родительского макета, и все выглядит одинаково даже на другом устройстве.
Вот как я это делаю:
float[] values = new float[9];
parentLayout.matrix.getValues(values);
values[Matrix.MTRANS_X] /= parentLayout.getWidth();
values[Matrix.MTRANS_Y] /= parentLayout.getHeight();
Затем в функции загрузки я просто умножаю эти значения.
Работа с изображениями осуществляется с помощью postTranslate / postScale / postRotate сточка привязки (для жеста двумя пальцами это средняя точка между этими пальцами).
Теперь я хочу перенести это приложение на iOS и использовать аналогичную технику для достижения правильного положения изображений на устройствах iOS.CGAffineTransform, похоже, очень похож на класс Matrix.Порядок полей различен, но, похоже, они работают одинаково.
Допустим, этот массив является образцом массива значений из приложения Android:
let a: [CGFloat] = [0.35355338, -0.35355338, 0.44107446, 0.35355338, 0.35355338, 0.058058262]
Я не сохраняю последние 3 поля, потому что они всегда 0, 0 и 1 и на iOSони даже не могут быть установлены (документация также утверждает, что это [0, 0, 1]).Вот как выглядит «преобразование»:
let tx = a[2] * width //multiply percentage translation x with parent width
let ty = a[5] * height //multiply percentage translation y with parent height
let transform = CGAffineTransform(a: a[0], b: a[3], c: a[1], d: a[4], tx: tx, ty: ty)
Однако это работает только для очень простых случаев.Для других изображение обычно неуместно или даже полностью испорчено.
Я заметил, что по умолчанию на Android у меня есть точка привязки в [0, 0], но на iOS это центр изображения.
Например:
float midX = parentLayout.getWidth() / 2.0f;
float midY = parentLayout.getHeight() / 2.0f;
parentLayout.matrix.postScale(0.5f, 0.5f, midX, midY);
Дает следующую матрицу:
0.5, 0.0, 360.0,
0.0, 0.5, 240.0,
0.0, 0.0, 1.0
[360.0, 240.0] - просто вектор из левого верхнего угла.
Однако на iOS мне не нужно указывать среднюю точку, потому что она уже трансформирована вокруг центра:
let transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
и дает мне:
CGAffineTransform(a: 0.5, b: 0.0, c: 0.0, d: 0.5, tx: 0.0, ty: 0.0)
Я попытался установить другую точку привязки на iOS:
parentView.layer.anchorPoint = CGPoint(x: 0, y: 0)
Однако я не могу получить правильные результаты.Я пробовал переводить по ширине * 0,5, -высоте * 0,5, масштабировать и переводить обратно, но я не получаю тот же результат, что и на Android.
Короче говоря: как я могу изменить матрицу из Androidв CGAffineTransform из iOS для достижения того же внешнего вида?
Я также прилагаю как можно более простые демонстрационные проекты.Цель состоит в том, чтобы скопировать выходной массив из Android в массив «a» в проекте iOS и изменить вычисление CGAffineTransform (и / или настройку parentView) таким образом, чтобы изображение выглядело одинаково на обеих платформах, независимо от того, что выводит журнал из Android.
Android: https://github.com/piotrros/MatrixAndroid
iOS: https://github.com/piotrros/MatrixIOS
edit:
@ Решение Sulthan отлично работает!Несмотря на это, у меня возник вопрос о том, чтобы обратить процесс вспять, и он мне тоже нужен.Используя его ответ, я попытался включить в свое приложение:
let savedTransform = CGAffineTransform.identity
.concatenating(CGAffineTransform(translationX: -width / 2, y: -height / 2))
.concatenating(
self.transform
)
.concatenating(CGAffineTransform(translationX: width / 2, y: height / 2))
let tx = savedTransform.tx
let ty = savedTransform.ty
let t = CGAffineTransform(a: savedTransform.a, b: savedTransform.b, c: savedTransform.c, d: savedTransform.d, tx: tx / cWidth, ty: ty / cHeight)
placement.transform = [Float(t.a), Float(t.c), Float(t.tx), Float(t.b), Float(t.d), Float(t.ty), 0, 0, 1]
Размещение - это просто класс для хранения "Android" -версии матрицы.cWidth / cHeight - это ширина / высота родителя.Я делю tx / ty на них, чтобы получить процент ширины / высоты, как я делаю на Android.
Однако это не работает.TX / TY неправильно.
Для ввода:
[0,2743883, -0,16761175, 0,43753636, 0,16761175, 0,2743883, 0,40431038, 0,0, 0,0, 1,0]
возвращает:
[0,2743883, -0,16761175, 0,18834576, 0,16761175, 0,2743883, 0,2182884, 0,0, 0,0, 1,0]
, так что все остальноеTX / TY в порядке.Где ошибка?