首页 > 系统 > iOS > 正文

iOS绘制专属于程序猿的浪漫爱心

2020-07-26 03:26:48
字体:
来源:转载
供稿:网友

近来无事,想想IT该怎样才能彰显浪漫情怀,不能口头上说说而已,最关键的是要有可视化的东西展示出来才行~

废话不多说,直接上Demo

HeartView.h

//// HeartView.h// DrawHeart//// Created by WQL on 16/3/1.// Copyright © 2016年 WQL. All rights reserved.//#import <UIKit/UIKit.h>@interface HeartView : UIView/** * 比率 */@property (nonatomic,assign) CGFloat rate;/** * 填充的颜色 */@property (nonatomic,strong) UIColor *fillColor;/** * 线条的颜色 */@property (nonatomic,strong) UIColor *strokeColor;/** * 线条的宽度 */@property (nonatomic,assign) CGFloat lineWidth;@end

HeartView.m文件:

//// HeartView.m// DrawHeart//// Created by WQL on 16/3/1.// Copyright © 2016年 WQL. All rights reserved.//#import "HeartView.h"//间距NSInteger const spaceWidth = 5;//波浪的振幅NSInteger const waveAmplitude = 5;@interface HeartView (){  CGFloat t;}@end@implementation HeartView- (instancetype)initWithFrame:(CGRect)frame{  self = [super initWithFrame:frame];  if (self) {    [self loadTimer];  }  return self;}- (void)drawRect:(CGRect)rect{  [super drawRect:rect];    //上面的两个半圆 半径为整个frame的四分之一  CGFloat radius = MIN((self.frame.size.width-spaceWidth*2)/4, (self.frame.size.height-spaceWidth*2)/4);    //左侧圆心 位于左侧边距+半径宽度  CGPoint leftCenter = CGPointMake(spaceWidth+radius, spaceWidth+radius);  //右侧圆心 位于左侧圆心的右侧 距离为两倍半径  CGPoint rightCenter = CGPointMake(spaceWidth+radius*3, spaceWidth+radius);    //左侧半圆  UIBezierPath *heartLine = [UIBezierPath bezierPathWithArcCenter:leftCenter radius:radius startAngle:M_PI endAngle:0 clockwise:YES];  //右侧半圆  [heartLine addArcWithCenter:rightCenter radius:radius startAngle:M_PI endAngle:0 clockwise:YES];    //曲线连接到新的底部顶点 为了弧线的效果,控制点,坐标x为总宽度减spaceWidth,刚好可以相切,平滑过度 y可以根据需要进行调整,y越大,所画出来的线越接近内切圆弧  [heartLine addQuadCurveToPoint:CGPointMake((self.frame.size.width/2), self.frame.size.height-spaceWidth*2) controlPoint:CGPointMake(self.frame.size.width-spaceWidth, self.frame.size.height*0.6)];    //用曲线 底部的顶点连接到左侧半圆的左起点 为了弧线的效果,控制点,坐标x为spaceWidth,刚好可以相切,平滑过度。y可以根据需要进行调整,y越大,所画出来的线越接近内切圆弧(效果是越胖)  [heartLine addQuadCurveToPoint:CGPointMake(spaceWidth, spaceWidth+radius) controlPoint:CGPointMake(spaceWidth, self.frame.size.height*0.6)];    //线条处理  [heartLine setLineCapStyle:kCGLineCapRound];  //线宽  [self setHeartLineWidthWithPath:heartLine];  //线条的颜色  [self setHeartStrokeColor];    //根据坐标点连线  [heartLine stroke];  //clipToBounds 切掉多余的部分  [heartLine addClip];      //初始化波浪的构成  UIBezierPath *waves = [UIBezierPath bezierPath];    //首先 把起始点设置为左侧 x坐标为spaceWidth 心形从下往上填充,y坐标需要满足一定的函数关系式,当rate为0时,位置为总高度-2倍的留白距离(spaceWidth)+波浪的振幅;当rate为1时,位置为留白距离(spaceWidth)-振幅。由这两个状态构建函数表达式,即可得到如下表达式  CGPoint startPoint = CGPointMake(spaceWidth, (self.frame.size.height-3*spaceWidth+waveAmplitude*2)*(1-self.rate)+spaceWidth-waveAmplitude);  [waves moveToPoint:startPoint];    //关键的地方来了 波浪线怎么画?  //首先,x坐标是从左往右连续的 y坐标是起始的高度加上一定的波动 这里选择了cos函数。5是波动的幅度大小,50控制的是波峰的间距,t是为了让其动起来,随时间发生波动  for (int i = 0; i<self.frame.size.width-spaceWidth*2+self.lineWidth*2; i++) {    //x是要考虑线宽的 不然的话,会导致填充的宽度不够 y就是在某个值附近波动    CGPoint middlePoint = CGPointMake(spaceWidth+i-self.lineWidth, startPoint.y+waveAmplitude*cos(M_PI/50*i+t));        [waves addLineToPoint:middlePoint];  }    //画波浪线的右端 到底部的垂直线  [waves addLineToPoint:CGPointMake(self.frame.size.width-spaceWidth*2, self.frame.size.height-spaceWidth*2)];  //画右侧底部的点 到达左侧底部的点之间的横线  [waves addLineToPoint:CGPointMake(spaceWidth, self.frame.size.height-spaceWidth*2)];  //设置填充颜色  [self setHeartFillColor];  //填充  [waves fill];  }//设置线条宽度 默认为1- (void)setHeartLineWidthWithPath:(UIBezierPath*)path{  CGFloat lineW;  if (self.lineWidth) {    lineW = self.lineWidth;  }else{    lineW = 1;  }    [path setLineWidth:lineW];}//设置线条颜色- (void)setHeartStrokeColor{  UIColor *strokColor;  if (self.strokeColor) {    strokColor = self.strokeColor;  }else{    strokColor = [UIColor blackColor];  }    [strokColor set];}//设置填充的颜色- (void)setHeartFillColor{  UIColor *fillColor;  if (self.fillColor) {    fillColor = self.fillColor;  }else{    fillColor = [UIColor orangeColor];  }    [fillColor set];}//为了实现动态的效果,加一个Timer- (void)loadTimer{  NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];  [timer fire];}//t 是一个影响波浪线的参数,每次修改之,再画,则每次的都不一样,则有动态的效果- (void)timerAction{  t += M_PI/50;    if (t == M_PI) {    t = 0;  }  //修改了t之后 要调用draw方法  [self setNeedsDisplay];}@end一些关键点,我已经注释啦~

