当前位置: 移动技术网 > IT编程>移动开发>IOS > iOS仿支付宝芝麻信用分数仪表盘动画效果

iOS仿支付宝芝麻信用分数仪表盘动画效果

2019年07月24日  | 移动技术网IT编程  | 我要评论

艺术照网站,逆之魔魂,普洱汽车站

先看看效果图:

仪表盘动画效果.jpg

1.圆环上绿点的旋转

2.分数值及提示语的变化

3.背景色的变化

直接上主要代码:

1.自定义zldashboardview仪表盘文件:

.h 文件:

/**
 * 根据跃动数字
 *
 * 确定百分比
 * 现在的跳动数字——>背景颜色变化
 *
 */

#import <uikit/uikit.h>
@interface zldashboardview : uiview
@property (nonatomic, strong) uiimage *bgimage;
@property (nonatomic, copy) void(^timerblock)(nsinteger);

/**
 * 跃动数字刷新
 *
 */
- (void)refreshjumpnofromno:(nsstring *)startno tono:(nsstring *)tono;

@end

.m 文件

#import "zldashboardview.h"
#import "uiview+extensions.h" 

#define degreestoradians(x) (m_pi*(x)/180.0) //把角度转换成pi的方式
static const cgfloat kmarkerradius = 5.f; // 光标直径
static const cgfloat ktimerinterval = 0.03;
static const cgfloat kfastproportion = 0.9;

static const nsinteger maxnumber = 1000;

@interface zldashboardview () {
  cgfloat animationtime;
  nsinteger beginno;
  nsinteger jumpcurrentno;
  nsinteger endno;
}

// 百分比 0 - 100 根据跃动数字设置
@property (nonatomic, assign) cgfloat percent;

@property (nonatomic, strong) cashapelayer *bottomlayer; // 进度条底色
@property (nonatomic, assign) cgfloat linewidth; // 弧线宽度

@property (nonatomic, strong) uiimageview *markerimageview; // 光标

@property (nonatomic, strong) uiimageview *bgimageview; // 背景图片

@property (nonatomic, assign) cgfloat circelradius; //圆直径
@property (nonatomic, assign) cgfloat startangle; // 开始角度
@property (nonatomic, assign) cgfloat endangle; // 结束角度

@property (nonatomic, strong) uilabel *showlable; // 跳跃数字
@property (nonatomic, strong) uilabel *markedlabel; // 提示语
@property (nonatomic, strong) nstimer *fasttimer;
@property (nonatomic, strong) nstimer *slowtimer;

@property (nonatomic, assign) nsinteger intervalnum;

@end

@implementation zldashboardview

#pragma mark - life cycle

- (instancetype)initwithframe:(cgrect)frame {

  self = [super initwithframe:frame];
  if (self) {
    self.backgroundcolor = [uicolor clearcolor];

    self.circelradius = self.frame.size.width - 10.f;
    self.linewidth = 2.f;
    self.startangle = -200.f;
    self.endangle = 20.f;

    // 尺寸需根据图片进行调整
    self.bgimageview.frame = cgrectmake(6, 6, self.circelradius, self.circelradius * 2 / 3);
    self.bgimageview.backgroundcolor = [uicolor clearcolor];
    [self addsubview:self.bgimageview];

    //添加圆框
    [self setupcirclebg];

    //光标
    [self setupmarkerimageview];

    //添加跃动数字 及 提示语
    [self setupjumpnoview];
  }
  return self;
}


- (void)setupcirclebg {

  // 圆形路径
  uibezierpath *path = [uibezierpath bezierpathwitharccenter:cgpointmake(self.width / 2, self.height / 2)
                            radius:(self.circelradius - self.linewidth) / 2
                          startangle:degreestoradians(self.startangle)
                           endangle:degreestoradians(self.endangle)
                           clockwise:yes];

  // 底色
  self.bottomlayer = [cashapelayer layer];
  self.bottomlayer.frame = self.bounds;
  self.bottomlayer.fillcolor = [[uicolor clearcolor] cgcolor];
  self.bottomlayer.strokecolor = [[uicolor colorwithred:206.f / 256.f green:241.f / 256.f blue:227.f alpha:1.f] cgcolor];
  self.bottomlayer.opacity = 0.5;
  self.bottomlayer.linecap = kcalinecapround;
  self.bottomlayer.linewidth = self.linewidth;
  self.bottomlayer.path = [path cgpath];
  [self.layer addsublayer:self.bottomlayer];

// 240 是用整个弧度的角度之和 |-200| + 20 = 220
//  [self createanimationwithstartangle:degreestoradians(self.startangle)
//                endangle:degreestoradians(self.startangle + 220 * 1)];
}

