近期項(xiàng)目中需要實(shí)現(xiàn)一個(gè)拼圖功能,拼圖的模版需要在項(xiàng)目發(fā)版后由設(shè)計(jì)師提供,通過(guò)后端下發(fā)。效果類似下圖:

就是在一個(gè)背景圖上有N個(gè)不同形狀大小的區(qū)域,這些區(qū)域可以放入自己的照片,這些照片可以滑動(dòng)或者放大。最后拼成一張整圖。
實(shí)現(xiàn)這些功能的思路就是,后端下發(fā)背景圖和形狀的信息,前端通過(guò)形狀信息創(chuàng)建N個(gè)UIScrollView。用UIScrollView加載用戶的照片,實(shí)現(xiàn)滑動(dòng)和放大。
難點(diǎn)就在于怎么把形狀信息通過(guò)后端下發(fā),然后客戶端解析。
接到這個(gè)需求后我嘗試了兩個(gè)方案:
1.我們都知道Lottie這個(gè)地方庫(kù),可以通過(guò)把動(dòng)畫存放在json里然后解析json實(shí)現(xiàn)動(dòng)畫的功能。那既然能實(shí)現(xiàn)動(dòng)畫了,解析形狀信息應(yīng)該也不是問(wèn)題吧。
研究之后發(fā)現(xiàn)Lottie并不能直接解析得到UIBezierPath或者CGPathRef。最終放棄。
2.通過(guò)SVG格式下發(fā),正好iOS有SVGKit這個(gè)第三方庫(kù)可以解析SVG格式的照片。只要把形狀通過(guò)SVG保存就能讀取出形狀信息了。
事實(shí)證明這個(gè)方案確實(shí)可行。但是SVGKit也沒(méi)有直接解析得到UIBezierPath或者CGPathRef的接口。好在可以間接獲得?。?/p>
NSString *path = [[NSBundle mainBundle] pathForResource:@"Resource/Animation/compare/favourite" ofType:@"svg"];
NSData *svgData = [[NSData alloc] initWithContentsOfFile:path];
// SVGKLayeredImageView* imageview = [[SVGKLayeredImageView alloc] initWithSVGKImage:[SVGKImage imageWithData:svgData]];
// imageview.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
// [self insertSubview:imageview aboveSubview:self.originalImageView];
SVGKImage* img = [SVGKImage imageWithData:svgData];
CALayer* f = [img CALayerTree];
CGMutablePathRef cpath = CGPathCreateMutable();
for(int i = 0; i < [f.sublayers count]; i++)
CGPathAddPath(cpath, NULL, ((CAShapeLayer*)[f.sublayers objectAtIndex:i]).path);
CAShapeLayer* sl = [[CAShapeLayer alloc] init];
// CGPathAddPath(cpath, NULL, ((CAShapeLayer*)[f.sublayers objectAtIndex:0]).path);
sl.path = ((CAShapeLayer*)f.sublayers.firstObject).path;
self.originalImageView.layer.mask = sl;
步驟就是:
1.通過(guò)svg文件創(chuàng)建SVGKImage。
2.通過(guò)SVGKImage獲得CALayer。
3.通過(guò)CALayer獲得CGPathRef。
4.通過(guò)CGPathRef,創(chuàng)建不同形狀的UIScrollView。
參考文獻(xiàn):
http://hk.uwenku.com/question/p-fkzekhvr-yg.html