下面就是看看怎么使用这个视图了:

ViewController.m中:

//// ViewController.m// DrawHeart//// Created by WQL on 16/3/1.// Copyright © 2016年 WQL. All rights reserved.//#import "ViewController.h"#import "HeartView.h"NSInteger const heartWidth = 200;NSInteger const heartHeight = 200;@interface ViewController (){ HeartView *heartView;}@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; heartView = [[HeartView alloc]initWithFrame:CGRectMake((self.view.frame.size.width-heartWidth)/2, (self.view.frame.size.height-heartHeight)/2, heartWidth, heartHeight)]; heartView.rate = 0.5; heartView.lineWidth = 1; heartView.strokeColor = [UIColor blackColor]; heartView.fillColor = [UIColor redColor]; heartView.backgroundColor = [UIColor clearColor]; [self.view addSubview:heartView];  [self loadSlider];}- (void)loadSlider{ UISlider *valueSlider = [[UISlider alloc]initWithFrame:CGRectMake((self.view.frame.size.width-300)/2, self.view.frame.size.height-150, 300, 50)]; valueSlider.minimumValue = 0.0; valueSlider.maximumValue = 1.0; valueSlider.value = 0.5; [valueSlider addTarget:self action:@selector(valueChangedAction:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:valueSlider];}- (void)valueChangedAction:(UISlider*)slider{ heartView.rate = slider.value;}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end

这里我添加了一个slider,为了实现随意设置爱心填充的rate。

哈,下面就是看看效果了:

以上就是本文的全部内容,希望对大家的学习有所帮助,快点制作属于自己浪漫爱心送给自己吧。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表