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

近来无事,想想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。

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

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

(0)

相关推荐

  • iOS绘制3D饼图的实现方法

    实现核心 1.压缩饼图,使饼图有3D的效果,并不是真正的画了个3D圆柱 2.绘制厚度,带阴影效果,让看上去像是圆柱的高 3.路径添加好了,用颜色填充后绘制一下,添加阴影后还需绘制一遍 饼图添加阴影的思考 之前这加阴影的一段不是很明白,为啥设颜色和阴影都要draw一次 进过反复的测试,我自己分析了一下,每次draw一下想当于,把当前的设置画出来,再次draw就在这基础上,再画最近的设置,这里加颜色和阴影就像是一层一层的画上去.要是不draw的话,再设置颜色相当于重新设置了颜色,之前设置的颜色就无效

  • IOS绘制动画颜色渐变折线条

    先给大家展示下效果图: 概述 现状 折线图的应用比较广泛,为了增强用户体验,很多应用中都嵌入了折线图.折线图可以更加直观的表示数据的变化.网络上有很多绘制折线图的demo,有的也使用了动画,但是线条颜色渐变的折线图的demo少之又少,甚至可以说没有.该Blog阐述了动画绘制线条颜色渐变的折线图的实现方案,以及折线图线条颜色渐变的实现原理,并附以完整的示例. 成果 本人已将折线图封装到了一个UIView子类中,并提供了相应的接口.该自定义折线图视图,基本上可以适用于大部分需要集成折线图的项目.若你

  • iOS开发中使用Quartz2D绘制上下文栈和矩阵的方法

    上下文栈 一.qurza2d是怎么将绘图信息和绘图的属性绘制到图形上下文中去的? 说明: 新建一个项目,自定义一个view类和storyboard关联后,重写该类中的drowrect方法. 画线的三个步骤: (1)获取上下文 (2)绘图 (3)渲染 要求:画两条单独的线 代码和效果图: 复制代码 代码如下: - (void)drawRect:(CGRect)rect {     //获取上下文     CGContextRef ctx=UIGraphicsGetCurrentContext();

  • IOS绘制虚线的方法总结

    一.重写drawRect方法. - (void)drawRect:(CGRect)rect { [super drawRect:rect]; CGContextRef currentContext = UIGraphicsGetCurrentContext(); //设置虚线颜色 CGContextSetStrokeColorWithColor(currentContext, [UIColor BlackColor].CGColor); //设置虚线宽度 CGContextSetLineWidt

  • iOS使用Charts框架绘制饼状图

    首先先看一下效果: 饼状图 一.创建饼状图对象 创建饼状图对象用到类是PieChartView.h, 代码如下: self.pieChartView = [[PieChartView alloc] init]; self.pieChartView.backgroundColor = BgColor; [self.view addSubview:self.pieChartView]; [self.pieChartView mas_makeConstraints:^(MASConstraintMak

  • iOS动画之向右拉的抽屉3D效果

    首先我们忽略掉3D效果,先要做的是一个右拉的抽屉效果. 总体思路: 1.创建一个ContainerViewController容器控制器,然后把左侧选择菜单的SideMenuViewController,和右侧负责显示内容的MainViewController 添加到ContainerViewController中. 2.给容器控制器ContainerViewController添加一个手势监听,通过修改偏移量完成抽屉效果. 3.设置anchorPoint,给左侧SideMenuViewCont

  • iOS使用Charts框架绘制柱形图

    首先看一下最终要实现的效果: 最终效果 一.初始化barChartView 绘制柱形图需要用到BarChartView这个类,下面是初始化代码: self.barChartView = [[BarChartView alloc] init]; self.barChartView.delegate = self;//设置代理 [self.view addSubview:self.barChartView]; [self.barChartView mas_makeConstraints:^(MASC

  • 利用iOS绘制图片生成随机验证码示例代码

    先来看看效果图 实现方法 .h文件 @property (nonatomic, retain) NSArray *changeArray; @property (nonatomic, retain) NSMutableString *changeString; @property (nonatomic, retain) UILabel *codeLabel; -(void)changeCode; @end .m文件 @synthesize changeArray = _changeArray;

  • IOS 实现3D 浮动效果动画

    涉及到的技术点 CATransform3DRotate 转换坐标系 整体视图的层级结构 tvOSCardView cardImageView cardParallaxView 转换坐标系的代码 CGFloat xFactor = MIN(1, MAX(-1, (touchPoint.x - (self.bounds.size.width / 2)) / (self.bounds.size.width / 2))); CGFloat yFactor = MIN(1, MAX(-1, (touchP

  • iOS App开发中用CGContextRef绘制基本图形的基本示例

    Graphics Context是图形上下文,也可以理解为一块画布,我们可以在上面进行绘画操作,绘制完成后,将画布放到我们的view中显示即可,view看作是一个画框. CGContextRef功能强大,我们借助它可以画各种图形.开发过程中灵活运用这些技巧,可以帮助我们提供代码水平. 首先创建一个集成自UIView的,自定义CustomView类. 在CustomView.m中实现代码. 复制代码 代码如下: #import <QuartzCore/QuartzCore.h> 覆盖DranRe

随机推荐