- (void)setupmarkerimageview {
  if (_markerimageview) {
    return;
  }
  _markerimageview = [[uiimageview alloc] init];
  _markerimageview.backgroundcolor = [uicolor clearcolor];
  _markerimageview.layer.backgroundcolor = [uicolor greencolor].cgcolor;
  _markerimageview.layer.shadowcolor = [uicolor whitecolor].cgcolor;
  _markerimageview.layer.shadowoffset = cgsizemake(0, 0);
  _markerimageview.layer.shadowradius = kmarkerradius*0.5;
  _markerimageview.layer.shadowopacity = 1;
  _markerimageview.layer.maskstobounds = no;
  self.markerimageview.layer.cornerradius = self.markerimageview.frame.size.height / 2;
  [self addsubview:self.markerimageview];
  _markerimageview.frame = cgrectmake(-100, self.height, kmarkerradius, kmarkerradius);
}

- (void)setupjumpnoview {
  if (_showlable) {
    return;
  }
  cgfloat width = self.circelradius / 2 + 50;
  cgfloat height = self.circelradius / 2 - 50;
  cgfloat xpixel = self.bgimageview.left + (self.bgimageview.width - width)*0.5;//self.circelradius / 4;
  cgfloat ypixel = self.circelradius / 4;
  cgrect labelframe = cgrectmake(xpixel, ypixel, width, height);
  _showlable = [[uilabel alloc] initwithframe:labelframe];
  _showlable.backgroundcolor = [uicolor clearcolor];
  _showlable.textcolor = [uicolor greencolor];
  _showlable.textalignment = nstextalignmentcenter;
  _showlable.font = [uifont systemfontofsize:100.f];
  _showlable.text = [nsstring stringwithformat:@"%ld",jumpcurrentno];
  [self addsubview:_showlable];

  // 提示语
  _markedlabel = [[uilabel alloc] initwithframe:cgrectmake(xpixel, cgrectgetmaxy(_showlable.frame), width, 30)];
  _markedlabel.backgroundcolor = [uicolor clearcolor];
  _markedlabel.textcolor = [uicolor greencolor];
  _markedlabel.textalignment = nstextalignmentcenter;
  _markedlabel.font = [uifont systemfontofsize:20.f];
  _markedlabel.text = @"营养良好";
  [self addsubview:_markedlabel];
}

#pragma mark - animation

- (void)createanimationwithstartangle:(cgfloat)startangle endangle:(cgfloat)endangle { // 光标动画

  //启动定时器
  [_fasttimer setfiredate:[nsdate distantpast]];
  // 设置动画属性
  cakeyframeanimation *pathanimation = [cakeyframeanimation animationwithkeypath:@"position"];
  pathanimation.calculationmode = kcaanimationpaced;
  pathanimation.fillmode = kcafillmodeforwards;
  pathanimation.removedoncompletion = no;
  pathanimation.duration = _percent * ktimerinterval;
  pathanimation.timingfunction = [camediatimingfunction functionwithname:kcamediatimingfunctioneaseout];
  pathanimation.repeatcount = 1;

  // 设置动画路径
  cgmutablepathref path = cgpathcreatemutable();
  cgpathaddarc(path, null, self.width / 2, self.height / 2, (self.circelradius - kmarkerradius / 2) / 2, startangle, endangle, 0);
  pathanimation.path = path;
  cgpathrelease(path);

  [self.markerimageview.layer addanimation:pathanimation forkey:@"movemarker"];

}

#pragma mark - setters / getters


/**
 * 开始动画 确定百分比
 *
 */
- (void)refreshjumpnofromno:(nsstring *)startno tono:(nsstring *)tono {

  beginno = 0;//[startno integervalue];
  jumpcurrentno = 0;//[startno integervalue];
  endno = [tono integervalue];
  _percent = endno * 100 / maxnumber;

  nsinteger diffnum = endno - beginno;
  if (diffnum <= 0) {
    return;
  }
  if (diffnum < 100) {
    _intervalnum = 5;
  } else if (diffnum < 300) {
    _intervalnum = 15;
  } else if (diffnum <= maxnumber) {
    _intervalnum = 10;
  }
  nslog(@"数字间隔:%ld",_intervalnum);

  //数字
  [self setupjumpthings];

  // 设置角度
  nsinteger angle = 0;
  nsinteger num = [tono floatvalue] - [startno floatvalue];
  if (num < 200) {
    angle = self.startangle + 220 * (num / 200.0) / 5.0;
  } else if (num < 350) {
    angle = self.startangle + 220 / 5.0 + (3 / 5.0 * 220) * (num - 200) / 150.0;
  } else {
    angle = self.startangle + 220 / 5.0 * 4 + (220 / 5.0) * (num - 350) / 250.0;
  }

  //光标
  [self createanimationwithstartangle:degreestoradians(self.startangle)
                endangle:degreestoradians(angle)];
}

