CALayer 之contents 的妙用

由于項(xiàng)目的一個(gè)需求,研究了下CALayer ,發(fā)現(xiàn)了一個(gè)比較有趣的屬性contents先展示下完成的需求效果。

QQ20180721-1302-HD.gif

可以看到,就是一個(gè)對(duì)一個(gè)圖片模糊處理后,點(diǎn)擊的時(shí)候,點(diǎn)擊區(qū)域變?yōu)榍逦?,而未觸摸區(qū)域依然保持模糊狀態(tài)。如果單純的處理一張圖片模糊我們知道有很多種方法可以實(shí)現(xiàn),這里的主要難點(diǎn)是,在手指觸摸的區(qū)域需要還原圖片的清晰,并且如果在手指長(zhǎng)按滑動(dòng)的情況下,需要根據(jù)手指移動(dòng)的軌跡來(lái)還原圖片的清晰。

剛接手這個(gè)需求的時(shí)候,首先想到的是,根據(jù)手指移動(dòng)的軌跡 重新繪制點(diǎn)擊的區(qū)域來(lái)完成,但是實(shí)驗(yàn)以后發(fā)現(xiàn)并不太容易實(shí)現(xiàn)理想效果,而且性能很差。

使用 CGContextRef 處理問(wèn)題
1,首先性能很差,在手指長(zhǎng)按滑動(dòng)時(shí),如果時(shí)時(shí)的根據(jù)移動(dòng)位置做重繪操作,必定造成內(nèi)存的激增。這個(gè)避免不了。
2, 不能很好的處理觸摸區(qū)域周邊的糊化效果,
3,當(dāng)做圖片放大時(shí),對(duì)觸摸清晰的區(qū)域不好把控。

基于上述這些問(wèn)題,后面果斷放棄使用圖形上下文來(lái)做這個(gè)需求。

困擾了很久,看了一些GPUImage上面的效果 也沒有找到想要的答案。

后來(lái)有一天忽然想到一個(gè)問(wèn)題,UIImageView是怎么顯示圖片出來(lái)的,也就是它的內(nèi)部實(shí)現(xiàn)。我們都知道系統(tǒng)的顯示控件都是繼承自UIView 而一個(gè)view之所以能夠顯示,是因?yàn)槠鋬?nèi)部的layer ,所有的顯示有CALayer來(lái)處理。想到這一點(diǎn)就馬上查閱文檔,發(fā)現(xiàn)了一個(gè)其內(nèi)部的 Contents,和 mask 屬性。

通過(guò)測(cè)試,果然可以實(shí)現(xiàn)需求效果。。這里說(shuō)下大概思路。

1, 首先將圖片模糊化 ,在模糊之前保存當(dāng)前的圖片,以備做觸摸清晰時(shí)使用。。 這里我使用的是Accelerate庫(kù)的一些函數(shù),來(lái)處理模糊。設(shè)置和frame。
2, 創(chuàng)建一個(gè)和模糊圖片相同的UIImageView對(duì)象 frame需相同,將該對(duì)象layer內(nèi)部的mask 替換為自定義的CALayer 對(duì)象 ,
3, 將自定義的CALayer對(duì)象內(nèi)部的contents替換為一個(gè)"占位圖片", 初始化時(shí),先隱藏自定義的layer 對(duì)象。這樣由于imageView的layer屬性已經(jīng)替換為自定義的了,當(dāng)將自定義的layerhidden 設(shè)置為 YES 時(shí),當(dāng)前這張圖片也就不會(huì)顯示出來(lái)了。
4, 在手勢(shì)事件觸發(fā)的時(shí)候,將自定義的layer 顯示出來(lái),并且將之前保存的清晰圖片賦值給自定義的圖片對(duì)象,由于圖片對(duì)象的layer已經(jīng)被替換,所以顯示出來(lái)的,就是我們想要的結(jié)果了。

  CALayer *imageMaskLayer = [CALayer layer];
        NSString *path = [[NSBundle mainBundle] pathForResource:@"patternFinnal" ofType:@".png"];
        UIImage *displayerImage = [UIImage imageWithContentsOfFile:path];
        imageMaskLayer.contents = (__bridge id)displayerImage.CGImage;
        imageMaskLayer.frame = CGRectMake(0, 0, touchSize, touchSize);
        imageMaskLayer.hidden = YES;
        self.imageMaskLayer = imageMaskLayer;
        _showImageView.layer.mask = imageMaskLayer;

在觸發(fā)手勢(shì)后的操作。

 CGPoint touchPoint = [pre locationInView:self.imageView];
    if (pre.state == UIGestureRecognizerStateBegan || pre.state == UIGestureRecognizerStateChanged) {
        
        self.imageMaskLayer.hidden = NO;
        self.showImageView.image = self.matterImage;
        [CATransaction begin];
        [CATransaction setDisableActions:YES];
        self.imageMaskLayer.position = CGPointMake(touchPoint.x, touchPoint.y - 50);
        [CATransaction commit];
        if ([self.delegate respondsToSelector:@selector(toucClearView: touchPiontDidChange:)]) {
            [self.delegate toucClearView:self touchPiontDidChange:touchPoint];
        }

這里有必要說(shuō)下,
當(dāng)手指滑動(dòng)時(shí),我是修改layer內(nèi)部的position來(lái)處理的,真的是免去了,之前根據(jù)滑動(dòng)位置來(lái)計(jì)算位置的煩惱。但是在設(shè)置 layerposition 之前必須要設(shè)置[CATransaction begin] 才有效。

這段時(shí)間我將這段邏輯抽取了出來(lái),封裝了一個(gè)小的demo ,如果對(duì)你有些幫助,還望給個(gè)star.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 CALayer IOS SDK詳解之CALayer(一) http://doc.okbase.net/Hell...
    Kevin_Junbaozi閱讀 5,346評(píng)論 3 23
  • 1、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明AI閱讀 16,228評(píng)論 3 119
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,698評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫全貌。在這里你可以看...
    F麥子閱讀 5,273評(píng)論 5 13
  • 致2015級(jí)教育學(xué)院新生 ——暨教育學(xué)院生涯規(guī)劃交流會(huì)演講稿 一、精通一項(xiàng)技能 不要讓你的大學(xué)時(shí)光白白度過(guò),最直接...
    Airing閱讀 738評(píng)論 1 20

友情鏈接更多精彩內(nèi)容