news 2026/7/14 7:32:09

PullToBounce核心组件解析:BallView与WaveView动画原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PullToBounce核心组件解析:BallView与WaveView动画原理

PullToBounce核心组件解析:BallView与WaveView动画原理

【免费下载链接】PullToBounceAnimated "Pull To Refresh" Library for UIScrollView. Inspired by https://dribbble.com/shots/1797373-Pull-Down-To-Refresh项目地址: https://gitcode.com/gh_mirrors/pu/PullToBounce

PullToBounce是一款为UIScrollView打造的动画刷新库,它通过BallView与WaveView两个核心组件实现了极具视觉冲击力的"下拉刷新"效果。本文将深入解析这两个组件的动画原理,帮助开发者理解其工作机制并应用到自己的iOS项目中。

BallView:带动画效果的球形加载指示器

BallView是PullToBounce中负责显示加载状态的核心组件,它通过组合多个CALayer实现了复杂的动画效果。该组件位于项目的PullToBounce/Source/BallView.swift文件中。

核心结构与初始化

BallView的初始化过程中创建了一个可移动的视图容器(circleMoveView)和一个圆形图层(circleLayer):

let circleMoveView = UIView() circleMoveView.frame = CGRect(x: 0, y: 0, width: moveUpDist, height: moveUpDist) circleMoveView.center = CGPoint(x: frame.width/2, y: frame.height + circleSize / 2) self.addSubview(circleMoveView) circleLayer = CircleLayer( size: circleSize, moveUpDist: moveUpDist, superViewFrame: circleMoveView.frame, color: color ) circleMoveView.layer.addSublayer(circleLayer)

这里的circleLayer是一个自定义的CAShapeLayer子类,它包含了一个旋转指示器(spiner),用于在加载过程中显示旋转动画。

动画实现原理

BallView的动画主要包括两个阶段:

  1. 上升动画:当用户下拉触发刷新时,BallView会向上移动指定距离
  2. 旋转动画:上升到指定位置后,内部的SpinerLayer开始旋转,显示加载状态

上升动画通过CABasicAnimation实现位置变化:

func moveUp(_ distance: CGFloat) { let move = CABasicAnimation(keyPath: "position") move.fromValue = NSValue(cgPoint: position) move.toValue = NSValue(cgPoint: CGPoint(x: position.x, y: position.y - distance)) move.duration = upDuration move.timingFunction = timeFunc move.fillMode = CAMediaTimingFillMode.forwards move.isRemovedOnCompletion = false self.add(move, forKey: move.keyPath) }

旋转动画则由SpinerLayer负责,它通过strokeEnd和strokeStart的动画组合实现了一个不断旋转且逐渐绘制的圆环效果:

func animation() { self.isHidden = false let rotate = CABasicAnimation(keyPath: "transform.rotation.z") rotate.fromValue = 0 rotate.toValue = Double.pi * 2 rotate.duration = 1 rotate.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) rotate.repeatCount = HUGE self.add(rotate, forKey: rotate.keyPath) strokeEndAnimation() }

WaveView:实现弹性波浪效果

WaveView是PullToBounce中负责实现下拉时波浪形变效果的组件,其源代码位于PullToBounce/Source/WaveView.swift。

波浪路径生成

WaveView的核心是通过UIBezierPath创建一个可变形的波浪形状。它使用二次贝塞尔曲线(quadCurve)来实现波浪效果:

func wavePath(amountX:CGFloat, amountY:CGFloat) -> CGPath { let w = self.frame.width let h = self.frame.height let centerY:CGFloat = 0 let bottomY = h let topLeftPoint = CGPoint(x: 0, y: centerY) let topMidPoint = CGPoint(x: w / 2 + amountX, y: centerY + amountY) let topRightPoint = CGPoint(x: w, y: centerY) let bottomLeftPoint = CGPoint(x: 0, y: bottomY) let bottomRightPoint = CGPoint(x: w, y: bottomY) let bezierPath = UIBezierPath() bezierPath.move(to: bottomLeftPoint) bezierPath.addLine(to: topLeftPoint) bezierPath.addQuadCurve(to: topRightPoint, controlPoint: topMidPoint) bezierPath.addLine(to: bottomRightPoint) return bezierPath.cgPath }

通过改变topMidPoint的位置,WaveView可以创建不同幅度的波浪形状。

弹性回弹动画

当用户释放下拉操作时,WaveView会执行一个弹性回弹动画,通过CAKeyframeAnimation实现一系列平滑过渡的路径变化:

