日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】使用Core Graphics绘画一个山寨微信icon

發布時間:2025/7/14 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】使用Core Graphics绘画一个山寨微信icon 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

文章出處:http://www.jianshu.com/p/1008f9803759#

先看最終效果:

- - -

繪畫這個純屬周末雨天無聊,這里使用的都是Core Graphics上很基本的幾個方法,對新手(我也是新手)來說還是有幫助的。下面說下這個繪制過程。

0. 設置背景色

1. 繪制綠色橢圓

2. 繪制綠色三角形

3. 繪制眼睛

4. 繪制白色橢圓

5. 繪制白色三角形

6. 繪制眼睛

7. 就這么簡單

_ _ _

那么,省去創建project的步驟之后我們要做的就是自定義個UIView子類,我們就將它命名為`WechatView`,然后在storyboard上拖動一個`UIView`到視圖控制器上。

接著,為了在繪制過程中能不需要每次都編譯,我們可以使用iOS7之后的一個新特性 `IB_DESIGNABLE` 來時時看到我們的繪畫過程。說到 `IB_DESIGNABLE` 就自然的會聯想到 `IBInspectable`,先淺陋的介紹一下這兩個的作用。首先是 `IB_DESIGNABLE`,如剛才所說,它可以讓我們時時的看到我們的繪制過程,大大的省去了我們編譯的時間,是iOS7上一個超贊的新特性。然后是 `IBInspectable`,它是添加在屬性上的,在屬性上添加上它我們就可以在Xcode的右邊的*Show the Attributes inspector*上看到,并可以自定義這些值(當然,并不是所有的類習慣都支持的,具體有哪些,需要的時候試試便知哈)。

回到正題,現在我們只需要將 `IB_DESIGNABLE` 添加到`WechatView` 的頭文件上即可(當然,你想添加到.m文件上編譯器也不反對)。然后,在這里就添加一個用處不大的屬性bkColor作為背景顏色,如下代碼:

IB_DESIGNABLE

@interface WechatView : UIView

@property(nonatomic, assign)IBInspectable UIColor *bkColor;

@end

這樣,我們就可以在點擊storyboard后,選擇*Show the Identity inspector*上看到下圖:

?

在*Show the Attributes inspector*上看到下圖:

?

現在改變一下bkColor,將它改為灰色。

?

改后當然是看不到視圖改變的,我們得真正的為 `backgoundColor` 這個屬性賦值;或者使用Core Graphices來填充背景。方法一中如果想時時看到改變效果,我們可以添加如下代碼:

- (void)prepareForInterfaceBuilder {

[super prepareForInterfaceBuilder];

self.backgroundColor = self.bkColor;

}

代碼剛上,效果即可見哈,爽

`prepareForInterfaceBuilder` 這個方法是iOS8之后才有的,它就是提供給我們試試查看效果的,但是它只是在當你的view準備被繪制在*Interface Builder*時被執行,換句話說就是程序運行時它是不被調用的。==command+r==運行下程序我們就可以發現,這是的view背景并不是剛才所看到的灰色。說明`prepareForInterfaceBuilder`確實沒有被調用。(我們可以通過這個方法,省去編譯時間來看我們的繪制效果,然后再將代碼移到我們所要的位置)。這個方法就說到這。

填充背景

還有方法二,也是接下來我們要用到的方法:使用Core Graphices來填充背景。將前面的代碼注釋掉,然后添加如下代碼:

- (void)drawRect:(CGRect)rect {

/*0. 填充背景*/

//將當前context的顏色填充為bkColor

[self.bkColor setFill];

//填充顏色到當前的context上,大小為rect

CGContextFillRect(context, rect);

}

同樣,可以看到`WechatView`的背景變成了灰色。這樣就算開始了第0步繪畫。

繪制綠色橢圓

第1步是開始繪制綠色橢圓,在以上的代碼基礎上繼續添加如下代碼:

//繪制的最小寬度

CGFloat minWidth = MAX(160, rect.size.width);

//定義綠色橢圓位置和大小

CGFloat greenX = 10;

CGFloat greenY = 10;

CGFloat greenCircleWidth = minWidth/1.5;

CGFloat greenCircleHeight = 21.0/24 * greenCircleWidth;

CGFloat gcW = greenCircleWidth;

