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

SwiftUI中如何实现数组文本的曲线形状滚动?

SwiftUI实现曲线文本滚动(无需额外框架)

核心思路

借助SwiftUI原生的GeometryReader获取容器尺寸,结合rotationEffect和offset把每个文本元素映射到目标曲线上,再通过ScrollView或动画实现滚动效果。下面以二次曲线为例,你可以根据需求替换成其他曲线公式。

完整实现代码

import SwiftUI

struct CurvedScrollingText: View {
    // 示例文本数组
    let textItems = ["文本1", "文本2", "文本3", "文本4", "文本5", "文本6", "文本7", "文本8"]
    // 曲线参数:控制弯曲程度,可按需调整
    private let curveFactor: CGFloat = 0.001
    // 滚动偏移量,控制滚动动画逻辑
    @State private var scrollOffset: CGFloat = 0
    
    var body: some View {
        GeometryReader { geo in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 40) {
                    ForEach(textItems, id: \.self) { text in
                        Text(text)
                            .font(.title)
                            .foregroundColor(.white)
                            .padding(.vertical, 8)
                            .padding(.horizontal, 16)
                            .background(Color.blue)
                            .cornerRadius(8)
                            // 根据元素位置计算曲线偏移量
                            .offset(y: calculateCurveY(position: getElementPosition(text), width: geo.size.width))
                            // 计算旋转角度,让文本贴合曲线切线
                            .rotationEffect(Angle(degrees: calculateRotation(position: getElementPosition(text), width: geo.size.width)))
                    }
                }
                .padding(.horizontal, geo.size.width / 2)
                .offset(x: scrollOffset)
                .onAppear {
                    // 自动循环滚动动画
                    withAnimation(.linear(duration: 15).repeatForever(autoreverses: false)) {
                        scrollOffset = -(CGFloat(textItems.count) * 100 + geo.size.width)
                    }
                }
            }
            .background(Color.green.opacity(0.3))
            .frame(height: 200)
        }
    }
    
    // 获取元素在数组中的位置索引
    private func getElementPosition(_ text: String) -> CGFloat {
        guard let index = textItems.firstIndex(of: text) else { return 0 }
        return CGFloat(index)
    }
    
    // 二次曲线计算Y轴偏移:y = k*(x - mid)^2,调整数值让曲线居中
    private func calculateCurveY(position: CGFloat, width: CGFloat) -> CGFloat {
        let elementWidth: CGFloat = 100 // 单个文本元素的总宽度(含间距)
        let x = position * elementWidth - width / 2
        return curveFactor * x * x - 50
    }
    
    // 根据曲线导数计算旋转角度,保证文本与曲线贴合自然
    private func calculateRotation(position: CGFloat, width: CGFloat) -> Double {
        let elementWidth: CGFloat = 100
        let x = position * elementWidth - width / 2
        let slope = 2 * curveFactor * x
        return atan(Double(slope)) * 180 / .pi
    }
}

struct CurvedScrollingText_Previews: PreviewProvider {
    static var previews: some View {
        CurvedScrollingText()
    }
}

关键说明

  • 曲线映射:通过二次曲线公式计算每个文本的Y偏移,curveFactor值越小,曲线越平缓。
  • 文本旋转:利用曲线导数计算切线斜率,将文本旋转对应角度,避免文本倾斜突兀。
  • 滚动逻辑:通过ScrollView结合offset动画实现自动滚动,也可去掉动画改成手动拖拽滚动。
  • 无额外依赖:完全基于SwiftUI原生API实现,不需要引入第三方框架。

自定义调整方向

  • 修改curveFactor可以改变曲线的弯曲程度。
  • 替换calculateCurveY中的公式,可实现圆形、正弦曲线等不同形状的滚动效果。
  • 调整spacing、元素尺寸和动画时长,适配不同布局需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:12:40