iOS粒子路径移动效果 iOS实现QQ拖动效果
发布时间 - 2026-01-11 02:28:06 点击率:次粒子效果,QQ拖动效果,实现很简单,具体代码如下

一、图示
二、分析
我们要实现的如果如上面的图示,那么我们可以按照下面的步骤操作:
第一步:我们的红点其实是一个UIButton。创建一个BageValueView继承自UIButton
第二步:初始化的时候,初始化控件,设置圆角,修改背景、文字颜色
第三步:添加手势。在手势的处理中我们,我们需要让当前控件随着手指移动而移动。
第四步:控件一开始创建的时候,其实有两个圆,一个就是我们能够拖动的大圆,另外一个就是原始位置上会改变大小的圆。这一步骤中,主要就是创建这个小圆,它的初始参数和大圆一样。
在手势的处理中,根据两圆的位置,来计算小圆半径,当两圆的位置大于最大位置时候,小圆隐藏掉。
//获取两个圆之间的距离
CGFloat distance = [self distanceWithSmallCircle:self.smallCircle bigCircle:self];
if(distance<=MAX_DIST){//只有距离不超过最大距离才计算小圆半径
//计算小圆的半径
//小圆半径最小的时候是MIN_RADIUS,这个时候两个圆达到最大距离MAX_DIST
//小圆半径最大的时候是原始半径,这个时候两圆距离是0
//处于前面两者之间的时候,小圆的半径是:MIN_RADIUS + (原始半径 - MIN_RADIUS)/MAX_DIST * (MAX_DIST - 当前的距离)
CGFloat smallR = self.bounds.size.width * 0.5;
smallR = MIN_RADIUS + (MAX_DIST-distance) * (smallR-MIN_RADIUS)/MAX_DIST;
//重新设置小圆的尺寸
self.smallCircle.bounds = CGRectMake(0, 0, smallR*2, smallR*2);
//重新设置小圆的半径
self.smallCircle.layer.cornerRadius = smallR;
}else{//超过了最大距离
self.smallCircle.hidden = YES;
}
第五步:创建大小圆之间的连接部分。连接部分我们需要创建一个形状图层(CAShapeLayer)——它可以根据一个路径生成一个形状。
路径分析如下图
根据上面我们需要创建一个 ABCDA 其中DA和BC是曲线,控制点分别为O和P。
第六步:当手势结束的时候,我们需要判断当前两圆的位置,如果小圆最大距离,那么复位。如果大于最大距离,那么添加一个销毁动画。
三、代码
2.1 BageValueView.m
//
// BageValueView.m
// 03_UIView78_粒子效果2
//
// Created by 杞文明 on 17/7/22.
// Copyright © 2017年 杞文明. All rights reserved.
//
#import "BageValueView.h"
#define MAX_DIST 80
#define MIN_RADIUS 5
@interface BageValueView()
@property (nonatomic, weak) UIView *smallCircle;
@property (nonatomic, weak) CAShapeLayer *shap;
@end
@implementation BageValueView
-(void)awakeFromNib{
[self setUp];
}
-(instancetype)initWithFrame:(CGRect)frame{
if ( self = [super initWithFrame:frame] ) {
[self setUp];
}
return self;
}
//形状图层
-(CAShapeLayer*)shap{
if(_shap == nil){
//形状图层,它可以根据一个路径生成一个形状
CAShapeLayer *shap = [CAShapeLayer layer];
//设置形状填充色
shap.fillColor = [UIColor redColor].CGColor;
_shap = shap;
//添加到最底层
[self.superview.layer insertSublayer:shap atIndex:0];
}
return _shap;
}
//初始化
-(void)setUp{
//设置圆角
self.layer.cornerRadius = self.bounds.size.width * 0.5;
//设置背景文字颜色
[self setBackgroundColor:[UIColor redColor]];
[self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
self.titleLabel.font = [UIFont systemFontOfSize:12];
//添加手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
[self addGestureRecognizer:pan];
//添加小圆
UIView *smallCircle = [[UIView alloc]initWithFrame:self.frame];
smallCircle.backgroundColor = self.backgroundColor;
smallCircle.layer.cornerRadius = self.layer.cornerRadius;
self.smallCircle = smallCircle;
//把小圆添加到父控件中,并且在大圆下面
[self.superview insertSubview:smallCircle belowSubview:self];
}
-(void)pan:(UIPanGestureRecognizer*)pan{
//获取当前点
CGPoint currentP = [pan translationInView:self];
//移动
CGPoint center = self.center;
center.x += currentP.x;
center.y += currentP.y;
self.center = center;
//复位
[pan setTranslation:CGPointZero inView:self];
//获取两个圆之间的距离
CGFloat distance = [self distanceWithSmallCircle:self.smallCircle bigCircle:self];
if(distance<=MAX_DIST){//只有距离不超过最大距离才计算小圆半径
//计算小圆的半径
//小圆半径最小的时候是MIN_RADIUS,这个时候两个圆达到最大距离MAX_DIST
//小圆半径最大的时候是原始半径,这个时候两圆距离是0
//处于前面两者之间的时候,小圆的半径是:MIN_RADIUS + (原始半径 - MIN_RADIUS)/MAX_DIST * (MAX_DIST - 当前的距离)
CGFloat smallR = self.bounds.size.width * 0.5;
smallR = MIN_RADIUS + (MAX_DIST-distance) * (smallR-MIN_RADIUS)/MAX_DIST;
//重新设置小圆的尺寸
self.smallCircle.bounds = CGRectMake(0, 0, smallR*2, smallR*2);
//重新设置小圆的半径
self.smallCircle.layer.cornerRadius = smallR;
}else{//超过了最大距离
self.smallCircle.hidden = YES;
[self.shap removeFromSuperlayer];
}
//创建不规则路径,其实就是连个圆之间连接的部分
//小圆不隐藏才创建
if(self.smallCircle.hidden == NO){
UIBezierPath *path = [self pathWithSmallCircle:self.smallCircle bigCircle:self];
self.shap.path = path.CGPath;
}
//当手指松开的时候
if (pan.state==UIGestureRecognizerStateEnded) {
//如果两圆之间的距离小于最大距离,大圆复位
if (distance<MAX_DIST) {
//移除形状图层
[self.shap removeFromSuperlayer];
//添加一个弹性动画
[UIView animateWithDuration:0.25 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{
//大圆复位
self.center = self.smallCircle.center;
} completion:^(BOOL finished) {
//小圆显示
self.smallCircle.hidden = NO;
}];
} else {
//距离大于最大位置的时候,播放动画,按钮从父控件中删除
//添加一个UIImageView 用来播放动画
UIImageView *imageV = [[UIImageView alloc] initWithFrame:self.bounds];
[self addSubview:imageV];
//添加图片
NSMutableArray *imageArray = [NSMutableArray array];
for (int i=1; i<=8; i++) {
NSString *imageName = [NSString stringWithFormat:@"%d",i];
UIImage *image = [UIImage imageNamed:imageName];
[imageArray addObject:image];
}
imageV.animationImages = imageArray;
//设置动画时长
[imageV setAnimationDuration:1];
//开始动画
[imageV startAnimating];
//一秒钟后.把当前的按钮从父控件当中移.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self removeFromSuperview];
});
}
}
}
//计算两个圆之间的距离 使用勾股定理:两直角边的平方和等于斜边的平方
- (CGFloat)distanceWithSmallCircle:(UIView *)smallCircle bigCircle:(UIView *)bigCircle{
//X轴上的偏移量(就是x1-x2的值)
CGFloat offsetX = bigCircle.center.x - smallCircle.center.x;
//y轴上的偏移量(就是y1-y2的值)
CGFloat offsetY = bigCircle.center.y - smallCircle.center.y;
return sqrt(offsetX*offsetX + offsetY*offsetY);
}
//根据两个圆设置一个不规的路径
- (UIBezierPath *)pathWithSmallCircle:(UIView *)smallCircle bigCircle:(UIView *)bigCircle{
CGFloat x1 = smallCircle.center.x;
CGFloat y1 = smallCircle.center.y;
CGFloat x2 = bigCircle.center.x;
CGFloat y2 = bigCircle.center.y;
CGFloat d = [self distanceWithSmallCircle:smallCircle bigCircle:self];
if (d <= 0) {
return nil;
}
CGFloat cosθ = (y2 - y1) / d;
CGFloat sinθ = (x2 - x1) / d;
CGFloat r1 = smallCircle.bounds.size.width * 0.5;
CGFloat r2 = bigCircle.bounds.size.width * 0.5;
CGPoint pointA = CGPointMake(x1 - r1 * cosθ, y1 + r1 * sinθ);
CGPoint pointB = CGPointMake(x1 + r1 * cosθ, y1 - r1 * sinθ);
CGPoint pointC = CGPointMake(x2 + r2 * cosθ, y2 - r2 * sinθ);
CGPoint pointD = CGPointMake(x2 - r2 * cosθ, y2 + r2 * sinθ);
CGPoint pointO = CGPointMake(pointA.x + d * 0.5 * sinθ, pointA.y + d * 0.5 * cosθ);
CGPoint pointP = CGPointMake(pointB.x + d * 0.5 * sinθ, pointB.y + d * 0.5 * cosθ);
UIBezierPath *path = [UIBezierPath bezierPath];
//AB
[path moveToPoint:pointA];
[path addLineToPoint:pointB];
//BC(曲线)
[path addQuadCurveToPoint:pointC controlPoint:pointP];
//CD
[path addLineToPoint:pointD];
//DA(曲线)
[path addQuadCurveToPoint:pointA controlPoint:pointO];
return path;
}
//清空高亮状态
-(void)setHighlighted:(BOOL)highlighted{}
@end
2.2 ViewController.m
//
// ViewController.m
// 03_UIView78_粒子效果2
//
// Created by 杞文明 on 17/7/22.
// Copyright © 2017年 杞文明. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//让View在显示时不要把Autoresizing转成自动布局
self.view.translatesAutoresizingMaskIntoConstraints = NO;
}
@end
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# iOS路径移动
# iOS
# QQ拖动效果
# iOS粒子效果
# iOS实现一个可以在屏幕中自由移动的按钮
# ios实现简单随便移动的AR功能
# 小圆
# 这个时候
# 图层
# 创建一个
# 它可以
# 不超过
# 拖动
# 平方和
# 是一个
# 勾股定理
# 圆角
# 这一
# 偏移量
# 超过了
# 要把
# 我们可以
# 很简单
# 分别为
# 另外一个
# 第二步
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】
Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】
如何在 Telegram Web View(iOS)中防止键盘遮挡底部输入框
Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID
Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】
JavaScript如何实现类型判断_typeof和instanceof有什么区别
谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复
微信小程序 配置文件详细介绍
jimdo怎样用html5做选项卡_jimdo选项卡html5实现与切换效果【指南】
JS碰撞运动实现方法详解
如何打造高效商业网站?建站目的决定转化率
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势
郑州企业网站制作公司,郑州招聘网站有哪些?
悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音
如何快速查询网址的建站时间与历史轨迹?
如何快速上传自定义模板至建站之星?
Laravel怎么连接多个数据库_Laravel多数据库连接配置
如何用AWS免费套餐快速搭建高效网站?
用v-html解决Vue.js渲染中html标签不被解析的问题
如何在万网自助建站平台快速创建网站?
如何挑选优质建站一级代理提升网站排名?
C语言设计一个闪闪的圣诞树
制作企业网站建设方案,怎样建设一个公司网站?
Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置
如何实现建站之星域名转发设置?
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
Windows Hello人脸识别突然无法使用
小米17系列还有一款新机?主打6.9英寸大直屏和旗舰级影像
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?
邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?
南京网站制作费用,南京远驱官方网站?
大型企业网站制作流程,做网站需要注册公司吗?
开心动漫网站制作软件下载,十分开心动画为何停播?
胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?
Python高阶函数应用_函数作为参数说明【指导】
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
Win11怎么修改DNS服务器 Win11设置DNS加速网络【指南】
如何快速搭建支持数据库操作的智能建站平台?
移动端脚本框架Hammer.js
猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?
如何在阿里云虚拟主机上快速搭建个人网站?
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
香港服务器部署网站为何提示未备案?
Laravel如何发送系统通知?(Notification渠道示例)
Laravel怎么创建自己的包(Package)_Laravel扩展包开发入门到发布
Linux网络带宽限制_tc配置实践解析【教程】