- (void)setbgimage:(uiimage *)bgimage {

  _bgimage = bgimage;
  self.bgimageview.image = bgimage;
}

- (uiimageview *)bgimageview {

  if (nil == _bgimageview) {
    _bgimageview = [[uiimageview alloc] init];
  }
  return _bgimageview;
}

#pragma mark - 跃动数字

- (void)setupjumpthings {

  animationtime = _percent * ktimerinterval;

  self.fasttimer = [nstimer timerwithtimeinterval:ktimerinterval*kfastproportion
                       target:self
                      selector:@selector(fasttimeraction)
                      userinfo:nil
                      repeats:yes];
  [[nsrunloop currentrunloop] addtimer:_fasttimer formode:nsrunloopcommonmodes];

  //时间间隔 = (总时间 - 快时间间隔*变化次数)/ 再次需要变化的次数
  //快时间
  nsinteger fastendno = endno * kfastproportion;

  nsinteger fastjump = fastendno/_intervalnum;
  if (fastjump % _intervalnum) {
    fastjump++;
    fastendno += _intervalnum;
  }
  cgfloat fastttime = fastjump*ktimerinterval*kfastproportion;

  //剩余应跳动次数
  nsinteger changno = endno - fastendno;
  nsinteger endjump = changno / _intervalnum + changno % _intervalnum;
  //慢时间间隔
  nstimeinterval slowinterval = (animationtime - fastttime) / endjump;

  self.slowtimer = [nstimer timerwithtimeinterval:slowinterval
                       target:self
                      selector:@selector(slowtimeraction)
                      userinfo:nil
                      repeats:yes];
  [[nsrunloop currentrunloop] addtimer:_slowtimer formode:nsrunloopcommonmodes];
  [_fasttimer setfiredate:[nsdate distantfuture]];
  [_slowtimer setfiredate:[nsdate distantfuture]];
}

#pragma mark 加速定时器触发事件
- (void)fasttimeraction {
  if (jumpcurrentno >= endno) {
    [self.fasttimer invalidate];
    return;
  }
  if (jumpcurrentno >= endno * kfastproportion) {
    [self.fasttimer invalidate];
    [self.slowtimer setfiredate:[nsdate distantpast]];
    return;
  }
  [self commontimeraction];
}

#pragma mark 减速定时器触发事件
- (void)slowtimeraction {
  if (jumpcurrentno >= endno) {
    [self.slowtimer invalidate];
    return;
  }
  [self commontimeraction];
}

#pragma mark 计时器共性事件 - lable赋值 背景颜色及提示语变化
- (void)commontimeraction {

  if (jumpcurrentno % 100 == 0 && jumpcurrentno != 0) {
    nsinteger colorindex = jumpcurrentno / 100;
    dispatch_async(dispatch_get_main_queue(), ^{
      if (self.timerblock) {
        self.timerblock(colorindex);
      }
    });
  }
  nsinteger changevalueby = endno - jumpcurrentno;

  if (changevalueby/10 < 1) {
    jumpcurrentno++;
  } else {
//    nsinteger changeby = changevalueby / 10;
    jumpcurrentno += _intervalnum;
  }

  _showlable.text = [nsstring stringwithformat:@"%ld",jumpcurrentno];
  if (jumpcurrentno < 350) {
    _markedlabel.text = @"营养太差";
  } else if (jumpcurrentno <= 550) {
    _markedlabel.text = @"营养较差";
  } else if (jumpcurrentno <= 600) {
    _markedlabel.text = @"营养中等";
  } else if (jumpcurrentno <= 650) {
    _markedlabel.text = @"营养良好";
  } else if (jumpcurrentno <= 700) {
    _markedlabel.text = @"营养优秀";
  } else if (jumpcurrentno <= 950) {
    _markedlabel.text = @"营养较好";
  }
}

@end
在所需的当前控制器里展示:

//
// viewcontroller.m
// zldashboard
//
// created by qtx on 16/9/19.
// copyright © 2016年 zl. all rights reserved.
//

#import "viewcontroller.h"
#import "zldashboardview.h"
#import "zlgradientview.h"
#import "uiview+extensions.h"


