
簡介(當前版本:1.11.4)
一個專門裁剪圖片、GIF、視頻的輪子,簡單易用,功能豐富(高自由度的參數(shù)設(shè)定、支持旋轉(zhuǎn)和鏡像翻轉(zhuǎn)、蒙版、壓縮等),能滿足絕大部分裁剪的需求。
Feature:
? 能自適應裁剪區(qū)域的縮放;
? 高自由度的參數(shù)設(shè)定,包括裁剪區(qū)域的間距、裁剪寬高比、是否自適應縮放等;
? 支持最多8個拖拽方向的裁剪區(qū)域;
? 支持上左下右的旋轉(zhuǎn);
? 水平和垂直的鏡像翻轉(zhuǎn);
? 兩種邊框樣式;
? 支持圓框裁剪;
? 自定義毛玻璃樣式、邊框顏色、背景顏色、遮罩透明度;
? 自定義邊框圖片;
? 可動態(tài)修改視圖區(qū)域和裁剪區(qū)域間距,支持橫豎屏切換;
? 可自定義蒙版圖片裁剪;
? 可裁剪本地視頻整段畫面或某一幀畫面;
? 可截取某一段本地視頻,裁剪后并轉(zhuǎn)成GIF;
? 可裁剪GIF;
? 可保存當前裁剪狀態(tài);
? 圖片支持N宮格裁剪;
? 兼容Swift&SwiftUI環(huán)境。
TODO:
?? Swift版本;
?? 固定不縮放裁剪區(qū)域;
?? 視頻不再需要修正方向再裁剪;
?? 裁剪遠程視頻;
?? 持久化緩存裁剪歷史;
?? 將視頻裁剪部分(AVFoundation模塊)分離出來;
?? 實現(xiàn)蘋果相冊裁剪功能中的自由拖拽旋轉(zhuǎn)、翻轉(zhuǎn)角度的效果。
注意:由于autoLayout不利于手勢控制,所以目前使用的是frame布局,暫不支持autoLayout。
最新改動
兼容Swift&SwiftUI環(huán)境。

如何使用
初始化
1. 配置初始參數(shù)
可設(shè)置的裁剪元素(圖片、GIF、視頻),只能選擇其中一個,并且不能為nil:
- image:裁剪的圖片/GIF(以UIImage傳入)
- imageData:裁剪的圖片/GIF(以NSData傳入)
- videoURL:裁剪的本地視頻(以NSURL傳入)
- videoAsset:裁剪的本地視頻(以AVURLAsset傳入)
其他部分可配置參數(shù)(更多可查看JPImageresizerView的頭文件):
- blurEffect:毛玻璃樣式
- borderImage:邊框圖片
- frameType & strokeColor:邊框樣式&顏色
- bgColor:背景色
- maskAlpha:遮罩透明度
- resizeWHScale:裁剪的寬高比
- contentInsets:裁剪區(qū)域與視圖的間距
- maskImage:蒙版圖片
圖片/GIF
//【裁剪的圖片/GIF】以UIImage傳入
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithImage:image make:^(JPImageresizerConfigure *configure) {
// 到這里已經(jīng)有了默認參數(shù)值,可以在這里另外設(shè)置你想要的參數(shù)值(使用了鏈式編程方式)
configure
.jp_maskAlpha(0.5)
.jp_strokeColor([UIColor yellowColor])
.jp_frameType(JPClassicFrameType)
.jp_contentInsets(contentInsets)
.jp_bgColor([UIColor orangeColor])
.jp_isClockwiseRotation(YES)
.jp_animationCurve(JPAnimationCurveEaseOut);
}];
// 如果想要初始化為正方形,可設(shè)置 JPImageresizerConfigure 的 resizeWHScale 屬性
configure.resizeWHScale = 1; // 默認為0,完全顯示
// 另外如果還需要固定比例的話:
configure.isArbitrarily = YES; // 默認為YES
// 2.【裁剪的圖片/GIF】以NSData傳入
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithImageData:imageData make:^(JPImageresizerConfigure *configure) { ...... };
視頻
關(guān)于從系統(tǒng)相冊獲取的視頻,視頻方向有可能是修改過的(即相冊中旋轉(zhuǎn)、翻轉(zhuǎn)過),修改后的videoTrack.preferredTransform != CGAffineTransformIdentity,圖片也會,不過好歹圖片有個imageOrientation屬性告知具體改動了什么,由于我才疏學淺,單單從preferredTransform并不知道是經(jīng)過了具體的哪些改動,如果只是旋轉(zhuǎn)還好,旋轉(zhuǎn)+翻轉(zhuǎn)后的數(shù)值都是不一定的,這樣導致最后裁剪時會錯亂,目前只好先修正方向后再進行裁剪,日后改進,希望能有緣之士給予指點!
初始化后再修正(先進入頁面后再修正),具體操作可參照Demo:
// 1.【視頻】以NSURL傳入
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoURL:videoURL make:^(JPImageresizerConfigure *configure) { ...... } fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 初始化修正視頻方向的錯誤回調(diào)
} fixStartBlock:^{
// 初始化修正視頻方向的開始回調(diào)
} fixProgressBlock:^(float progress) {
// 初始化修正視頻方向的進度回調(diào)
} fixCompleteBlock:^(NSURL *cacheURL) {
// 初始化修正視頻方向的完成回調(diào)
}];
// 2.【視頻】以AVURLAsset傳入
[JPImageresizerConfigure defaultConfigureWithVideoAsset:videoAsset
make:^(JPImageresizerConfigure *configure) { ...... }
fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) { ...... }
fixStartBlock:^{ ...... } fixProgressBlock:^(float progress) { ...... }
fixCompleteBlock:^(NSURL *cacheURL) { ...... }];