let values = [ self.wavePath(amountX: positionX, amountY: positionY), self.wavePath(amountX: -(positionX * 0.7), amountY: -(positionY * 0.7)), self.wavePath(amountX: positionX * 0.4, amountY: positionY * 0.4), self.wavePath(amountX: -(positionX * 0.3), amountY: -(positionY * 0.3)), self.wavePath(amountX: positionX * 0.15, amountY: positionY * 0.15), self.wavePath(amountX: 0.0, amountY: 0.0) ] bounce.values = values bounce.duration = bounceDuration

这种"衰减振动"效果模拟了真实物理世界中的弹性行为,使动画更加自然生动。

组件协作流程

PullToBounce的完整动画效果是BallView和WaveView协同工作的结果:

  1. 用户下拉UIScrollView,WaveView根据下拉距离生成相应的波浪形状
  2. 当下拉距离达到阈值时,BallView开始执行上升动画
  3. BallView上升到指定位置后,启动内部的旋转加载动画
  4. 数据加载完成后,BallView执行下降动画回到初始位置
  5. 同时,WaveView执行弹性回弹动画,恢复到初始状态

这种组合动画创造了视觉上的层次感和流畅的用户体验,使简单的刷新操作变得生动有趣。

集成与使用

要在自己的项目中使用PullToBounce,首先需要克隆仓库:

git clone https://gitcode.com/gh_mirrors/pu/PullToBounce

然后将Source目录下的核心文件添加到你的项目中。通过PullToBounceWrapper类可以轻松地为UIScrollView或其子类(如UITableView)添加动画刷新效果。

BallView和WaveView的设计遵循了单一职责原则,使其易于维护和扩展。开发者可以通过修改颜色、大小、动画时长等参数,轻松定制符合自己应用风格的刷新效果。

通过理解这两个核心组件的动画原理,开发者不仅可以更好地使用PullToBounce库,还能从中学习到复杂iOS动画的实现技巧,应用到自己的项目中。

【免费下载链接】PullToBounceAnimated "Pull To Refresh" Library for UIScrollView. Inspired by https://dribbble.com/shots/1797373-Pull-Down-To-Refresh项目地址: https://gitcode.com/gh_mirrors/pu/PullToBounce

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

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

企业财务数字化转型:OCR票据识别与智能合同管理解决方案

1. 企业财务数字化转型的痛点与解决方案财务票据和合同管理一直是企业运营中最繁琐的环节之一。我见过太多财务部门被堆积如山的纸质票据淹没的场景——发票分类、信息录入、归档存储,这些工作不仅耗时耗力,还容易出错。更糟的是,当需要查询某…

作者头像 李华
网站建设 2026/7/14 7:29:30

Phrase ListPhrase深度解析:构建优雅的逗号分隔列表

Phrase ListPhrase深度解析:构建优雅的逗号分隔列表 【免费下载链接】phrase Phrase is an Android string resource templating library 项目地址: https://gitcode.com/gh_mirrors/ph/phrase Phrase是一个强大的Android字符串资源模板库,而List…

作者头像 李华
网站建设 2026/7/14 7:28:35

PARD2-Qwen3-8B社区支持:如何参与贡献与获取最新更新

PARD2-Qwen3-8B社区支持:如何参与贡献与获取最新更新 【免费下载链接】PARD2-Qwen3-8B 项目地址: https://ai.gitcode.com/hf_mirrors/amd/PARD2-Qwen3-8B PARD2-Qwen3-8B是一个基于Qwen3-8B的目标对齐并行草稿模型,专为双模式推测解码而设计。作…

作者头像 李华
网站建设 2026/7/14 7:28:21

YOLOv11在电动车违规行为检测中的应用与实践

1. 项目概述:电动车骑行规范识别系统的核心价值电动车骑行规范识别系统是当前智慧交通领域的热门研究方向。这个毕设项目采用YOLOv11算法实现了一套完整的电动车违规行为检测方案,能够实时识别骑行过程中不戴头盔、违规载人、闯红灯等典型违规行为。我在…

作者头像 李华
网站建设 2026/7/14 7:25:33

遗传算法实战三要素:初始化、适应度函数与收敛控制

1. 这不是教科书里的遗传算法,而是我调试了73次后才敢写的实操指南“遗传算法”这四个字,听上去像生物课上讲DNA双螺旋时顺带提的一句术语,又像AI面试题里那个永远答不全的“请手推交叉概率公式”。但真实情况是:我在工业质检系统…

作者头像 李华