iOS 3D倒影輪播圖實現(xiàn)


一直想寫一個帶倒影效果的3D輪播圖锭部,最近有時間暂论,就研究了一下,下面是實現(xiàn)后的效果拌禾,可無限循環(huán)輪播:

效果

倒影

首先是倒影效果取胎,要想實現(xiàn)倒影,需要了解CALayer復(fù)制層湃窍。這里要注意的是闻蛀,復(fù)制層CAReplicatorLayer是針對父視圖來說的,比如要給一個UIImageView添加倒影效果您市,則要針對UIImageView的父視圖的根層進行設(shè)置復(fù)制層觉痛。

所以這里寫了一個繼承自UIView類的HLImageView,在其上面添加一個顯示圖片的UIImageView,并在HLImageView初始化方法中設(shè)置其復(fù)制層茵休,效果如下:

倒影效果

具體的代碼如下:

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        
        CGFloat w = frame.size.width;
        CGFloat h = frame.size.height;
        
        _posiP = self.layer.position;
        
        _imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, w, h / 2.0)];
        [self addSubview:_imgView];
        
        CAReplicatorLayer *repL =  (CAReplicatorLayer *)self.layer;
        repL.instanceCount = 2;
        //復(fù)制出來的子層,它都是繞著復(fù)制層錨點進行旋轉(zhuǎn).
        repL.instanceTransform = CATransform3DMakeRotation(M_PI, 1, 0, 0);
        
        repL.instanceRedOffset -= 0.5;
        repL.instanceGreenOffset -= 0.5;
        repL.instanceBlueOffset -= 0.5;
        repL.instanceAlphaOffset -= 0.5;
        
    }
    return self;
}

這里注意的是復(fù)制出來的子層都是繞復(fù)制層的錨點進行旋轉(zhuǎn)的薪棒,CALayer默認的錨點是(0.5,0.5)榕莺,所以這里默認繞中心點延伸的軸旋轉(zhuǎn)俐芯,上面代碼是繞x軸旋轉(zhuǎn),即會產(chǎn)生倒影效果钉鸯。

3D效果旋轉(zhuǎn)

實現(xiàn)倒影效果后吧史,接下來就是實現(xiàn)圖片旋轉(zhuǎn)時遠小近大的3D效果。

3D效果

在這里要用到CATransform3D這個結(jié)構(gòu)體唠雕。API中我們可以看到CATransform3D是一個4X4的矩陣贸营,如下:

struct CATransform3D
{
  CGFloat m11, m12, m13, m14;
  CGFloat m21, m22, m23, m24;
  CGFloat m31, m32, m33, m34;
  CGFloat m41, m42, m43, m44;
};

這里的矩陣乘法公式如下圖:

矩陣乘法公式

公式中我們可以看到,m34這個值影響了z軸的translation及塘,其默認值是0莽使,這里設(shè)置m34值,就可以實現(xiàn)遠小近大的效果:

這里需要給一個旋轉(zhuǎn)角度笙僚,否則無法看到3D效果芳肌。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    CATransform3D transform0 = CATransform3DIdentity;
    transform0.m34 = -1 / 550.0;
    
    _img.layer.transform = CATransform3DRotate(transform0, M_PI_4, 0, 1, 0);
    
}

這里要注意的是,旋轉(zhuǎn)軸的原點是圖層的錨點anchorPoint,默認是中心點(0.5亿笤,0.5),要想繞邊軸旋轉(zhuǎn)則要相應(yīng)設(shè)置設(shè)置錨點為(0.0翎迁,0.5)或(1.0,0.5)净薛。

實現(xiàn)倒影效果的3D旋轉(zhuǎn)

了解上面的兩種效果后汪榔,我們就可以實現(xiàn)帶倒影的3D輪播圖效果了。
具體思路就是用UIScrollView寫一個輪播圖,加載圖片的是一個繼承自UIView的自定義類肃拜,在其上加載圖片并實現(xiàn)倒影效果痴腌,對其進行輪播旋轉(zhuǎn)操作。
效果問首效果圖所示燃领。

這里主要是設(shè)置UIScrollView的代理士聪,并在在代理方式- (void)scrollViewDidScroll:(UIScrollView *)scrollView中實現(xiàn)3D旋轉(zhuǎn)效果。