又或者先修正再初始化(先修正后再進入頁面),可以使用JPImageresizerTool的API來修正,具體操作可參照Demo:
// 獲取視頻信息
AVURLAsset *videoAsset = [AVURLAsset assetWithURL:videoURL];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[videoAsset loadValuesAsynchronouslyForKeys:@[@"duration", @"tracks"] completionHandler:^{
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
AVAssetTrack *videoTrack = [videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
if (CGAffineTransformEqualToTransform(videoTrack.preferredTransform, CGAffineTransformIdentity)) {
// 無需修正,進入裁剪界面
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoAsset:videoAsset make:nil fixErrorBlock:nil fixStartBlock:nil fixProgressBlock:nil fixCompleteBlock:nil];
......
return;
}
// 修正方向
[JPImageresizerTool fixOrientationVideoWithAsset:videoAsset fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 修正視頻方向的錯誤回調(diào)
} fixStartBlock:^(AVAssetExportSession *exportSession) {
// 修正視頻方向的開始回調(diào)
// 返回exportSession,可監(jiān)聽進度或取消導出
} fixCompleteBlock:^(NSURL *cacheURL) {
// 修正視頻方向的完成回調(diào)
// cacheURL:修正方向后的視頻導出后的最終存放路徑,默認該路徑為NSTemporaryDirectory文件夾下,保存該路徑,裁剪后刪除視頻。
// 開始裁剪,進入裁剪界面
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoAsset:[AVURLAsset assetWithURL:cacheURL] make:nil fixErrorBlock:nil fixStartBlock:nil fixProgressBlock:nil fixCompleteBlock:nil];
......
}];
- PS1:如果視頻不需要修正,
fixStartBlock、fixProgressBlock、fixErrorBlock均不會調(diào)用,會直接調(diào)用fixCompleteBlock,返回原路徑; - PS2:如果確定是無需修正方向的視頻,
fixErrorBlock、fixStartBlock、fixProgressBlock、fixCompleteBlock傳nil; - PS3:更換視頻:
-setVideoURL: animated: fixErrorBlock: fixStartBlock: fixProgressBlock: fixCompleteBlock:和-setVideoAsset: animated: fixErrorBlock: fixStartBlock: fixProgressBlock: fixCompleteBlock:方法也與之同理,內(nèi)部會判定是否需要修正; - PS4:如果需要初始化就固定裁剪寬高比(如圓切、蒙版等),需要設(shè)置
JPImageresizerConfigure的isArbitrarily屬性為NO(默認為YES):
JPImageresizerConfigure *configure = [JPImageresizerConfigure darkBlurMaskTypeConfigureWithImage:nil make:^(JPImageresizerConfigure *configure) {
configure
.jp_maskImage([UIImage imageNamed:@"love.png"])
.jp_isArbitrarily(NO);
}];
2. 創(chuàng)建JPImageresizerView對象并添加到視圖上
JPImageresizerView *imageresizerView = [JPImageresizerView imageresizerViewWithConfigure:configure imageresizerIsCanRecovery:^(BOOL isCanRecovery) {
// 可在這里監(jiān)聽到是否可以重置
// 如果不需要重置(isCanRecovery為NO),可在這里做相應處理,例如將重置按鈕設(shè)置為不可點或隱藏
// PS:isCanRecovery僅針對[旋轉(zhuǎn)]、[縮放]、[鏡像]的變化情況,其他如裁剪寬高比、圓切等變化情況需用戶自行判定能否重置
// 具體操作可參照Demo
// 注意循環(huán)引用
} imageresizerIsPrepareToScale:^(BOOL isPrepareToScale) {
// 可在這里監(jiān)聽到裁剪區(qū)域是否預備縮放至適合范圍
// 如果預備縮放(isPrepareToScale為YES),此時裁剪、旋轉(zhuǎn)、鏡像功能不可用,可在這里做相應處理,例如將對應按鈕設(shè)置為不可點或隱藏
// 具體操作可參照Demo
// 注意循環(huán)引用
}];
[self.view addSubview:imageresizerView];
self.imageresizerView = imageresizerView;
// 創(chuàng)建后均可動態(tài)修改configure的參數(shù)
self.imageresizerView.image = [UIImage imageNamed:@"Kobe.jpg"]; // 更換裁剪圖片(默認帶動畫效果)
self.imageresizerView.resizeWHScale = 16.0 / 9.0; // 修改裁剪寬高比
self.imageresizerView.initialResizeWHScale = 0.0; // 默認為初始化時的resizeWHScale,調(diào)用 -recoveryByInitialResizeWHScale 方法進行重置則 resizeWHScale 會重置為該屬性的值
// 注意:iOS11以下的系統(tǒng),所在的controller最好設(shè)置automaticallyAdjustsScrollViewInsets為NO
// 不然imageresizerView會隨導航欄或狀態(tài)欄的變化產(chǎn)生偏移
if (@available(iOS 11.0, *)) {
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
在Swift中的使用
// 1.初始配置
let configure = JPImageresizerConfigure.defaultConfigure(with: image) { c in
_ = c
.jp_viewFrame(frame)
.jp_bgColor(.black)
.jp_frameType(.classicFrameType)
.jp_contentInsets(.init(top: 16, left: 16, bottom: 16, right: 16))
.jp_animationCurve(.easeInOut)
}
// 2.創(chuàng)建imageresizerView
let imageresizerView = JPImageresizerView(configure: configure) { [weak self] isCanRecovery in
// 當不需要重置設(shè)置按鈕不可點
self?.recoveryBtn.isEnabled = isCanRecovery
} imageresizerIsPrepareToScale: { [weak self] isPrepareToScale in
// 當預備縮放設(shè)置按鈕不可點,結(jié)束后可點擊
self?.operationView.isUserInteractionEnabled = !isPrepareToScale
}
// 3.添加到視圖上
view.insertSubview(imageresizerView, at: 0)
self.imageresizerView = imageresizerView
具體使用可以去Github下載Demo查看(JPCropViewController)。
裁剪
裁剪說明:
1.裁剪過程是在子線程中執(zhí)行,進度、錯誤、完成的回調(diào)都會切回主線程執(zhí)行,如果是高清圖片,裁剪前可添加HUD提示;
2.compressScale:圖片和GIF的壓縮比例,大于等于1按原圖尺寸裁剪,小于等于0則返回nil(例:compressScale = 0.5,1000 x 500 --> 500 x 250);
3.cacheURL:緩存路徑,可設(shè)置為nil,圖片和GIF則不緩存,而視頻會默認緩存到系統(tǒng)的NSTemporaryDirectory文件夾下,視頻名為當前時間戳,格式為mp4;
4.錯誤原因 JPCropErrorReason 說明:
- JPCEReason_NilObject:裁剪元素為空
- JPCEReason_CacheURLAlreadyExists:緩存路徑已存在其他文件
- JPCEReason_NoSupportedFileType:不支持的文件類型
- JPCEReason_VideoAlreadyDamage:視頻文件已損壞
- JPCEReason_VideoExportFailed:視頻導出失敗
- JPCEReason_VideoExportCancelled:視頻導出取消
5.注意:緩存路徑的圖片格式會自動修正,例如原本寫的是`xxx/xxx.jpeg`,由于使用了蒙版,裁剪后則會修正為`xxx/xxx.png`了,最終的緩存路徑要以裁剪回調(diào)`completeBlock`中的`result.cacheURL`為準。
裁剪圖片
// 1.以原圖尺寸進行裁剪
[self.imageresizerView cropPictureWithCacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 錯誤的回調(diào)
// reason:錯誤原因
// 注意循環(huán)引用
} completeBlock:^(JPImageresizerResult *result) {
// 裁剪完成
// result:裁剪后的結(jié)果(JPImageresizerResult)
// result.image:裁剪后的圖片(已解碼好的)
// result.cacheURL:目標存放路徑
// result.isCacheSuccess:是否緩存成功(緩存不成功則cacheURL為nil)
// 注意循環(huán)引用
}];
// 2.自定義壓縮比例裁剪圖片
// compressScale --- 壓縮比例,大于等于1按原圖尺寸裁剪,小于等于0則返回nil(例:compressScale = 0.5,1000 x 500 --> 500 x 250)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片、緩存路徑)
- (void)cropPictureWithCompressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
- 裁剪N宮格圖片
// 1.自定義N宮格裁剪
// columnCount:N宮格的列數(shù)(最小1列)
// rowCount:N宮格的行數(shù)(最小1行)
// compressScale --- 壓縮比例,大于等于1按原圖尺寸裁剪,小于等于0則返回nil(例:compressScale = 0.5,1000 x 500 --> 500 x 250)
// bgColor --- N宮格的背景色(如果圖片有透明區(qū)域,或者設(shè)置了蒙版的情況才生效,設(shè)置隱藏(透明)區(qū)域的背景色)
[self.imageresizerView cropGirdPicturesWithColumnCount:4 rowCount:2 compressScale:1 bgColor:UIColor.redColor cacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 錯誤的回調(diào)
// reason:錯誤原因
// 注意循環(huán)引用
} completeBlock:^(JPImageresizerResult *originResult, NSArray<JPImageresizerResult *> *fragmentResults, NSInteger columnCount, NSInteger rowCount) {
// 裁剪完成
// originResult:裁剪后的原圖結(jié)果(開始N宮格之前)
// fragmentResults:裁剪后的原圖被裁剪成N宮格圖片的結(jié)果集合(共 columnCount * rowCount 個)
// columnCount:調(diào)用該方法時傳入的列數(shù)
// rowCount:調(diào)用該方法時傳入的行數(shù)
// 注意循環(huán)引用
}];
// 2.九宮格裁剪(3行3列)
- (void)cropNineGirdPicturesWithCompressScale:(CGFloat)compressScale
bgColor:(UIColor *)bgColor
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropNGirdDoneBlock)completeBlock;
分享至朋友圈(建議使用resizeWHScale = 1進行裁剪):
裁剪GIF
// 1.原圖尺寸裁剪GIF
[self.imageresizerView cropGIFWithCacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 錯誤的回調(diào)
// reason:錯誤原因
// 注意循環(huán)引用
} completeBlock:^(JPImageresizerResult *result) {
// 裁剪完成
// result:裁剪后的結(jié)果(JPImageresizerResult)
// result.image:裁剪后的GIF(已解碼好的)
// result.cacheURL:目標存放路徑
// result.isCacheSuccess:是否緩存成功(緩存不成功則cacheURL為nil)
// 注意循環(huán)引用
}];
// 2.自定義壓縮比例裁剪GIF
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的GIF、緩存路徑)
- (void)cropGIFWithCompressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 3.自定義裁剪GIF
// isReverseOrder --- 是否倒放
// rate --- 速率
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的GIF、緩存路徑)
- (void)cropGIFWithCompressScale:(CGFloat)compressScale
isReverseOrder:(BOOL)isReverseOrder
rate:(float)rate
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
裁剪GIF的其中一幀
// 1.原圖尺寸裁剪GIF當前幀畫面
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片、緩存路徑)
- (void)cropGIFCurrentIndexWithCacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 2.自定義壓縮比例裁剪GIF當前幀畫面
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片、緩存路徑)
- (void)cropGIFCurrentIndexWithCompressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 3.自定義壓縮比例裁剪GIF指定幀畫面
// index --- 第幾幀畫面
// compressScale --- 壓縮比例,大于等于1按原圖尺寸裁剪,小于等于0則返回nil(例:compressScale = 0.5,1000 x 500 --> 500 x 250)
- (void)cropGIFWithIndex:(NSUInteger)index
compressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
- PS:可以設(shè)置isLoopPlaybackGIF自主選擇裁剪哪一幀(默認為NO,設(shè)置為YES會自動播放GIF)
self.imageresizerView.isLoopPlaybackGIF = NO;
裁剪本地視頻
- PS:目前只針對本地視頻,遠程視頻暫未適配。
// 裁剪整段視頻
// cacheURL:如果為nil,會默認緩存到系統(tǒng)的NSTemporaryDirectory文件夾下,視頻名為當前時間戳,格式為mp4
[self.imageresizerView cropVideoWithCacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPCropErrorReason reason) {
// 錯誤的回調(diào)
// reason:錯誤原因
// 注意循環(huán)引用
} progressBlock:^(float progress) {
// 監(jiān)聽進度
// progress:0~1
// 注意循環(huán)引用
} completeBlock:^(JPImageresizerResult *result) {
// 裁剪完成
// result:裁剪后的結(jié)果(JPImageresizerResult)
// result.cacheURL:目標存放路徑,如果為nil,會默認緩存到系統(tǒng)的NSTemporaryDirectory文件夾下,視頻名為當前時間戳,格式為mp4
// result.isCacheSuccess:是否緩存成功(緩存不成功則cacheURL為nil)
// 注意循環(huán)引用
}];
// 可設(shè)置視頻導出質(zhì)量
// presetName --- 系統(tǒng)的視頻導出質(zhì)量,如:AVAssetExportPresetLowQuality,AVAssetExportPresetMediumQuality,AVAssetExportPresetHighestQuality等
- (void)cropVideoWithPresetName:(NSString *)presetName
cacheURL:(NSURL *)cacheURL
errorBlock:(JPCropErrorBlock)errorBlock
progressBlock:(JPExportVideoProgressBlock)progressBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 取消視頻導出
// 當視頻正在導出時調(diào)用即可取消導出,觸發(fā)errorBlock回調(diào)(JPCEReason_ExportCancelled)
- (void)videoCancelExport;
- PS:由于視頻的寬高都必須是16的整數(shù)倍,否則導出后系統(tǒng)會自動對尺寸進行校正,不足的地方會以綠邊的形式進行填充,因此我在方法內(nèi)部對裁剪尺寸做了對16除余的修改,所以最后導出視頻的寬高比有可能跟指定的寬高比有些許差異。
裁剪視頻的其中一幀
// 1.原圖尺寸裁剪視頻當前幀畫面
// cacheURL --- 緩存路徑(可設(shè)置為nil,則不會緩存)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片、緩存路徑)
- (void)cropVideoCurrentFrameWithCacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 2.自定義壓縮比例裁剪視頻當前幀畫面
// cacheURL --- 緩存路徑(可設(shè)置為nil,則不會緩存)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片、緩存路徑)
- (void)cropVideoCurrentFrameWithCompressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 3.自定義壓縮比例裁剪視頻指定幀畫面
// second --- 第幾秒畫面
// cacheURL --- 緩存路徑(可設(shè)置為nil,則不會緩存)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片、緩存路徑)
- (void)cropVideoOneFrameWithSecond:(float)second
compressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
截取視頻某一段裁剪后轉(zhuǎn)GIF
// 1.視頻從當前時間開始截取指定秒數(shù)畫面轉(zhuǎn)GIF(fps = 10,rate = 1,maximumSize = 500 * 500)
// duration --- 截取多少秒
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的GIF、緩存路徑)
- (void)cropVideoToGIFFromCurrentSecondWithDuration:(NSTimeInterval)duration
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 2.視頻自定義截取指定秒數(shù)畫面轉(zhuǎn)GIF
// duration --- 截取多少秒
// fps --- 幀率(設(shè)置為0則以視頻真身幀率)
// rate --- 速率
// maximumSize --- 截取的尺寸(設(shè)置為0則以視頻真身尺寸)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的GIF、緩存路徑)
- (void)cropVideoToGIFFromStartSecond:(NSTimeInterval)startSecond
duration:(NSTimeInterval)duration
fps:(float)fps
rate:(float)rate
maximumSize:(CGSize)maximumSize
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
- PS:裁剪整段視頻畫面圓切、蒙版的功能不能使用,目前只對圖片和GIF有效。
蒙版

