iOS開發示例————使用CAShapeLayer&UIBezierPath繪製資料餅圖
前言借鑑標哥的部落格部分文章:http://www.henishuo.com/ios-cashapelayer-learning/
CAShapeLayer和drawRect的比較:
drawRect:屬於CoreGraphics框架,佔用CPU,效能消耗大,不建議重寫
CAShapeLayer:屬於CoreAnimation框架,通過GPU來渲染圖形,節省效能。動畫渲染直接提交給手機GPU,不消耗記憶體,這兩者各有各的用途,而不是說有了CAShapeLayer就不需要drawRect。
溫馨提示:drawRect只是一個方法而已,是UIView的方法,重寫此方法可以完成我們的繪製圖形功能。
CAShapeLayer與UIBezierPath的關係:
CAShapeLayer中shape代表形狀的意思,所以需要形狀才能生效
貝塞爾曲線可以建立基於向量的路徑,而UIBezierPath類是對CGPathRef的封裝
貝塞爾曲線給CAShapeLayer提供路徑,CAShapeLayer在提供的路徑中進行渲染。路徑會閉環,所以繪製出了Shape,用於CAShapeLayer的貝塞爾曲線作為path,其path是一個首尾相接的閉環的曲線,即使該貝塞爾曲線不是一個閉環的曲線
示例簡介:
在餅圖上顯示陣列中幾個資料各佔有的百分比,SliceLayer是CAShapeLayer的子類,用於構造餅圖的各個扇面和選中某扇面的動畫效果,PieChart是UIView的子類,用於根據陣列的資料情況來設定餅圖的各個扇面和觸控方法,最後在VC中呼叫即可。
示例程式碼:
#import <QuartzCore/QuartzCore.h> #import <UIKit/UIKit.h> @interface SliceLayer : CAShapeLayer @property (nonatomic, assign) CGFloat startAngle; @property (nonatomic, assign) CGFloat endAngle; @property (nonatomic, assign) CGPoint centerPoint; @property (nonatomic, assign) CGFloat radius; @property (nonatomic, assign) BOOL selected; @property (nonatomic, strong) NSString *text; @property (nonatomic, assign) NSInteger tag; - (void)create; @end
#define RandomColor [UIColor colorWithRed:arc4random() % 255 / 255.0 green:arc4random() % 255 / 255.0 blue:arc4random() % 255 / 255.0 alpha:1.0] #import "SliceLayer.h" @implementation SliceLayer - (void)create { UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:_centerPoint]; [path addArcWithCenter:_centerPoint radius:_radius startAngle:_startAngle endAngle:_endAngle clockwise:YES]; [path closePath]; self.path = path.CGPath; self.strokeColor = [UIColor cyanColor].CGColor; self.fillColor = RandomColor.CGColor; } - (void)setSelected:(BOOL)selected { _selected = selected; CGPoint newCenterPoint = _centerPoint; if (selected) { newCenterPoint = CGPointMake(_centerPoint.x + cosf((_startAngle + _endAngle) / 2) * 30, _centerPoint.y + sinf((_startAngle + _endAngle) / 2) * 30); } UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:newCenterPoint]; [path addArcWithCenter:newCenterPoint radius:_radius startAngle:_startAngle endAngle:_endAngle clockwise:YES]; [path closePath]; self.path = path.CGPath; CABasicAnimation *animation = [CABasicAnimation animation]; animation.keyPath = @"path"; animation.toValue = path; animation.duration = 0.5; [self addAnimation:animation forKey:nil]; } @end
#import <UIKit/UIKit.h>
//typedef void(^MyBlock)(CGFloat);
@interface PieChart : UIView
@property (nonatomic, strong) NSArray *datas;
@property (nonatomic, strong) NSMutableArray *sliceLayerArray;
//@property (nonatomic, strong) MyBlock angleBlock;
@end
#import "PieChart.h"
#import "SliceLayer.h"
@implementation PieChart {
CGFloat percentage;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.sliceLayerArray = @[].mutableCopy;
}
return self;
}
- (void)setDatas:(NSArray *)datas {
_datas = datas;
CGFloat startAngle = 0;
CGFloat endAngle = 0;
for (int i = 0; i < datas.count; i++) {
percentage = [datas[i] floatValue];
CGFloat angle = percentage * M_PI * 2;
endAngle = angle + startAngle;
SliceLayer *sliceLayer = [[SliceLayer alloc] init];
sliceLayer.startAngle = startAngle;
sliceLayer.endAngle = endAngle;
sliceLayer.radius = 100.0f;
sliceLayer.centerPoint = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
sliceLayer.tag = i;
[sliceLayer create];
[self.layer addSublayer:sliceLayer];
[self.sliceLayerArray addObject:sliceLayer];
CATextLayer *textLayer = [CATextLayer layer];
textLayer.frame = CGRectMake(sliceLayer.centerPoint.x + cosf((startAngle + endAngle) / 2) * 50 - 15, sliceLayer.centerPoint.y + sinf((startAngle + endAngle) / 2) * 50 - 10, 40, 20);
textLayer.string = [NSString stringWithFormat:@"%1.f%%", percentage * 100];
textLayer.fontSize = 17;
textLayer.contentsScale = 2;
[sliceLayer addSublayer:textLayer];
startAngle = endAngle;
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CGPoint touchPoint = [[touches anyObject] locationInView:self];
for (SliceLayer *slice in _sliceLayerArray) {
//判斷選擇區域
if (CGPathContainsPoint(slice.path, 0, touchPoint, YES)) {
slice.selected = YES;
// self.angleBlock((slice.endAngle - slice.startAngle) / 2 / M_PI);
} else {
slice.selected = NO;
}
}
}
#import "ViewController.h"
#import "PieChart.h"
@class PieChart;
@interface ViewController () {
CAShapeLayer *shapeLayer;
NSTimer *timer;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
PieChart *pieChart = [[PieChart alloc] initWithFrame:self.view.bounds];
pieChart.datas = @[@0.1, @0.2, @0.3, @0.25, @0.1, @0.05];
pieChart.backgroundColor = [UIColor orangeColor];
[self.view addSubview:pieChart];
}
相關推薦
iOS開發示例————使用CAShapeLayer&UIBezierPath繪製資料餅圖
前言借鑑標哥的部落格部分文章:http://www.henishuo.com/ios-cashapelayer-learning/ CAShapeLayer和drawRect的比較: drawRect:屬於CoreGraphics框架,佔用CPU,效能消耗大,不建議重寫CA
iOS開發-聊天氣泡的繪製和聊天訊息列表
iOS開發中什麼最重要?流媒體?即時通訊?還是其他什麼技術?其實都不是,最重要的東西誠然只是iOS的基礎,比如畫一個按鈕,封裝一個控制元件,擴充套件一個類等等。這些東西看似簡單,實則很難,所有的技術都基於這些最基礎的東西,今天要說的是聊天氣泡的繪製,和做一個簡單
ios開發中的4種資料持久化方式
iOS中的永久儲存,也就是在關機重新啟動裝置,或者關閉應用時,不會丟失資料。在實際開發應用時,往往需要持久儲存資料的,這樣使用者才能在對應用進行操作後,再次啟動能看到自己更改的結果與痕跡。ios開發中,我們需要資料持久化這一種技術,也需要不斷在實際開發的工作與學習中完善資
iOS開發總結之UITableView表格資料的批量操作
1.效果圖 2.關鍵程式碼 #import "DealsViewController.h" #import "Deal.h" #import "DealCell.h" @interface DealsViewController () <UITableViewD
iOS開發中對JSON解析資料的處理
在網上看到一個例子,對JSON解析出來的資料處理的方法非常簡單,而且通用,把我對它理解的思路寫一下。 首先介紹下JSON解析,JSON解析出來的資料只有陣列和物件兩種結構。 objective - c中用字典來儲存物件資訊。key值對應物件名字,value值對應物件的值。在
iOS開發-------塗鴉板(UIBezierPath 貝賽爾曲線)與 MVC初嘗試
塗鴉板,顧名思義就是能夠在上面畫點東西,貝賽爾曲線(UIBezierPath),也可以叫做貝賽爾路徑。因為path的直譯就是路徑,看起來很高大上,之前樓主也確實這麼認為的,很高大上,細細瞭解,其實也不難,畢竟難的東西蘋果都給我們封裝好了。初次用MVC模式來
iOS 簡單的使用UIBezierPath繪製
UIBezierPath這個類呢主要用於繪圖。 之前的專案中需要繪圖的部分都是用Core Graphics來繪製,OC是我的第一門語言,所以對於Core Graphics的C語言API不太適應,最近發現原來蘋果的UIKit中已經對Core Graphics做了一些簡單的
iOS開發中,對請求資料出現的一些簡單處理
這裡呢是整理的一位老鳥的東西,好東西得分享 大致實現思路就是迴圈便利做比較,如果發現是NSNull型別的就把值改為空字串;這樣的好處就是當資料請求回來,刪除一下資料裡面為<null>型別的東西,避免在直接取的時候產生程式崩潰問題; 兩個方法,一個返回NSA
iOS開發——定制圓形頭像與照相機圖庫的使用
agen dem gen 聲明 rom 觀察者 sof one picker 如今的App都很流行圓形的頭像,比方QQ右上角的頭像,今日頭條的頭像等等。這已經成為App設計的趨勢了。今天我們就來簡單實現一下這個功能,我還會把從手機拍照中或者圖庫中取出作為頭
解決使用echarts做動態資料餅圖展示中data如何傳值的問題
** 解決使用echarts做動態資料餅圖展示中data如何傳值的問題 ** 如圖,將所查出的資料以餅圖形式展示 下面是頁面data的傳值方法 這是data,請忽略data裡的那些值。那是用來測試用的, 首先將從資料庫查出的資料裝到兩個list裡面,再通過json傳到前臺。
簡單死資料餅圖
效果圖: CustomPiechartView繼承View package com.example.piechart.view; import android.content.Context; import android.graphics.Canvas; import an
Android移動開發-使用OpenGL來繪製3D紋理圖的實現
OpenGL(全寫Open Graphics Library)是指定義了一個跨程式語言、跨平臺的程式設計介面規格的專業的圖形程式介面。它用於三維影象(二維的亦可),是一個功能強大,呼叫方便的底層圖形庫。 OpenGL是行業領域中最為廣泛接納的 2D/
R繪製3D餅圖
二維餅圖程式碼如下:#繪製2維餅圖 x=read.delim("C:/Users/a/Desktop/sample.txt",header=FALSE) #讀入文字資料 names(x)=c("word
Android使用j4lChartAndroid外掛繪製3D餅圖
圖表是常見的直觀表示資料的途徑,目前在android手機上繪製圖表基本有兩種方法:一是利用java的canvas自己繪製,這種方法自己可操作性強,可以隨心所欲地繪製,但是缺點就是工作量大;二是利用第三方外掛。本文將給大家介紹一下利用第三方外掛j4lChartAndroid如
【視覺化】pandas與matplotlib繪製環形餅圖
匯入相關庫 import pandas as pd import matplotlib.pyplot as plt % matplotlib inline 生產測試資料 data = pd.D
iOS開發之初:根據一張gif圖,返回其中每一幀的圖片陣列(ImageView載入gif))
在APP開發過程中能用到gif圖的地方無非就是重新整理和載入動畫了(等用到小動畫的地方).但是UIImageView是無法直接載入gif圖的,ImageView提供了一個載入動畫圖片陣列的方法..那要有很多幀.png/.jpg的圖片才行…但是像我這種沒有美工的開
iOS圖形繪製 UIBezierPath 繪製折線圖、柱狀圖、餅形圖
iOS圖形繪製 UIBezierPath 繪製折線圖、柱狀圖以及餅形圖(感謝Mr_Wendao,如果想檢視餅形圖原始碼請點選連線,餅形圖我借鑑了Mr_Wendao的程式碼學習,再次感謝)。 先看一下程式碼的效果圖 如下圖 下面是主要程式碼 在初始化
iOS開發之Runtime常用示例總結
開發一、構建Runtime測試用例本篇博客的內容是依托於實例的,所以我們在本篇博客中先構建我們的測試類,Runtime將會對該類進行相關的操作。下方就是本篇博客所涉及Demo的目錄,上面的RuntimeKit類是講Runtime常用的功能進行了簡單的封裝,而下方的TestClass以及相關的類目就是我們Run
iOS開發技巧之:獲取ios相簿gif圖片 原資料
<AssetsLibrary/AssetsLibrary.h> 從Safari上儲存了一張動態GIF到本地的相簿中可以確定,儲存到本地相簿的動態GIF沒有問題,只是iPhone的相簿不能顯示動態GIF然後在自己的應用中,要可以選擇GIF圖片上傳到伺服器用UIImagePickerCo
iOS開發技巧之:iOS判斷兩個陣列中資料是否相同
IOS開發之判斷兩個陣列中資料是否相同例項詳解 前言: 工作中遇到的問題,這裡記錄下,也許能幫助到大家 例項程式碼: ? 1