news 2026/8/21 15:31:26

如何用 Dance 实现可拖拽进度动画?交互式 scrubbing 动画完整实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何用 Dance 实现可拖拽进度动画?交互式 scrubbing 动画完整实战

如何用 Dance 实现可拖拽进度动画?交互式 scrubbing 动画完整实战

【免费下载链接】DanceA radical & elegant animation library for iOS.项目地址: https://gitcode.com/gh_mirrors/dance1/Dance

在 iOS 开发中,可拖拽进度动画是视频播放器、音乐 App、视频剪辑工具里最常见的交互形式——用户拖动进度条,画面实时跟随。Dance正是为此而生的 iOS 动画库:它基于 iOS 10 的UIViewPropertyAnimator,一行view.dance.animate { ... }即可创建动画,并能随时暂停、反向、scrubbing(拖动进度)预览。本文将以完整实战的方式,教你从零实现一个交互式 scrubbing 动画

Dance 动画库是什么?为什么天生适合做拖拽进度动画?🎯

Dance 是一款radical & elegant的 iOS 动画库,把UIViewPropertyAnimator的强大能力封装成了极其优雅的链式 API。它的核心理念是:动画一旦创建,就"附着"在视图上,你可以在任何能引用到该视图的地方,随时控制这段动画。

circle.dance.animate(duration: 2.0, curve: .easeInOut) { $0.center = endPosition $0.backgroundColor = .systemBlue }.start()

正是这种"动画可被外部引用控制"的设计,让 Dance 做 scrubbing 动画得心应手——进度条拖到哪,动画就渲染到哪,全程无缝衔接。核心实现只有单个文件,非常适合阅读:Dance.swift。

什么是 scrubbing 动画?拖拽进度动画的核心原理 🔍

Scrubbing 一词源自视频剪辑:像拖动播放器进度条一样,把动画"进度"拖到任意位置。在UIViewPropertyAnimator中,这对应fractionComplete属性(0 表示动画起点,1 表示终点)。

Dance 把它封装成了直观的progress属性(源码见 Dance.swift):

概念说明
progress = 0动画处于起始状态
progress = 0.5动画正好进行到一半
progress = 1动画到达终点

💡 理解这一点后,实现可拖拽进度动画就只剩"把手指/滑块的位置换算成 0~1 的数字"这一步了。

环境准备:最快安装 Dance 动画库的方法 ⚡

Dance 要求iOS 10+、Swift 3+,安装方式二选一:

方式一:CocoaPods(推荐)

platform :ios, '10.0' target 'YourProject' do use_frameworks! pod 'Dance' end

方式二:直接拖入源码—— 将 Dance.swift 拖入 Xcode 工程,同样可用。

如果想把示例工程跑起来对照学习,也可以直接 clone 仓库https://gitcode.com/gh_mirrors/dance1/Dance,打开DanceExample.xcodeproj即可体验官方演示(一个圆形视图沿直线运动,用滑块实时拖拽进度)。

第一步:创建一段可被拖拽的动画 🎬

先创建一段"待命"的动画。注意:.animate {}只是定义动画,不会立刻播放:

import Dance // 用 UIKit 内置曲线(easeInOut / easeIn / easeOut / linear) circle.dance.animate(duration: 2.0, curve: .linear) { $0.center = endPosition }.addCompletion { position in print("动画结束位置:\(position)") } // 需要时再启动 circle.dance.start()

Dance 还支持四种时序方式:UIKit 内置曲线、UISpringTimingParameters弹簧参数、自定义三次贝塞尔曲线、dampingRatio阻尼比,你可以在 README.md 的 Usage 章节找到全部写法。

第二步:核心代码——用 progress 实现交互式 scrubbing 🚀

创建好动画后,拖拽进度的核心代码只有一行:

// 方式一:直接给 progress 赋值 circle.dance.progress = 0.5 // 方式二:链式调用 setProgress(支持 Int / Float / Double / CGFloat) circle.dance.setProgress(to: 0.5)

你可能好奇:如果动画还没启动,直接设置进度会怎样?Dance 做了很贴心的处理——在 Dance.swift 中,setFractionComplete会自动启动并立即暂停动画,然后才设置进度,确保动画始终能被拖拽。这就是 Dance 的 "forgiving"(宽容)哲学:替你兜住错误,绝不崩溃。

第三步:用 UISlider 驱动拖拽进度动画(完整实战)🎛️

