iOS繪制專屬于程序猿的浪漫愛(ài)心
近來(lái)無(wú)事,想想IT該怎樣才能彰顯浪漫情懷,不能口頭上說(shuō)說(shuō)而已,最關(guān)鍵的是要有可視化的東西展示出來(lái)才行~
廢話不多說(shuō),直接上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];
//上面的兩個(gè)半圓 半徑為整個(gè)frame的四分之一
CGFloat radius = MIN((self.frame.size.width-spaceWidth*2)/4, (self.frame.size.height-spaceWidth*2)/4);
//左側(cè)圓心 位于左側(cè)邊距+半徑寬度
CGPoint leftCenter = CGPointMake(spaceWidth+radius, spaceWidth+radius);
//右側(cè)圓心 位于左側(cè)圓心的右側(cè) 距離為兩倍半徑
CGPoint rightCenter = CGPointMake(spaceWidth+radius*3, spaceWidth+radius);
//左側(cè)半圓
UIBezierPath *heartLine = [UIBezierPath bezierPathWithArcCenter:leftCenter radius:radius startAngle:M_PI endAngle:0 clockwise:YES];
//右側(cè)半圓
[heartLine addArcWithCenter:rightCenter radius:radius startAngle:M_PI endAngle:0 clockwise:YES];
//曲線連接到新的底部頂點(diǎn) 為了弧線的效果,控制點(diǎn),坐標(biāo)x為總寬度減spaceWidth,剛好可以相切,平滑過(guò)度 y可以根據(jù)需要進(jìn)行調(diào)整,y越大,所畫(huà)出來(lái)的線越接近內(nèi)切圓弧
[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)];
//用曲線 底部的頂點(diǎn)連接到左側(cè)半圓的左起點(diǎn) 為了弧線的效果,控制點(diǎn),坐標(biāo)x為spaceWidth,剛好可以相切,平滑過(guò)度。y可以根據(jù)需要進(jìn)行調(diào)整,y越大,所畫(huà)出來(lái)的線越接近內(nèi)切圓弧(效果是越胖)
[heartLine addQuadCurveToPoint:CGPointMake(spaceWidth, spaceWidth+radius) controlPoint:CGPointMake(spaceWidth, self.frame.size.height*0.6)];
//線條處理
[heartLine setLineCapStyle:kCGLineCapRound];
//線寬
[self setHeartLineWidthWithPath:heartLine];
//線條的顏色
[self setHeartStrokeColor];
//根據(jù)坐標(biāo)點(diǎn)連線
[heartLine stroke];
//clipToBounds 切掉多余的部分
[heartLine addClip];
//初始化波浪的構(gòu)成
UIBezierPath *waves = [UIBezierPath bezierPath];
//首先 把起始點(diǎn)設(shè)置為左側(cè) x坐標(biāo)為spaceWidth 心形從下往上填充,y坐標(biāo)需要滿足一定的函數(shù)關(guān)系式,當(dāng)rate為0時(shí),位置為總高度-2倍的留白距離(spaceWidth)+波浪的振幅;當(dāng)rate為1時(shí),位置為留白距離(spaceWidth)-振幅。由這兩個(gè)狀態(tài)構(gòu)建函數(shù)表達(dá)式,即可得到如下表達(dá)式
CGPoint startPoint = CGPointMake(spaceWidth, (self.frame.size.height-3*spaceWidth+waveAmplitude*2)*(1-self.rate)+spaceWidth-waveAmplitude);
[waves moveToPoint:startPoint];
//關(guān)鍵的地方來(lái)了 波浪線怎么畫(huà)?
//首先,x坐標(biāo)是從左往右連續(xù)的 y坐標(biāo)是起始的高度加上一定的波動(dòng) 這里選擇了cos函數(shù)。5是波動(dòng)的幅度大小,50控制的是波峰的間距,t是為了讓其動(dòng)起來(lái),隨時(shí)間發(fā)生波動(dòng)
for (int i = 0; i<self.frame.size.width-spaceWidth*2+self.lineWidth*2; i++) {
//x是要考慮線寬的 不然的話,會(huì)導(dǎo)致填充的寬度不夠 y就是在某個(gè)值附近波動(dòng)
CGPoint middlePoint = CGPointMake(spaceWidth+i-self.lineWidth, startPoint.y+waveAmplitude*cos(M_PI/50*i+t));
[waves addLineToPoint:middlePoint];
}
//畫(huà)波浪線的右端 到底部的垂直線
[waves addLineToPoint:CGPointMake(self.frame.size.width-spaceWidth*2, self.frame.size.height-spaceWidth*2)];
//畫(huà)右側(cè)底部的點(diǎn) 到達(dá)左側(cè)底部的點(diǎn)之間的橫線
[waves addLineToPoint:CGPointMake(spaceWidth, self.frame.size.height-spaceWidth*2)];
//設(shè)置填充顏色
[self setHeartFillColor];
//填充
[waves fill];
}
//設(shè)置線條寬度 默認(rèn)為1
- (void)setHeartLineWidthWithPath:(UIBezierPath*)path
{
CGFloat lineW;
if (self.lineWidth) {
lineW = self.lineWidth;
}else{
lineW = 1;
}
[path setLineWidth:lineW];
}
//設(shè)置線條顏色
- (void)setHeartStrokeColor
{
UIColor *strokColor;
if (self.strokeColor) {
strokColor = self.strokeColor;
}else{
strokColor = [UIColor blackColor];
}
[strokColor set];
}
//設(shè)置填充的顏色
- (void)setHeartFillColor
{
UIColor *fillColor;
if (self.fillColor) {
fillColor = self.fillColor;
}else{
fillColor = [UIColor orangeColor];
}
[fillColor set];
}
//為了實(shí)現(xiàn)動(dòng)態(tài)的效果,加一個(gè)Timer
- (void)loadTimer
{
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[timer fire];
}
//t 是一個(gè)影響波浪線的參數(shù),每次修改之,再畫(huà),則每次的都不一樣,則有動(dòng)態(tài)的效果
- (void)timerAction
{
t += M_PI/50;
if (t == M_PI) {
t = 0;
}
//修改了t之后 要調(diào)用draw方法
[self setNeedsDisplay];
}
@end一些關(guān)鍵點(diǎn),我已經(jīng)注釋啦~
下面就是看看怎么使用這個(gè)視圖了:
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
這里我添加了一個(gè)slider,為了實(shí)現(xiàn)隨意設(shè)置愛(ài)心填充的rate。
哈,下面就是看看效果了:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,快點(diǎn)制作屬于自己浪漫愛(ài)心送給自己吧。
相關(guān)文章
IOS開(kāi)發(fā)OC代碼中創(chuàng)建Swift編寫(xiě)的視圖控制器
這篇文章主要介紹了IOS開(kāi)發(fā)OC代碼中創(chuàng)建Swift編寫(xiě)的視圖控制器的相關(guān)資料,需要的朋友可以參考下2017-06-06
iOS如何將UIButton中的圖片與文字上下對(duì)齊詳解
對(duì)于UIButton實(shí)現(xiàn)上顯示圖片,下顯示文字這個(gè)需求估計(jì)各位iOS開(kāi)發(fā)者們都不陌生,所以下面這篇文章主要給大家介紹了關(guān)于iOS如何將UIButton中圖片與文字上下對(duì)齊的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-10-10
仿IOS效果 帶彈簧動(dòng)畫(huà)的ListView
這篇文章主要介紹了仿IOS效果,帶彈簧動(dòng)畫(huà)的ListView,感興趣的小伙伴們可以參考一下2016-01-01
總結(jié)iOS開(kāi)發(fā)中的斷點(diǎn)續(xù)傳與實(shí)踐
本文先從斷點(diǎn)續(xù)傳問(wèn)題開(kāi)始,介紹斷點(diǎn)續(xù)傳概述和原理。接著結(jié)合筆者調(diào)研中嘗試的 AFHTTPRequestOpeartion,簡(jiǎn)單分析源碼。最后分別基于 NSURLConnection,NSURLSessionDataTask 和 NSURLSessionDownloadTask 去實(shí)現(xiàn)應(yīng)用重啟情況下的斷點(diǎn)續(xù)傳。下面一起來(lái)看看。2016-07-07
iOS基于AVFoundation 制作用于剪輯視頻項(xiàng)目
這篇文章主要為大家介紹了利用AVFoundation 制作用于剪輯視頻的項(xiàng)目,可以實(shí)現(xiàn)視頻擴(kuò)展或者回退的功能,感興趣的小伙伴快來(lái)跟隨小編一起學(xué)習(xí)吧2021-12-12
IOS 開(kāi)發(fā)之swift中手勢(shì)的實(shí)例詳解
這篇文章主要介紹了IOS 開(kāi)發(fā)之swift中手勢(shì)的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文大家能掌握IOS手勢(shì)的使用方法,需要的朋友可以參考下2017-09-09