在代理方法中分別獲得當(dāng)前展示的圖和即將展示的下一張圖猛蔽,在滑動手勢下不斷改變兩張圖的旋轉(zhuǎn)角度即可剥悟。原理不難,但實現(xiàn)起來還是有點復(fù)雜的曼库。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    CGFloat c = ceilf(scrollView.contentOffset.x / _w);
    
    if (c > 0 && c < _imgViews.count) {
        CGFloat value = (scrollView.contentOffset.x - (c - 1) * _w) / _w; // 滑動時的值范圍0~1
        
        // 當(dāng)前展示圖的實時旋轉(zhuǎn)角度
        CGFloat angle0 = M_PI_2 * value;
        
        // 當(dāng)前展示的圖
        HLImageView *img0 = (HLImageView *)_imgViews[(int)c - 1];
        img0.layer.anchorPoint = CGPointMake(0.0, 0.5);
        img0.layer.position = CGPointMake(img0.posiP.x - img0.frame.size.width / 2.0 * (1 - value),img0.posiP.y);
        
        // 設(shè)置3D旋轉(zhuǎn)效果
        CATransform3D transform0 = CATransform3DIdentity;
        transform0.m34 = -1 / 550.0;
        img0.layer.transform = CATransform3DRotate(transform0, angle0, 0, 1, 0);
        
        // 當(dāng)前展示圖后一張圖的實時旋轉(zhuǎn)角度
        CGFloat angle1 = M_PI_2 * (1 - value);
        
        // 當(dāng)前展示圖的后一張圖
        HLImageView *img1 = (HLImageView *)_imgViews[(int)c];
        img1.layer.anchorPoint = CGPointMake(1.0, 0.5);
        img1.layer.position = CGPointMake(img1.posiP.x + img1.frame.size.width / 2.0 * value, img1.posiP.y);
        
        //設(shè)置3D旋轉(zhuǎn)效果
        CATransform3D transform1 = CATransform3DIdentity;
        transform1.m34 = -1 / 550.0;
        
        img1.layer.transform = CATransform3DRotate(transform1, -angle1, 0, 1, 0);
        
        NSLog(@"===========:%f--------:%f=========:%f",scrollView.contentOffset.x,c,value);
    }
    
    
    if (scrollView.contentOffset.x == _w * (_imgViews.count - 1)) {
        
        HLImageView *firstImg = (HLImageView *)_imgViews[1];
        firstImg.layer.transform = CATransform3DIdentity;
        
        scrollView.contentOffset = CGPointMake(_w, 0);
    } else if (scrollView.contentOffset.x == 0) {
        
        HLImageView *lastImg = (HLImageView *)_imgViews[imgCount];
        lastImg.layer.transform = CATransform3DIdentity;
        
        scrollView.contentOffset = CGPointMake(_w * imgCount, 0);
    }
}

無限輪播

可能有人注意到了上面代理方法里最后部分的


    if (scrollView.contentOffset.x == _w * (_imgViews.count - 1)) {
        
        HLImageView *firstImg = (HLImageView *)_imgViews[1];
        firstImg.layer.transform = CATransform3DIdentity;
        
        scrollView.contentOffset = CGPointMake(_w, 0);
    } else if (scrollView.contentOffset.x == 0) {
        
        HLImageView *lastImg = (HLImageView *)_imgViews[imgCount];
        lastImg.layer.transform = CATransform3DIdentity;
        
        scrollView.contentOffset = CGPointMake(_w * imgCount, 0);
    }

這里實現(xiàn)的就是無限輪播区岗。我的demo中有5張不同的圖,按順序編號從1到5毁枯,設(shè)置輪播圖如下:

圖號:5慈缔、1、2后众、3胀糜、4颅拦、5蒂誉、1

順序:1、2距帅、3右锨、4、5碌秸、6绍移、7

總共在UIScrollView中添加了7張圖,其中首張為最后一張圖5讥电,最后一張為第一張圖1蹂窖。

這樣在輪播到第7張圖1時立刻跳轉(zhuǎn)到第2張圖1,輪播到第1張圖5時立即跳到第6張圖5恩敌。即產(chǎn)生了無限輪播的效果瞬测。


更新:自動輪播及點擊圖片回調(diào)。

源碼:GitHub地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市月趟,隨后出現(xiàn)的幾起案子灯蝴,更是在濱河造成了極大的恐慌,老刑警劉巖孝宗,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件穷躁,死亡現(xiàn)場離奇詭異,居然都是意外死亡因妇,警方通過查閱死者的電腦和手機问潭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婚被,“玉大人睦授,你說我怎么就攤上這事∷ふ” “怎么了去枷?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長是复。 經(jīng)常有香客問我删顶,道長,這世上最難降的妖魔是什么淑廊? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任逗余,我火速辦了婚禮,結(jié)果婚禮上季惩,老公的妹妹穿的比我還像新娘录粱。我一直安慰自己,他們只是感情好画拾,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布啥繁。 她就那樣靜靜地躺著,像睡著了一般青抛。 火紅的嫁衣襯著肌膚如雪旗闽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天蜜另,我揣著相機與錄音适室,去河邊找鬼。 笑死举瑰,一個胖子當(dāng)著我的面吹牛捣辆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播此迅,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼汽畴,長吁一口氣:“原來是場噩夢啊……” “哼促煮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起整袁,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤衍腥,失蹤者是張志新(化名)和其女友劉穎垒玲,沒想到半個月后围段,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溉浙,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年炸客,在試婚紗的時候發(fā)現(xiàn)自己被綠了疾棵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡痹仙,死狀恐怖是尔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情开仰,我是刑警寧澤拟枚,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站众弓,受9級特大地震影響恩溅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谓娃,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一脚乡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧滨达,春花似錦奶稠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至稽莉,卻和暖如春瀑志,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背污秆。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昧甘,地道東北人良拼。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像充边,于是被迫代替她去往敵國和親庸推。 傳聞我的和親對象是個殘疾皇子常侦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,509評論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件贬媒、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,024評論 4 62
  • 時間寶管理平臺一共分為四大模塊: 1聋亡、基礎(chǔ)管理 2、教務(wù)管理 3际乘、財務(wù)管理 4坡倔、報表管理 本篇文章介紹基礎(chǔ)管理部分...
    時間寶閱讀 280評論 0 0
  • 這本書是澳大利亞政史學(xué)家約翰·赫斯特為他們學(xué)生編寫的歷史教科書,雖說是教科書脖含,但作者抓住歐洲文明的基本元素罪塔,透過時...
    giguala閱讀 278評論 0 0
  • 你說 你喜歡我 你說 你和我一樣敏感 你說 好想見我 你說 傻瓜不許哭 你說 因為是你所以喜歡 你說 我們相遇是緣...
    璞玉未來閱讀 156評論 3 4