#define screen_width ([[uiscreen mainscreen] bounds].size.width)
#define screen_height ([[uiscreen mainscreen] bounds].size.height)

#define minnumber 350
#define maxnumber 950


@interface viewcontroller ()

@property (nonatomic, strong) zldashboardview *dashboardview;

@property (nonatomic, strong) zlgradientview * gradientview;

@property (nonatomic, strong) uibutton * clickbtn;

@property (nonatomic, strong) uislider * slider;

@end

@implementation viewcontroller

- (void)viewdidload {
  [super viewdidload];

  //创建背景色
  [self setupgradientview];

  //创建仪表盘
  [self setupcircleview];

  //添加触发动画的点击button
  [self addactionbutton];

  //改变value
  [self addslidechnagevalue];

}

- (void)addactionbutton {
  uibutton *starebutton = [uibutton buttonwithtype:uibuttontypecustom];
  starebutton.frame = cgrectmake(10.f, self.dashboardview.bottom + 50.f, screen_width - 20.f, 38.f);
  [starebutton addtarget:self action:@selector(onstarebuttonclick:) forcontrolevents:uicontroleventtouchupinside];
  [starebutton settitle:@"start animation" forstate:uicontrolstatenormal];
  [starebutton setbackgroundcolor:[uicolor lightgraycolor]];
  starebutton.layer.maskstobounds = yes;
  starebutton.layer.cornerradius = 4.f;
  [self.view addsubview:starebutton];

  _clickbtn = starebutton;
}

- (void)addslidechnagevalue {

  cgfloat width = 280;
  cgfloat height = 40;
  cgfloat xpixel = (screen_width - width) * 0.5;
  cgfloat ypixel = cgrectgetmaxy(_clickbtn.frame) + 20;
  cgrect slideframe = cgrectmake(xpixel, ypixel, width, height);

  uislider *slider = [[uislider alloc] initwithframe:slideframe];

  slider.minimumvalue = minnumber;
  slider.maximumvalue = maxnumber;

  slider.minimumtracktintcolor = [uicolor colorwithred:0.000 green:1.000 blue:0.502 alpha:1.000];
  slider.maximumtracktintcolor = [uicolor colorwithwhite:0.800 alpha:1.000];
  /**
   * 注意这个属性:如果你没有设置滑块的图片,那个这个属性将只会改变已划过一段线条的颜色,不会改变滑块的颜色,如果你设置了滑块的图片,又设置了这个属性,那么滑块的图片将不显示,滑块的颜色会改变(ios7)
   */
  [slider setthumbimage:[uiimage imagenamed:@""] forstate:uicontrolstatenormal];
  slider.thumbtintcolor = [uicolor cyancolor];


  [slider setvalue:0.5 animated:yes];

  [slider addtarget:self action:@selector(slidetap:)forcontrolevents:uicontroleventvaluechanged];

  [self.view addsubview:slider];

  _slider = slider;
}

- (void)slidetap:(uislider *)sender {
  cgfloat value = sender.value;
  nslog(@"%.f",value);
}

- (void)setupgradientview {
  self.gradientview = [[zlgradientview alloc] initwithframe:self.view.bounds];
  [self.view addsubview:self.gradientview];
}

- (void)setupcircleview {
  self.dashboardview = [[zldashboardview alloc] initwithframe:cgrectmake(40.f, 70.f, screen_width - 80.f, screen_width - 80.f)];
  self.dashboardview.bgimage = [uiimage imagenamed:@"backgroundimage"];
  [self.view addsubview:self.dashboardview];
}

- (void)onstarebuttonclick:(uibutton *)sender {

  if (sender.selected) {
    [self.gradientview removefromsuperview];
    self.gradientview = nil;
    [self.dashboardview removefromsuperview];
    self.dashboardview = nil;

    [self setupgradientview];
    [self setupcircleview];

    [self.view bringsubviewtofront:self.clickbtn];
    [self.view bringsubviewtofront:_slider];
  }
  sender.selected = yes;

  cgfloat value = _slider.value;

  nsstring *startno = [nsstring stringwithformat:@"%d", minnumber];
  nsstring *tono = [nsstring stringwithformat:@"%.f",value];//@"693"; 950
  nslog(@"endno:%@",tono);
  [self.dashboardview refreshjumpnofromno:startno tono:tono];

  __block typeof(self)blockself = self;
  self.dashboardview.timerblock = ^(nsinteger index) {
    [blockself.gradientview setupbackgroundcolorwithcolorarrayindex:index];
  };
}

@end

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网