// 設(shè)置蒙版圖片(目前僅支持png圖片)
self.imageresizerView.maskImage = [UIImage imageNamed:@"love.png"];
// 直接設(shè)置該值即是調(diào)用 -setMaskImage: isToBeArbitrarily: animated: 方法,其中默認 isToBeArbitrarily = (maskImage ? NO : self.isArbitrarily),isAnimated = YES
// 移除蒙版圖片
self.imageresizerView.maskImage = nil;

-
PS:如果使用了蒙版圖片,那么最后裁剪出來的是png圖片,因此裁剪后體積有可能會比原本的圖片更大。
吳彥祖換臉
圓切

// 設(shè)置圓切
// 設(shè)置后,resizeWHScale為1:1,半徑為寬高的一半,邊框的上、左、下、右的中部均可拖動。
self.imageresizerView.isRoundResize = YES;
// 直接設(shè)置該值即是調(diào)用 -setIsRoundResize: isToBeArbitrarily: animated: 方法,其中默認 isToBeArbitrarily = (isRoundResize ? NO : self.isArbitrarily),isAnimated = YES
// 還原矩形
self.imageresizerView.isRoundResize = NO;
// 或者只需設(shè)置一下resizeWHScale為任意值即可
self.imageresizerView.resizeWHScale = 0.0;
橫豎屏切換

