You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中实现图片绕圆周旋转并保持屏幕垂直朝上

解决SwiftUI图片绕圆周旋转时保持屏幕直立的问题

问题描述

我有三张图片分布在圆周的不同位置,希望它们沿顺时针方向绕圆周旋转,同时全程相对于屏幕保持直立状态。当前代码能实现顺时针旋转,但图片移动时是相对于圆心直立,而非屏幕。试过给旋转角度加负号,结果只是变成逆时针旋转,没解决直立问题。

原代码

import SwiftUI

struct AnotherCircleTry: View {
    @State private var rotationAngle = 0.0

    var body: some View {
        VStack {
            Spacer()
            Text("Rotating images!")
            Spacer()

            ZStack {
                Circle()
                    .stroke()
                    .frame(width: 250, height: 250)
                    .hidden()

                // Image 1
                Image("image-1")
                    .resizable()
                    .frame(width: 50, height: 50)
                    .clipShape(Circle())
                    .offset(x: cos(CGFloat(rotationAngle) / 180.0 * .pi) * 100,
                            y: sin(CGFloat(rotationAngle) / 180.0 * .pi) * 100)
                    .rotationEffect(.degrees(rotationAngle), anchor: .center)

                // Image 2
                Image("image-2")
                    .resizable()
                    .frame(width: 50, height: 50)
                    .clipShape(Circle())
                    .offset(x: cos(CGFloat(rotationAngle) / 180.0 * .pi) * 100,
                            y: sin(CGFloat(rotationAngle) / 180.0 * .pi) * 100)
                    .rotationEffect(.degrees((rotationAngle + 120)), anchor: .center)

                // Image 3
                Image("image-3")
                    .resizable()
                    .frame(width: 50, height: 50)
                    .clipShape(Circle())
                    .offset(x: cos(CGFloat(rotationAngle) / 180.0 * .pi) * 100,
                            y: sin(CGFloat(rotationAngle) / 180.0 * .pi) * 100)
                    .rotationEffect(.degrees((rotationAngle + 240)), anchor: .center)
            }
            .padding(.horizontal)
            
            Spacer()
        }
        .onAppear {
            withAnimation(Animation.linear(duration: 8).repeatForever(autoreverses: false)) {
                rotationAngle += 360
            }
        }
    }
}

#Preview{
        AnotherCircleTry()
}

解决方案

问题核心在于当前的rotationEffect让图片跟着圆周旋转方向同步转动,导致其相对于圆心直立。要让图片保持屏幕直立,需要给图片反向旋转相同角度,抵消位置变化带来的朝向偏移。

修改后的代码

import SwiftUI

struct AnotherCircleTry: View {
    @State private var rotationAngle = 0.0

    var body: some View {
        VStack {
            Spacer()
            Text("Rotating images!")
            Spacer()

            ZStack {
                Circle()
                    .stroke()
                    .frame(width: 250, height: 250)
                    .hidden()

                // Image 1:反向旋转抵消圆周旋转角度
                Image("image-1")
                    .resizable()
                    .frame(width: 50, height: 50)
                    .clipShape(Circle())
                    .offset(x: cos(CGFloat(rotationAngle) / 180.0 * .pi) * 100,
                            y: sin(CGFloat(rotationAngle) / 180.0 * .pi) * 100)
                    .rotationEffect(.degrees(-rotationAngle), anchor: .center)

                // Image 2:对应初始偏移120度,反向旋转抵消总角度
                Image("image-2")
                    .resizable()
                    .frame(width: 50, height: 50)
                    .clipShape(Circle())
                    .offset(x: cos(CGFloat(rotationAngle + 120) / 180.0 * .pi) * 100,
                            y: sin(CGFloat(rotationAngle + 120) / 180.0 * .pi) * 100)
                    .rotationEffect(.degrees(-(rotationAngle + 120)), anchor: .center)

                // Image 3:对应初始偏移240度,反向旋转抵消总角度
                Image("image-3")
                    .resizable()
                    .frame(width: 50, height: 50)
                    .clipShape(Circle())
                    .offset(x: cos(CGFloat(rotationAngle + 240) / 180.0 * .pi) * 100,
                            y: sin(CGFloat(rotationAngle + 240) / 180.0 * .pi) * 100)
                    .rotationEffect(.degrees(-(rotationAngle + 240)), anchor: .center)
            }
            .padding(.horizontal)
            
            Spacer()
        }
        .onAppear {
            withAnimation(Animation.linear(duration: 8).repeatForever(autoreverses: false)) {
                rotationAngle += 360
            }
        }
    }
}

#Preview{
        AnotherCircleTry()
}

原理说明

  1. 图片通过offset沿圆周移动时,自身朝向会随圆周位置改变而偏移(比如从圆心视角看,图片到上方时会变成横向)
  2. 给图片添加反向的rotationEffect,刚好抵消这个偏移,让图片始终保持相对于屏幕的直立状态
  3. 三张图片初始圆周位置相差120度,因此各自的反向旋转角度需要对应加上初始偏移量的负值

内容的提问来源于stack exchange,提问作者dramadom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 02:15:40