カメラロール内のビデオを選択すると、再生中の動画上でルーペ(拡大鏡)が使えるようになる。
ポイントは2つのAVPlayerLayerを合成しているところ。
@property AVPlayer *player; @property AVPlayerLayer *zoomPlayerLayer; @property AVPlayerLayer *mainPlayerLayer;mainPlayerLayer は通常の動画再生レイヤーで、zoomPlayerLayerがルーペ内の拡大された動画再生レイヤーになる。どちらも -[AVPlayerLayer playerLayerWithPlayer:] から取得した AVPlayerの動作再生レイヤー。このメソッドを使うと再生中の動画を複数のレイヤーで同時に表示することができる(って今回初めて知った)。この性質を利用して、zoomPlayerLayerに変形とマスクを適用することでループを表現している。
以下はzoomPlayerLayerの生成部分
// Set up the zoom AVPlayerLayer. self.zoomPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; CGSize zoomSize = CGSizeMake(self.view.layer.bounds.size.width * ZOOM_FACTOR, self.view.layer.bounds.size.height * ZOOM_FACTOR); self.zoomPlayerLayer.frame = CGRectMake((contentLayer.bounds.size.width /2) - (zoomSize.width /2), (contentLayer.bounds.size.height /2) - (zoomSize.height /2),zoomSize.width,zoomSize.height); [contentLayer addSublayer:self.zoomPlayerLayer]; [self.loupeView.layer addSublayer:contentLayer];
丸く切り取るマスク
// The content layer has a circular mask applied. CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.frame = contentLayer.bounds; CGMutablePathRef circlePath = CGPathCreateMutable(); CGPathAddEllipseInRect(circlePath, NULL, CGRectInset( self.loupeView.layer.bounds, LOUPE_BEZEL_WIDTH , LOUPE_BEZEL_WIDTH)); maskLayer.path = circlePath; CGPathRelease(circlePath);
動画再生の変形と合成がこんなに簡単にできるとは。これは色々と応用できそう。