// 需要用戶去監(jiān)聽橫豎屏的切換,或自己手動切換時,調(diào)用該方法刷新
// 1.updateFrame:刷新的Frame(例如橫豎屏切換,傳入self.view.bounds即可)
// 2.contentInsets:裁剪區(qū)域與主視圖的內(nèi)邊距
// 3.duration:刷新時長(大于0即帶有動畫效果)
//【具體操作可參照Demo】
[self.imageresizerView updateFrame:self.view.bounds contentInsets:contentInsets duration:duration];
更改邊框樣式


// 目前只提供兩種邊框樣式,分別是簡潔樣式JPConciseFrameType,和經(jīng)典樣式JPClassicFrameType
// 可在初始化或直接設(shè)置frameType屬性來修改邊框樣式
self.imageresizerView.frameType = JPClassicFrameType;
自定義邊框圖片


// 使用自定義邊框圖片(例:平鋪模式)
UIImage *tileBorderImage = [[UIImage imageNamed:@"jp_dotted_line"] resizableImageWithCapInsets:UIEdgeInsetsMake(14, 14, 14, 14) resizingMode:UIImageResizingModeTile];
// 設(shè)置邊框圖片與邊線的偏移量(即CGRectInset,用于調(diào)整邊框圖片與邊線的差距)
self.imageresizerView.borderImageRectInset = CGPointMake(-1.75, -1.75);
// 設(shè)置邊框圖片(若為nil則使用frameType的邊框)
self.imageresizerView.borderImage = tileBorderImage;
切換裁剪寬高比
- PS:設(shè)置裁剪寬高比會自動移除圓切和蒙版
// 1.自定義參數(shù)切換
/**
* resizeWHScale: 目標裁剪寬高比(0則為任意比例)
* isToBeArbitrarily:切換之后 resizeWHScale 是否為任意比例(若為YES,最后 resizeWHScale = 0)
* animated: 是否帶動畫效果
*/
[self.imageresizerView setResizeWHScale:(16.0 / 9.0) isToBeArbitrarily:YES animated:YES];
// 2.直接切換
self.imageresizerView.resizeWHScale = 1.0;
// 默認切換之后保存最新的 resizeWHScale,且自帶動畫效果,如果設(shè)置為0,以當前裁剪框的寬高比設(shè)置,并且最后 isArbitrarily = YES,相當于:
[self.imageresizerView setResizeWHScale:1.0 isToBeArbitrarily:(resizeWHScale <= 0) animated:YES];
// 是否可以任意比例拖拽(包括圓切、蒙版)
self.imageresizerView.isArbitrarily = !self.imageresizerView.isArbitrarily;
// 更多API可查看 JPImageresizerView.h 上的注釋
自定義毛玻璃樣式、邊框顏色、背景顏色、遮罩透明度
// 設(shè)置毛玻璃樣式(默認帶動畫效果)
self.imageresizerView.blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
// 設(shè)置邊框顏色(默認帶動畫效果)
self.imageresizerView.strokeColor = UIColor.whiteColor;
// 設(shè)置背景顏色(默認帶動畫效果)
self.imageresizerView.bgColor = UIColor.blackColor;
// 設(shè)置遮罩透明度(默認帶動畫效果)
// PS:跟毛玻璃互斥,當設(shè)置了毛玻璃則遮罩為透明
self.imageresizerView.maskAlpha = 0.5; // blurEffect = nil 才生效
// 一步設(shè)置毛玻璃樣式、邊框顏色、背景顏色、遮罩透明度
[self.imageresizerView setupStrokeColor:strokeColor blurEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark] bgColor:UIColor.blackColor maskAlpha: 0.5 animated:YES];
鏡像翻轉(zhuǎn)

