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

SwiftUI视频时间线拖拽问题:实现位移式拖动而非定位拖动

SwiftUI视频时间线拖拽交互修正方案

问题核心

你遇到的问题是直接将拖拽的绝对坐标赋值给矩形偏移,没有记录点击时光标与矩形的相对位置,导致矩形瞬间跳转到光标所在位置。

解决思路

要实现像PowerDirector那样的拖拽逻辑,需在拖拽开始时记录两个关键信息:

  • 矩形当前的初始偏移量
  • 光标相对于矩形左边缘的水平位置(即点击点在矩形内的x坐标)
    拖拽过程中,通过当前光标位置 - 相对位置计算矩形新的偏移量,确保矩形跟随拖拽位移移动,而非直接跳转到光标位置。

完整代码示例

import SwiftUI

struct VideoTimelineView: View {
    // 视频片段的水平偏移量
    @State private var videoOffset: CGFloat = 0
    // 存储拖拽起始信息:(矩形初始偏移, 光标相对矩形的X位置)
    @State private var dragStartData: (initialOffset: CGFloat, touchRelativeX: CGFloat)?
    
    var body: some View {
        VStack {
            // 时间线背景
            Rectangle()
                .fill(Color.gray.opacity(0.2))
                .frame(height: 60)
                .overlay(
                    // 模拟视频片段的灰色矩形
                    Rectangle()
                        .fill(Color.gray)
                        .frame(width: 150, height: 50)
                        .offset(x: videoOffset)
                        .gesture(
                            DragGesture()
                                .onChanged { gesture in
                                    if dragStartData == nil {
                                        // 拖拽开始时记录初始状态
                                        let relativeTouchX = gesture.location.x - videoOffset
                                        dragStartData = (videoOffset, relativeTouchX)
                                    }
                                    // 计算新偏移:当前光标位置 - 相对位置,保证矩形跟随拖拽位移移动
                                    let newOffset = gesture.location.x - dragStartData!.touchRelativeX
                                    videoOffset = newOffset
                                }
                                .onEnded { _ in
                                    // 拖拽结束清空记录
                                    dragStartData = nil
                                }
                        )
                )
        }
        .padding()
    }
}

struct VideoTimelineView_Previews: PreviewProvider {
    static var previews: some View {
        VideoTimelineView()
    }
}

额外优化(可选)

如果需要限制视频片段不能拖出时间线边界,可以在设置videoOffset时添加边界判断:

// 获取时间线可用宽度(减去左右padding)
let timelineWidth = UIScreen.main.bounds.width - 40
// 最大允许偏移:时间线宽度 - 视频片段宽度
let maxOffset = timelineWidth - 150
// 限制偏移在0到maxOffset之间
videoOffset = max(0, min(newOffset, maxOffset))

这样就能实现符合预期的拖拽交互,点击视频任意位置拖动时,视频会按照拖拽的位移量平稳移动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 22:07:27