CGFloat gcH = greenCircleHeight;

//1. 繪制綠色橢圓

UIColor *greenColor = RGB(125, 225, 73, 1);

//將當前context的顏色填充為greenColor

[greenColor setFill];

//繪制并填充橢圓

CGContextFillEllipseInRect(context, CGRectMake(greenX, greenY, greenCircleWidth, greenCircleHeight));

完成了第1步,效果見圖:

繪制綠色三角形

第2步:繪制綠色三角形。通過觀察微信的icon,計算,微調,我們可以添加以下的代碼來繪制這個三角形:

//2. 畫三角形

//橢圓左邊焦點

CGFloat greenCircleFocusLeft = gcW/2-sqrt(pow(gcW/2, 2)-pow(gcH/2, 2));

//橢圓右邊焦點

CGFloat greenCircleFocusRight = gcW/2+sqrt(pow(gcW/2, 2)-pow(gcH/2, 2));

CGFloat gcFL = greenCircleFocusLeft;

CGFloat gcFR = greenCircleFocusRight;

//眼睛大小

CGFloat eyesWidth1 = gcW/7.5;

//2. 畫三角形

CGPoint points[] = {

CGPointMake(gcFL-eyesWidth1, greenY + gcH + (gcFL-eyesWidth1)/12-10),

CGPointMake(greenX+gcW/2+40, 1.2*(greenX+gcW/2) + greenY),

CGPointMake(gcFL+10, 1.8*gcFL + greenY)};

CGContextAddLines(context, points, 3);

CGContextClosePath(context);

//CGContextStrokePath(context);

CGContextFillPath(context);

三角形的三個點的計算花了我不少時間,但是這不是重點,重點是其實很簡單的問題我卻傻X的花了很長時間哈,而且最終還只是湊合的,不是最優解。取消`CGContextStrokePath(context);`這句的注釋,我們可以看到下圖:

注釋掉后即可看到:

?

繪制眼睛

第3步:繪制眼睛。眼睛的位置取的是橢圓焦點的位置,而且繪制后看起來還挺對的。眼睛無非是兩個黑色的圓形。如下:

//3. 畫眼睛(圓)

[RGB(45, 49, 32, 1) setFill];

CGContextFillEllipseInRect(context, CGRectMake(greenX + gcFL, greenY+gcH/4, eyesWidth1, eyesWidth1));

CGContextFillEllipseInRect(context, CGRectMake(greenX + gcFR-eyesWidth1, greenY+gcH/4, eyesWidth1, eyesWidth1));

然后就是這樣了:

?

繪制白色icon

第4,5,6步跟1,2,3步基本是一樣的,只是位置不同而已。

//4. 畫白色橢圓

CGFloat wcX = greenX + gcW / 2;

CGFloat wcY = greenY + gcH / 2;

CGFloat wcW = gcW * 0.8;

CGFloat wcH = gcH * 0.8;

CGFloat whiteCircleFocusLeft = wcW/2-sqrt(pow(wcW/2, 2)-pow(wcH/2, 2));

CGFloat whiteCircleFocusRight = wcW/2+sqrt(pow(wcW/2, 2)-pow(wcH/2, 2));

CGFloat wcFL = whiteCircleFocusLeft;

CGFloat wcFR = whiteCircleFocusRight;

CGFloat eyesWidth2 = wcW/7.5;

UIColor *whiteColor = RGB(251, 251, 251, 1);

[whiteColor setFill];

CGContextFillEllipseInRect(context, CGRectMake(wcX, wcY, wcW, wcH));

//5. 畫白色三角形

CGPoint whiteTrianglePoints[] = {

CGPointMake(wcFR+eyesWidth2/4+wcX, wcY + wcH + (wcFL-eyesWidth2/4)/4),

CGPointMake(wcX+wcW/2, 0.9*(wcX+wcW/2)),

CGPointMake(wcFR+eyesWidth2, 0.9*wcFR + wcY)};

CGContextAddLines(context, whiteTrianglePoints, 3);

CGContextClosePath(context);

CGContextFillPath(context);

//6. 畫眼睛(圓)

[RGB(60, 64, 49, 1) setFill];

CGContextFillEllipseInRect(context, CGRectMake(wcX + wcFL, wcY + wcH/4, eyesWidth2, eyesWidth2));

