Преобразования, примененные к представлению, не суммируются.Скорее, представление начинает выравниваться с системой координат своего родителя, и преобразование применяется относительно этого.
Как уже упоминалось в других ответах, в образце кода BubbleLevel Apple достаточно частей чтобы выполнить то, что вы ищете.-[LevelViewController accelerometer:didAccelerate:]
уже содержит пример того, как извлечь сглаженную компоненту относительного вращения экрана вектора гравитации:
// Use a basic low-pass filter to only keep the gravity in the accelerometer values for the X and Y axes
accelerationX = acceleration.x * kFilteringFactor + accelerationX * (1.0 - kFilteringFactor);
accelerationY = acceleration.y * kFilteringFactor + accelerationY * (1.0 - kFilteringFactor);
// keep the raw reading, to use during calibrations
currentRawReading = atan2(accelerationY, accelerationX);
С учетом систем координат UIAcceleration и atan2 , есть несколько факторов, которые необходимо учитывать при расчете желаемого поворота вида:
- Когда устройство находится в вертикальном положении,
atan2
вернет -π / 2 (-90 °), поскольку входной гравитационный вектор равен {0,0, -1,0, 0,0}. CGAffineTransformMakeRotation
создает преобразование, которое будет вращаться по часовой стрелке (в iOS) на указанное число радиан, но необработанноеугол от atan2
указывает вращение против часовой стрелки.
Соответственно, вы захотите повернуть ваш вид на - (currentRawReading + π / 2), предполагая, что его родительский вид ориентирован с экраном в портретной ориентации:
view.transform = CGAffineTransformMakeRotation(-(currentRawReading + M_PI/2));