第一种:
是大家都知道的开源代码openflow,相关链接:http://www.sunetos.com/items/2010/12/05/open-source-ios-coverflow-implementations/
第二种:
绕某个中心线旋转的3D效果特效
代码如下:
.h里
#import <UIKit/UIKit.h>
@interface Test3DController : UIViewController {
float currentAngle;
float lastAngle;
NSTimer *animationTimer;
NSMutableArray *carouselViews;
UITouch *trackingTouch;
}
@end
#import <QuartzCore/QuartzCore.h>
#import "Test3DController.h"
@implementation Test3DController
- (void)setCarouselAngle:(float)angle
{
// we want to step around the outside of a circle in
// linear steps; work out the distance from one step
// to the next
float angleToAdd = 360.0f / [carouselViews count];
// apply positions to all carousel views
for(UIView *view in carouselViews)
{
NSLog(@"3D view : %f,%f",view.frame.origin.x,view.frame.origin.y);
float angleInRadians = angle * M_PI / 180.0f;
// get a location based on the angle
float xPosition = (self.view.frame.size.width * 0.5f) + 100.0f * sinf(angleInRadians);
float yPosition = (self.view.frame.size.height * 0.5f) + 30.0f * cosf(angleInRadians);
// get a scale too; effectively we have:
//
// 0.75f the minimum scale
// 0.25f the amount by which the scale varies over half a circle
//
// so this will give scales between 0.75 and 1.25. Adjust to suit!
float scale = 0.75f + 0.25f * (cosf(angleInRadians) + 1.0);
// apply location and scale
view.transform = CGAffineTransformScale(CGAffineTransformMakeTranslation(xPosition, yPosition), scale, scale);
// tweak alpha using the same system as applied for scale, this time
// with 0.3 the minimum and a semicircle range of 0.5
view.alpha = 0.3f + 0.5f * (cosf(angleInRadians) + 1.0);
// setting the z position on the layer has the effect of setting the
// draw order, without having to reorder our list of subviews
view.layer.zPosition = scale;
// work out what the next angle is going to be
angle += angleToAdd;
}
}
- (void)animateAngle
{
// work out the difference between the current angle and
// the last one, and add that again but made a bit smaller.
// This gives us inertial scrolling.
float angleNow = currentAngle;
currentAngle += (currentAngle - lastAngle) * 0.97f;
lastAngle = angleNow;
// push the new angle into the carousel
[self setCarouselAngle:currentAngle];
// if the last angle and the current one are now
// really similar then cancel the animation timer
if(fabsf(lastAngle - currentAngle) < 0.001)
{
[animationTimer invalidate];
animationTimer = nil;
}
}
-(void)btnCallBack:(id)sender
{
UIButton *btn = (UIButton*)sender;
NSLog(@"BUTTON PRESS view tag : %d",btn.tag);
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
//[self.view setBackgroundColor:[UIColor blackColor]];
// create views that are an 80x80 rect, centred on (0, 0)
CGRect frameForViews = CGRectMake(-40, -40, 80, 80);
// create six views, each with a different colour.
carouselViews = [[NSMutableArray alloc] initWithCapacity:6];
int c = 7;
while(c--)
{
//UIView *view = [[UIView alloc] initWithFrame:frameForViews];
UIButton *view = [UIButton buttonWithType:UIButtonTypeCustom];
[view setFrame:frameForViews];
//[view setBounds:frameForViews];
view.tag = c;
// We don't really care what the colours are as long as they're different,
// so just do anything
view.backgroundColor = [UIColor colorWithRed:(c&4) ? 1.0 : 0.0 green:(c&2) ? 1.0 : 0.0 blue:(c&1) ? 1.0 : 0.0 alpha:1.0];
[view addTarget:self action:@selector(btnCallBack:) forControlEvents:UIControlEventTouchUpInside];
// make the view visible, also add it to our array of carousel views
[carouselViews addObject:view];
[self.view addSubview:view];
}
currentAngle = lastAngle = 0.0f;
[self setCarouselAngle:currentAngle];
/*
Note: I've omitted viewDidUnload for brevity; remember to implement one and
clean up after all the objects created here
*/
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// if we're not already tracking a touch then...
if(!trackingTouch)
{
// ... track any of the new touches, we don't care which ...
trackingTouch = [touches anyObject];
// ... and cancel any animation that may be ongoing
[animationTimer invalidate];
animationTimer = nil;
lastAngle = currentAngle;
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// if our touch moved then...
if([touches containsObject:trackingTouch])
{
// use the movement of the touch to decide
// how much to rotate the carousel
CGPoint locationNow = [trackingTouch locationInView:self.view];
CGPoint locationThen = [trackingTouch previousLocationInView:self.view];
lastAngle = currentAngle;
currentAngle += (locationNow.x - locationThen.x) * 180.0f / self.view.bounds.size.width;
// the 180.0f / self.view.bounds.size.width just says "let a full width of my view
// be a 180 degree rotation"
// and update the view positions
[self setCarouselAngle:currentAngle];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// if our touch ended then...
if([touches containsObject:trackingTouch])
{
// make sure we're no longer tracking it
trackingTouch = nil;
// and kick off the inertial animation
animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(animateAngle) userInfo:nil repeats:YES];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
// treat cancelled touches exactly like ones that end naturally
[self touchesEnded:touches withEvent:event];
}
@end