CGContextFillEllipseInRect(context, CGRectMake(wcX + wcFR - eyesWidth2, wcY + wcH/4, eyesWidth2, eyesWidth2));

OK,現在就長這樣了,咋一看還是挺像的哈。

添加陰影

下面我們再添加一些細節上的東西。比如我們發現少了陰影,還有微信的icon上的三角形是圓角的。首先是陰影:在`CGFloat minWidth = MAX(160, rect.size.width);`這句之上加上下面的代碼:

//陰影

CGContextSetShadowWithColor(context, CGSizeMake(-0.5, 0.5), 6, [UIColor blackColor].CGColor);

陰影是加上了,但是并不是我們想要的效果。怎樣才能讓它只是在邊緣上加陰影呢?也很簡單,繼續在剛才添加的語句下添加:

CGContextBeginTransparencyLayer(context, nil);

?

搞定,感覺還行哈,不過眼睛的陰影好像也沒了。試試用同樣的方法看能不能解決:在第3步畫眼睛之前添加:

CGContextEndTransparencyLayer(context);

//為綠色橢圓的眼睛添加陰影

CGContextSetShadowWithColor(context, CGSizeMake(-0.5, 0.5), 2, [UIColor blackColor].CGColor);

然后在第3步畫完眼睛之后添加:

CGContextBeginTransparencyLayer(context, nil);

再然后在第6步畫眼睛之前添加上:

//為白色橢圓的眼睛添加陰影

CGContextSetShadowWithColor(context, CGSizeMake(-0.5, 0.5), 2, [UIColor blackColor].CGColor);

這樣說有點亂,注意到了:`CGContextBeginTransparencyLayer(context, nil)` 和 `CGContextEndTransparencyLayer(context)` 是成對出現的,從函數名稱可以知道它們的作用分別是開始一個透明的layer和結束一個透明的layer。而夾在它們中間的繪圖操作在指定的context上被合成到一個完全透明的背景(在context中作為一個分離的目標緩沖區)。這個操作會保持context原有的裁剪區域。調用了`Begin`之后除了1.全局的透明度被設置為1;2.陰影被屏蔽外,其他的都不變。這樣解釋后,上面的代碼應該可以理解了。現在我們的icon看起來是這樣的:

圓角三角形

最后,解決下圓角三角形的問題:回到第2步,將`CGContextFillPath(context);`注釋,并添加以下代碼:

CGContextSetLineJoin(context, kCGLineJoinRound);

CGContextSetLineWidth(context, 4);

CGContextSetStrokeColorWithColor(context, greenColor.CGColor);

CGContextDrawPath(context, kCGPathFillStroke);

然后同理在第5步畫白色三角形上注釋`CGContextFillPath(context);`,并添加以下代碼:

CGContextSetLineJoin(context, kCGLineJoinRound);

CGContextSetLineWidth(context, 3);

CGContextSetStrokeColorWithColor(context, whiteColor.CGColor);

CGContextDrawPath(context, kCGPathFillStroke);

好了,廢話說完了,也算是完成了,最終效果:

?

實際上,微信的icon的顏色還是一個漸變的,在這里就不繼續研究了,要實現漸變可以用`CGContextDrawLinearGradient(CGContextRef context, CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options)`或`CGContextDrawRadialGradient(CGContextRef context, CGGradientRef gradient, CGPoint startCenter, CGFloat startRadius, CGPoint endCenter, CGFloat endRadius, CGGradientDrawingOptions options)`這兩個函數。

bug 修復

command+r 編譯+運行以下(現在才需要編譯,這也太好了吧),然后發現成功的crash了。

?

什么原因?好吧,我把屬性定義成 `assign` 了(低級錯誤),改成`strong` ,問題解決。

結束語

以上就是我繪制的整個編碼過程,繪制微信icon實際上就用了core graphics的幾個基本功能,希望能對初學者有所幫助,說錯的地方也希望能得到指點哈~~

源碼地址:https://github.com/linshaolie/blog/tree/master/DrawWechatIcon

轉載于:https://www.cnblogs.com/panyuluoye/p/4954972.html

總結

以上是生活随笔為你收集整理的【转】使用Core Graphics绘画一个山寨微信icon的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。