现在把滑块接到动画上。在 Storyboard 中放一个取值范围0.0 ~ 1.0UISlider,然后:

@IBAction func sliderValueChanged(_ sender: UISlider) { // slider.value 恰好是 0~1,直接映射为动画进度 circle.dance.setProgress(to: sender.value) }

拖动滑块时,动画会实时、无缝地跟随到对应位置——一个可拖拽进度动画就完成了!官方示例工程就是这么实现的(见 ViewController.swift),它用了一个 10 秒的线性动画,滑块拖到哪儿,圆球就停在哪儿,效果非常直观。

第四步:暂停、反向与完成——动画生命周期全控制 🕹️

拖拽之外,Dance 还提供了完整的动画控制组合拳:

circle.dance.pause() // 暂停动画 circle.dance.reverse() // 像倒放视频一样反向播放 circle.dance.isReversed = true // 等价写法 circle.dance.finish(at: .current) // 结束动画,渲染在当前位置并触发完成回调

配合addCompletion,你可以在动画结束(.end)、回到起点(.start)或停在当前进度(.current)时执行后续逻辑。例如拖拽松手后,让动画从当前进度继续播放到终点,就是播放器类 App 最常见的交互。

进阶:结合 UIPanGestureRecognizer 实现手指拖拽 scrubbing ✋

滑块之外,更"原生"的做法是用手势直接拖拽。核心思路是把手指位移换算成 0~1 的进度:

@objc func handlePan(_ gesture: UIPanGestureRecognizer) { let translation = gesture.translation(in: view) // 把 300pt 的位移映射为 0~1 的动画进度,并做边界裁剪 let progress = min(max(translation.x / 300, 0), 1) circle.dance.setProgress(to: progress) if gesture.state == .ended { // 松手后:进度超过一半则播完,否则倒放回起点 circle.dance.progress > 0.5 ? circle.dance.start() : circle.dance.reverse() } }

这种"拖拽 + 松手回弹"的交互,正是视频剪辑、卡片滑动等场景的标配体验。

常见问题与调试技巧 🔧

  • 控制不生效?先检查circle.dance.hasAnimation是否为true——动画结束后,关联的 animator 会被移除,需要重新创建。
  • 看不到报错崩溃?这是 Dance 的宽容设计。例如对没有动画的视图调用.start(),它只会打印:** Dance Error: view with dance.tag = <tag> does not have an active animation! **,而不会闪退。
  • 想追踪动画状态?circle.dance.state.active/.inactive)、circle.dance.isRunning即可实时监控。

总结 ✨

借助 Dance 动画库,实现可拖拽进度动画只需三步:创建动画 → 把交互位置换算成 0~1 → 调用setProgress。相比手写CAAnimation或直接操作UIViewPropertyAnimator,Dance 的链式 API 让代码更简洁、更易维护,也让交互式 scrubbing 动画变得人人都能轻松上手。现在就打开示例工程 ViewController.swift 亲手试一试吧!

【免费下载链接】DanceA radical & elegant animation library for iOS.项目地址: https://gitcode.com/gh_mirrors/dance1/Dance

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/21 15:21:27

Outfit 字体上手指南:9 个字重如何快速统一你的品牌视觉

Outfit 字体上手指南&#xff1a;9 个字重如何快速统一你的品牌视觉 【免费下载链接】Outfit-Fonts The most on-brand typeface 项目地址: https://gitcode.com/gh_mirrors/ou/Outfit-Fonts Outfit 字体是一个主打"品牌感"的开源几何无衬线字体系列&#xff…

作者头像 李华
网站建设 2026/8/21 15:19:18

电商销售报表有哪些?七张核心报表助力电商运营决策

"一个做电商运营的朋友问我&#xff1a;我想做一套完整的销售报表&#xff0c;但不知道需要做哪些。我说&#xff1a;你先说说你现在最想看什么数据。他说&#xff1a;每天销售额多少、哪个商品卖得好、目标进度如何、退款率怎么样。我说&#xff1a;那你需要的不是一张报…

作者头像 李华
网站建设 2026/8/21 15:19:10

LLM智能体安全:内存控制流攻击原理与防御实战

1. 从存储到操控&#xff1a;LLM智能体面临的新型内存控制流攻击最近在折腾LangChain和LlamaIndex这类LLM智能体框架时&#xff0c;我一直在思考一个核心问题&#xff1a;我们给智能体“喂”了那么多上下文&#xff08;Context&#xff09;&#xff0c;让它记住了对话历史、工具…

作者头像 李华