iOS粒子路径移动效果 iOS实现QQ拖动效果
程序员文章站
2023-12-21 11:44:10
粒子效果,qq拖动效果,实现很简单,具体代码如下
一、图示
二、分析
我们要实现的如果如上面的图示,那么我们可以按照下面的步骤操作:
第一步:我们的红点其实是一...
粒子效果,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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。