近期项目中需要实现一个拼图功能,拼图的模版需要在项目发版后由设计师提供,通过后端下发。效果类似下图:
就是在一个背景图上有N个不同形状大小的区域,这些区域可以放入自己的照片,这些照片可以滑动或者放大。最后拼成一张整图。
实现这些功能的思路就是,后端下发背景图和形状的信息,前端通过形状信息创建N个UIScrollView。用UIScrollView加载用户的照片,实现滑动和放大。
难点就在于怎么把形状信息通过后端下发,然后客户端解析。
接到这个需求后我尝试了两个方案:
1.我们都知道Lottie这个地方库,可以通过把动画存放在json里然后解析json实现动画的功能。那既然能实现动画了,解析形状信息应该也不是问题吧。
研究之后发现Lottie并不能直接解析得到UIBezierPath或者CGPathRef。最终放弃。
2.通过SVG格式下发,正好iOS有SVGKit这个第三方库可以解析SVG格式的照片。只要把形状通过SVG保存就能读取出形状信息了。
事实证明这个方案确实可行。但是SVGKit也没有直接解析得到UIBezierPath或者CGPathRef的接口。好在可以间接获得!!
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.通过svg文件创建SVGKImage。
2.通过SVGKImage获得CALayer。
3.通过CALayer获得CGPathRef。
4.通过CGPathRef,创建不同形状的UIScrollView。