//
// HeartView.h
// Heart
//
// Created by targetcloud on 2017/7/27.
// Copyright © 2017年 targetcloud. 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;
/** 空白宽 默认控件frame的1/8*/
@property (nonatomic,assign) NSInteger spaceWidth;
/** 波幅 默认2*/
@property (nonatomic,assign) NSInteger waveAmplitude;
/** 波动速度 默认50 越小越快*/
@property (nonatomic,assign) CGFloat velocity;
@end
//
// HeartView.m
// Heart
//
// Created by targetcloud on 2017/7/27.
// Copyright © 2017年 targetcloud. All rights reserved.
//
#import "HeartView.h"
@interface HeartView ()
@end
@implementation HeartView
{
CGFloat t;
}
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self loadTimer];
}
return self;
}
- (void)drawRect:(CGRect)rect{
[super drawRect:rect];
/*
//辅助定位代码
UIBezierPath *rectout = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:0];
[rectout setLineCapStyle:kCGLineCapRound];
[rectout setLineWidth:self.lineWidth];
[self.strokeColor set];
[rectout stroke];
*/
CGFloat radius = MIN((self.frame.size.width-self.spaceWidth*2)/4, (self.frame.size.height-self.spaceWidth*2)/4);
CGPoint leftCenter = CGPointMake(self.spaceWidth+radius, self.spaceWidth+radius);
CGPoint rightCenter = CGPointMake(self.spaceWidth+radius*3, self.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];
[heartLine addQuadCurveToPoint:CGPointMake((self.frame.size.width/2), self.frame.size.height-self.spaceWidth*2) controlPoint:CGPointMake(self.frame.size.width-self.spaceWidth, self.frame.size.height*0.6)];
[heartLine addQuadCurveToPoint:CGPointMake(self.spaceWidth, self.spaceWidth+radius)controlPoint:CGPointMake(self.spaceWidth, self.frame.size.height*0.6)];
[heartLine setLineCapStyle:kCGLineCapRound];
[heartLine setLineWidth:self.lineWidth];
[self.strokeColor set];
[heartLine stroke];
[heartLine addClip];
UIBezierPath *waves = [UIBezierPath bezierPath];
CGPoint startPoint = CGPointMake(self.spaceWidth, (self.frame.size.height-3*self.spaceWidth+self.waveAmplitude*2)*(1-self.rate)+self.spaceWidth-self.waveAmplitude);
[waves moveToPoint:startPoint];
for (int i = 0; i<self.frame.size.width-self.spaceWidth*2+self.lineWidth*2; i++) {
CGPoint middlePoint = CGPointMake(startPoint.x+i-self.lineWidth, startPoint.y+self.waveAmplitude*cos(M_PI/self.velocity*i+t));
[waves addLineToPoint:middlePoint];
}
[waves addLineToPoint:CGPointMake(self.frame.size.width-self.spaceWidth, self.frame.size.height-self.spaceWidth*2)];
[waves addLineToPoint:CGPointMake(self.spaceWidth, self.frame.size.height-self.spaceWidth*2)];
[self.fillColor set];
[waves fill];
}
- (NSInteger) spaceWidth{
if (!_spaceWidth){
return MIN(self.frame.size.height,self.frame.size.width)/8;
}
return _spaceWidth;
}
- (NSInteger) waveAmplitude{
if (!_waveAmplitude){
return 2;
}
return _waveAmplitude;
}
- (CGFloat) velocity{
if (!_velocity){
return 50;
}
return _velocity;
}
- (CGFloat)lineWidth{
if (!_lineWidth) {
return 1;
}
return _lineWidth;
}
- (UIColor *)strokeColor{
if(!_strokeColor){
return [UIColor redColor];
}
return _strokeColor;
}
- (UIColor *) fillColor{
if (!_fillColor){
return [UIColor redColor];
}
return _fillColor;
}
- (void)loadTimer{
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[timer fire];
}
- (void)timerAction{
t += M_PI/self.velocity;
if (t == M_PI) {
t = 0;
}
[self setNeedsDisplay];
}
@end
使用
//
// ViewController.m
// Heart
//
// Created by targetcloud on 2017/7/27.
// Copyright © 2017年 targetcloud. 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.4;
heartView.lineWidth = 2;
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.8;
[valueSlider addTarget:self action:@selector(valueChangedAction:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:valueSlider];
UISlider *spaceSlider = [[UISlider alloc]initWithFrame:CGRectMake((self.view.frame.size.width-300)/2, self.view.frame.size.height-120, 300, 50)];
spaceSlider.minimumValue = heartWidth * 0.01;
spaceSlider.maximumValue = heartWidth * 0.25;
spaceSlider.value = heartWidth / 8;
[spaceSlider addTarget:self action:@selector(spaceChangedAction:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:spaceSlider];
}
- (void)spaceChangedAction:(UISlider*)slider{
heartView.spaceWidth = slider.value;
}
- (void)valueChangedAction:(UISlider*)slider{
heartView.rate = slider.value;
}
@end
效果如下
动画效果