// 垂直鏡像,YES->沿著Y軸旋轉(zhuǎn)180°,NO->還原
BOOL isVerticalityMirror = !self.imageresizerView.verticalityMirror;
[self.imageresizerView setVerticalityMirror:isVerticalityMirror animated:YES];
// 水平鏡像,YES->沿著X軸旋轉(zhuǎn)180°,NO->還原
BOOL isHorizontalMirror = !self.imageresizerView.horizontalMirror;
[self.imageresizerView setHorizontalMirror:isHorizontalMirror animated:YES];
旋轉(zhuǎn)
// 1.順/逆時針旋轉(zhuǎn)90°(默認逆時針)
[self.imageresizerView rotation];
// 若需要順時針旋轉(zhuǎn)可設(shè)置isClockwiseRotation屬性為YES
self.imageresizerView.isClockwiseRotation = YES;
// 2.自定義旋轉(zhuǎn)至目標方向(支持4個方向,分別是垂直向上、水平向左、垂直向下、水平向右)
[self.imageresizerView rotationToDirection:JPImageresizerVerticalDownDirection];
重置
重置目標狀態(tài),方向垂直向上,可重置為不同的resizeWHScale、圓切、蒙版
1. 一切按當前狀態(tài)重置
- (void)recovery;
2. 以resizeWHScale重置(會移除圓切、蒙版)
// 2.1 按初始裁剪寬高比(initialResizeWHScale)進行重置
- (void)recoveryByInitialResizeWHScale;
- (void)recoveryByInitialResizeWHScale:(BOOL)isToBeArbitrarily;
// 2.2 按當前裁剪寬高比進行重置(如果resizeWHScale為0,則重置到整個裁剪元素區(qū)域)
- (void)recoveryByCurrentResizeWHScale;
- (void)recoveryByCurrentResizeWHScale:(BOOL)isToBeArbitrarily;
// 2.3 按目標裁剪寬高比進行重置(如果resizeWHScale為0,則重置到整個裁剪元素區(qū)域)
// targetResizeWHScale:目標裁剪寬高比
// isToBeArbitrarily:重置之后 resizeWHScale 是否為任意比例(若為YES,最后 resizeWHScale = 0)
- (void)recoveryToTargetResizeWHScale:(CGFloat)targetResizeWHScale isToBeArbitrarily:(BOOL)isToBeArbitrarily;
3. 以圓切重置
- (void)recoveryToRoundResize;
- (void)recoveryToRoundResize:(BOOL)isToBeArbitrarily;
4. 以蒙版圖片重置
// 4.1 按當前蒙版圖片重置
- (void)recoveryByCurrentMaskImage;
- (void)recoveryByCurrentMaskImage:(BOOL)isToBeArbitrarily;
// 4.2 指定蒙版圖片重置
- (void)recoveryToMaskImage:(UIImage *)maskImage isToBeArbitrarily:(BOOL)isToBeArbitrarily;
預覽
// 預覽模式:隱藏邊框,停止拖拽操作,用于預覽裁剪后的區(qū)域
// 1.默認自帶動畫效果
self.imageresizerView.isPreview = YES;
// 2.自定義是否帶動畫效果
[self.imageresizerView setIsPreview:YES animated:NO]
保存當前裁剪狀態(tài)
// 1.很Easy,直接調(diào)用saveCurrentConfigure方法獲取當前裁剪的狀態(tài),可用一個全局變量來保存該對象
JPImageresizerConfigure *savedConfigure = [self.imageresizerView saveCurrentConfigure];
// 2.重新打開裁剪歷史
JPImageresizerView *imageresizerView = [JPImageresizerView imageresizerViewWithConfigure:savedConfigure imageresizerIsCanRecovery:^(BOOL isCanRecovery) {
......
} imageresizerIsPrepareToScale:^(BOOL isPrepareToScale) {
......
}];
[self.view addSubview:imageresizerView];
self.imageresizerView = imageresizerView;
// 3.可以設(shè)置JPImageresizerConfigure的isCleanHistoryAfterInitial屬性為YES,當初始化結(jié)束后自動清空歷史(默認為YES)
// 或者直接調(diào)用cleanHistory方法清空歷史
- PS1:若保存的
savedConfigure.history.viewFrame跟當前的viewFrame不一致,界面會導致錯亂,需要自行判斷是否一致才可重新打開; - PS2:另外目前只能在App使用期間進行保存,暫未實現(xiàn)持久化緩存。
其他
// 鎖定裁剪區(qū)域,鎖定后無法拖動裁剪區(qū)域,NO則解鎖
self.imageresizerView.isLockResizeFrame = YES;
// 旋轉(zhuǎn)至水平方向時是否自適應裁剪區(qū)域大小
// 當圖片寬度比圖片高度小時,該屬性默認YES,可手動設(shè)為NO
self.imageresizerView.isAutoScale = NO;
安裝
JPImageresizerView 可通過CocoaPods安裝,只需添加下面一行到你的podfile:
pod 'JPImageresizerView'
反饋地址
郵箱:zhoujianping24@hotmail.com
扣扣:184669029