Skip to content

Instantly share code, notes, and snippets.

@tonyxiao
Forked from d-ronnqvist/VideoView.m
Created December 8, 2013 18:32
Show Gist options
  • Save tonyxiao/7861726 to your computer and use it in GitHub Desktop.
Save tonyxiao/7861726 to your computer and use it in GitHub Desktop.
//
// VideoView.m
// MacVideoWall
//
// Created by David Rönnqvist on 9/28/13.
// This is the source code behind the Mac Video Wall that I was trying to port to iOS in [this Stack Overflow question](http://stackoverflow.com/questions/19065816/ios-alternative-to-qtmovielayer-that-has-non-nil-contents)
//
#import "VideoView.h"
#import <QuartzCore/QuartzCore.h>
#import <QTKit/QTKit.h>
@interface VideoView ()
@property (strong) CALayer *sourceLayer;
@end
@implementation VideoView
- (void)awakeFromNib {
// Initialization code here.
// The view needs layers
[self setWantsLayer:YES];
self.layer.backgroundColor = [NSColor colorWithCalibratedWhite:0.15 alpha:1.0].CGColor;
// Give the view's layer a perspective transform for it's children
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = 1./800.;
self.layer.sublayerTransform = perspective;
// Load the movie
NSError *error = nil;
NSURL *videoURL = [[NSBundle mainBundle] URLForResource:@"video" withExtension:@"m4v"];
NSLog(@"can %@ play this", [QTMovie canInitWithURL:videoURL]?@"absolutely":@"not");
QTMovie *movie = [QTMovie movieWithURL:videoURL error:&error];
if (error) {
NSLog(@"ERROR! %@", [error localizedDescription]);
}
// Create a movie layer
QTMovieLayer *movieLayer = [QTMovieLayer layerWithMovie:movie];
self.sourceLayer = movieLayer;
movieLayer.frame = CGRectInset(self.bounds, 50, 50);
[self.layer addSublayer:movieLayer];
// Start playing the movie
[movie play];
// Layout more layers inside this layer
CGRect layerRects = CGRectInset(self.bounds, 15, 15);
NSInteger num = 10;
CGFloat margin = 0.;
// Width & height of the layers
CGFloat width = CGRectGetWidth(layerRects)/num-margin;
CGFloat height = CGRectGetHeight(layerRects)/num-margin;
CGFloat floatNum = num;
self.sourceLayer.frame = (CGRect){layerRects.origin, CGSizeMake(width, height)};
self.sourceLayer.contentsRect = CGRectMake(0, 0, 1/floatNum, 1/floatNum);
// These are just the animations that tilt the all the layers
CABasicAnimation *flipY = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
flipY.fromValue = @(-M_PI/5.);
flipY.toValue = @(+M_PI/5.);
flipY.duration = 2.0;
flipY.autoreverses = YES;
flipY.repeatCount = INFINITY;
CABasicAnimation *flipX = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
flipX.fromValue = @(-M_PI/3.);
flipX.toValue = @(+M_PI/3.);
flipX.duration = 3.5;
flipX.autoreverses = YES;
flipX.repeatCount = INFINITY;
// Tilt the source layer
[self.sourceLayer addAnimation:flipY forKey:nil];
[self.sourceLayer addAnimation:flipX forKey:nil];
// Loop over the rows and coumns to create a grid of layers
for (NSInteger col=0; col<num; col++) {
for (NSInteger row=0; row<num; row++) {
if (row+col == 0) continue;
// Create a new layer
CALayer *copiedLayer = [CALayer layer];
// Give it the same contents as the movie layer
copiedLayer.contents = self.sourceLayer.contents;
copiedLayer.frame = CGRectMake(CGRectGetMinX(layerRects)+row*width +row*margin,
CGRectGetMinY(layerRects)+col*height +col*margin,
width, height);
// Display only part of that conent in this layer
copiedLayer.contentsRect = CGRectMake(row/floatNum, col/floatNum, 1/floatNum, 1/floatNum);
[self.layer addSublayer:copiedLayer];
// Add the tilting animation
[copiedLayer addAnimation:flipY forKey:nil];
[copiedLayer addAnimation:flipX forKey:nil];
}
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment