实现一
使用一个继承自UIView的类来包含要实现倒影效果的图片,重写这个UIView子类的绘图方法,以实现图片于倒影,
然后把这个View 添加到相应的地方显示。
代码:
CKReflectionImage.h
[cpp]
#import <UIKit/UIKit.h>
@interface CKReflectionImage : UIView {
@private
UIImage *image_;
/**
* Value of gradient start. This value is divided to height of image.
*/
CGFloat visibleReflectionHeight_;
/**
* Padding to top image.
*/
CGFloat paddingToTopImage_;
}
@property (nonatomic, readwrite, retain) UIImage *image;
@property (nonatomic, readwrite, assign) CGFloat visibleReflectionHeight;
@property (nonatomic, readwrite, assign) CGFloat paddingToTopImage;
@end
CKReflectionImage.h
[cpp
#import "CKReflectionImage.h"
@implementation CKReflectionImage
#pragma mark -
#pragma mark Properties
@synthesize image = image_;
@synthesize visibleReflectionHeight = visibleReflectionHeight_;
@synthesize paddingToTopImage = paddingToTopImage_;
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[image_ release];
image_ = nil;
visibleReflectionHeight_ = 0.0f;
paddingToTopImage_ = 0.0f;
[super dealloc];
}
#pragma mark -
#pragma mark Draw methods
/**
* Draws the receiver’s image within the passed-in rectangle.
*
* @param rect: The portion of the view’s bounds that needs to be updated.
*/
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
if (image_ != nil) {
// Get current context to draw.
CGContextRef context = UIGraphicsGetCurrentContext();
// Reflection image references
CGImageRef reflectionImage = NULL;
CGImageRef gradientImage = NULL;
// Frame of image
CGRect frame = [self frame];
frame.origin.x = 0.0f;
frame.origin.y = 0.0f;
frame.size.width = CGRectGetWidth(frame);
frame.size.height = image_.size.height * CGRectGetWidth(frame) / image_.size.width;
// Draw initial image in context
CGContextSaveGState(context);
{
// Draw image in context, commented but the image show in reverse.
// CGContextDrawImage(context, frame, [image_ CGImage]);
// Push context to draw image.
UIGraphicsPushContext(context);
// Draw original image in top
[image_ drawInRect:frame];
// Pop to context
UIGraphicsPopContext();
}
CGContextRestoreGState(context);
// Create gradient bitmap
CGContextSaveGState(context);
{
// Gradient is always black-white and the mask must be in the gray colorspace.
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
// Create a bitmap context
CGContextRef gradientContext = CGBitmapContextCreate(NULL, CGRectGetWidth(frame), CGRectGetHeight(frame), 8, 0, colorSpace, kCGImageAlphaNone);
// Define the start and the end grayscale values (with the alpha, even though our
// bitmap context doesn't support alpha gradient requieres it).
CGFloat colors[] = {0.0f, 1.0f, 1.0f, 1.0f};
// Creates the CGGradient
CGGradientRef grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2);
// Release colorSpace reference
CGColorSpaceRelease(colorSpace);
// Create the start and end points for the gradient vector (straight down).
CGPoint gradientStartPoint = CGPointMake(0, (CGRectGetHeight(frame) - visibleReflectionHeight_));
CGPoint gradientEndPoint = CGPointMake(0, ((CGRectGetHeight(frame) * 2) - visibleReflectionHeight_));
// Draw gradient into gradient context.
CGContextDrawLinearGradient(gradientContext, grayScaleGradient, gradientStartPoint, gradientEndPoint, kCGGradientDrawsAfterEndLocation);
// Release Gradient reference.
CGGradientRelease(grayScaleGradient);
// Convert the gradient context to image.
gradientImage = CGBitmapContextCreateImage(gradientContext);
// Release gradient context
CGContextRelease(gradientContext);
}
CGContextRestoreGState(context);
// Apply gradient bitmap to new context that contains image.
CGContextSaveGState(context);
{
// Create a RGB color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Create bitmap context to join image and gradient context.
CGContextRef reflectionContext = CGBitmapContextCreate(NULL, CGRectGetWidth(frame), CGRectGetHeight(frame), 8, 0, colorSpace, (kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast));
// Release color space
CGColorSpaceRelease(colorSpace);
// First clip mask to context
CGContextSaveGState(context);
{
// Clip gradient mask to reflection context.
CGContextClipToMask(reflectionContext, frame, gradientImage);
}
CGContextRestoreGState(context);
// Second draw image to context
CGContextSaveGState(reflectionContext);
{
// Push context to draw image.
UIGraphicsPushContext(reflectionContext);
// Draw original image in top
[image_ drawInRect:frame];
// Pop to context
UIGraphicsPopContext();
}
CGContextRestoreGState(reflectionContext);
// Delete gradient image mask
CGImageRelease(gradientImage);
// Convert reflection context to image.
reflectionImage = CGBitmapContextCreateImage(reflectionContext);
// Release reflection context
CGContextRelease(reflectionContext);
}
CGContextRestoreGState(context);
// Transform matrix and draw reflection bitmap.
CGContextSaveGState(context);
{
// Translate context matrix to height * 2 but next scale and sum 1.0f of image and padding.
CGContextTranslateCTM(context, CGRectGetMinX(frame), (CGRectGetHeight(frame) * 2) + paddingToTopImage_);
// Flip vertical image in context.
CGContextScaleCTM(context, 1.0f, -1.0f);
// Draw reflection image in context.
CGContextDrawImage(context, frame, reflectionImage);
// Release reflectio image.
CGImageRelease(reflectionImage);
}
CGContextRestoreGState(context);
}
}
/**
* Set current image to another image.
*
* @param image: Another image to set.
*/
- (void)setImage:(UIImage *)image {
if (image_ != image) {
[image_ release];
image_ = [image retain];
}
[self setNeedsDisplay];
}
/**
* Set current visibleReflectioHeight_ value to another.
*
* @param gradientStart: Another value to visible reflectio height variable.
*/
- (void)setVisibleReflectionHeight:(CGFloat)visibleReflectioHeight {
if (visibleReflectionHeight_ != visibleReflectioHeight) {
visibleReflectionHeight_ = visibleReflectioHeight;
}
[self setNeedsDisplay];
}
/**
* Set current paddingToTopImage variable to another value.
*
* @param paddingToTopImage: Another value to padding to top image.
*/
- (void)setPaddingToTopImage:(CGFloat)paddingToTopImage {
if (paddingToTopImage_ != paddingToTopImage) {
paddingToTopImage_ = paddingToTopImage;
}
[self setNeedsDisplay];
}
@end
使用:
[cpp]
CKReflectionImage *reflectionImage = [[CKReflectionImage alloc] initWithFrame:CGRectMake(96, 20, 128, 460)];
[reflectionImage setBackgroundColor:[UIColor clearColor]];
//set the padding of top image and its reflected image
[reflectionImage setPaddingToTopImage:5.0f];
// Hide 1/4 parts of image. show 3/4
[reflectionImage setVisibleReflectionHeight:(CGRectGetWidth([reflectionImage frame]) / 4 * 3)];
[reflectionImage setImage:[UIImage imageNamed:@"1.png"]];
[[self view] addSubview:reflectionImage];
实现效果
实现二
为UIImage添加一个关于倒影的category,以实现返回这个图片,
[cpp]
#import <UIKit/UIKit.h>
@interface UIImage (Reflection)
- (UIImage *)reflectionWithHeight:(int)height;
- (UIImage *)reflectionWithAlpha:(float)pcnt;
- (UIImage *)reflectionRotatedWithAlpha:(float)pcnt;
@end
UIImage+Reflection.h
[cpp]
#import "UIImage+Reflection.h"
#ifndef UIImageReflectionMethods
#define UIImageReflectionMethods
CGImageRef CreateGradientImage (int pixelsWide, int pixelsHigh, CGFloat endPoint) {
CGImageRef theCGImage = NULL;
// gradient is always black-white and the mask must be in the gray colorspace
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
// create the bitmap context
CGContextRef gradientBitmapContext = CGBitmapContextCreate(NULL, pixelsWide, pixelsHigh, 8, 0, colorSpace, kCGImageAlphaNone);
// define the start and end grayscale values (with the alpha, even though
// our bitmap context doesn't support alpha the gradient requires it)
CGFloat colors[] = {0.0, 1.0, 1, 1.0};
// create the CGGradient and then release the gray color space
CGGradientRef grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2);
CGColorSpaceRelease(colorSpace);
// create the start and end points for the gradient vector (straight down)
CGPoint gradientStartPoint = CGPointZero;
CGPoint gradientEndPoint = CGPointMake(0, endPoint);
if (endPoint < 0) {
gradientEndPoint = CGPointMake(0, -endPoint);
}
// draw the gradient into the gray bitmap context
CGContextDrawLinearGradient(gradientBitmapContext, grayScaleGradient, gradientStartPoint, gradientEndPoint, kCGGradientDrawsAfterEndLocation);
CGGradientRelease(grayScaleGradient);
// convert the context into a CGImageRef and release the context
theCGImage = CGBitmapContextCreateImage(gradientBitmapContext);
if (endPoint < 0) {
// rotate
CGContextClearRect(gradientBitmapContext, CGRectMake(0, 0, pixelsWide, pixelsHigh));
CGContextTranslateCTM(gradientBitmapContext, 0.0, pixelsHigh);
CGContextScaleCTM(gradientBitmapContext, 1.0, -1.0);
CGContextDrawImage(gradientBitmapContext, CGRectMake(0, 0, pixelsWide, pixelsHigh), theCGImage);
CGImageRelease(theCGImage);
theCGImage = CGBitmapContextCreateImage(gradientBitmapContext);
}
CGContextRelease(gradientBitmapContext);
// return the imageref containing the gradient
return theCGImage;
}
static CGContextRef MyCreateBitmapContext (int pixelsWide, int pixelsHigh) {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// create the bitmap context
CGContextRef bitmapContext = CGBitmapContextCreate (NULL, pixelsWide, pixelsHigh, 8, 0, colorSpace, (kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
CGColorSpaceRelease(colorSpace);
return bitmapContext;
}
#endif
@implementation UIImage (Reflection)
- (UIImage *)reflectionRotatedWithAlpha:(float)pcnt {
int height = self.size.height;
UIImage * fromImage = self;
pcnt = 1.0 / pcnt;
// create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = MyCreateBitmapContext(fromImage.size.width, height);
// create a 2 bit CGImage containing a gradient that will be used for masking the
// main view content to create the 'fade' of the reflection. The CGImageCreateWithMask
// function will stretch the bitmap image as required, so we can create a 1 pixel wide gradient
CGImageRef gradientMaskImage = CreateGradientImage(1, height, -(height * pcnt));
// create an image by masking the bitmap of the mainView content with the gradient view
// then release the pre-masked content bitmap and the gradient bitmap
CGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, fromImage.size.width, height), gradientMaskImage);
CGImageRelease(gradientMaskImage);
// In order to grab the part of the image that we want to render, we move the context origin to the
// height of the image that we want to capture, then we flip the context so that the image draws upside down.
// CGContextTranslateCTM(mainViewContentContext, 0.0, height);
// CGContextScaleCTM(mainViewContentContext, 1.0, -1.0);
// draw the image into the bitmap context
CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, fromImage.size.width, fromImage.size.height), [fromImage CGImage]);
// create CGImageRef of the main view bitmap content, and then release that bitmap context
CGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
// convert the finished reflection image to a UIImage
UIImage * theImage = [UIImage imageWithCGImage:reflectionImage];
// image is retained by the property setting above, so we can release the original
CGImageRelease(reflectionImage);
return theImage;
}
- (UIImage *)reflectionWithHeight:(int)height {
if (height == -1) {
height = [self size].height;
}
if (height == 0)
return nil;
UIImage * fromImage = self;
// create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = MyCreateBitmapContext(fromImage.size.width, fromImage.size.height);
// create a 2 bit CGImage containing a gradient that will be used for masking the
// main view content to create the 'fade' of the reflection. The CGImageCreateWithMask
// function will stretch the bitmap image as required, so we can create a 1 pixel wide gradient
CGImageRef gradientMaskImage = CreateGradientImage(1, height, height);
// create an image by masking the bitmap of the mainView content with the gradient view
// then release the pre-masked content bitmap and the gradient bitmap
CGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, fromImage.size.width, height), gradientMaskImage);
CGImageRelease(gradientMaskImage);
// In order to grab the part of the image that we want to render, we move the context origin to the
// height of the image that we want to capture, then we flip the context so that the image draws upside down.
CGContextTranslateCTM(mainViewContentContext, 0.0, fromImage.size.height);
CGContextScaleCTM(mainViewContentContext, 1.0, -1.0);
// draw the image into the bitmap context
CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, fromImage.size.width, fromImage.size.height), [fromImage CGImage]);
// create CGImageRef of the main view bitmap content, and then release that bitmap context
CGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
// convert the finished reflection image to a UIImage
UIImage * theImage = [UIImage imageWithCGImage:reflectionImage];
// image is retained by the property setting above, so we can release the original
CGImageRelease(reflectionImage);
return theImage;
}
- (UIImage *)reflectionWithAlpha:(float)pcnt {
int height = self.size.height;
UIImage * fromImage = self;
pcnt = 1.0 / pcnt;
// create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = MyCreateBitmapContext(fromImage.size.width, height);
// create a 2 bit CGImage containing a gradient that will be used for masking the
// main view content to create the 'fade' of the reflection. The CGImageCreateWithMask
// function will stretch the bitmap image as required, so we can create a 1 pixel wide gradient
CGImageRef gradientMaskImage = CreateGradientImage(1, height, height * pcnt);
// create an image by masking the bitmap of the mainView content with the gradient view
// then release the pre-masked content bitmap and the gradient bitmap
CGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, fromImage.size.width, height), gradientMaskImage);
CGImageRelease(gradientMaskImage);
// In order to grab the part of the image that we want to render, we move the context origin to the
// height of the image that we want to capture, then we flip the context so that the image draws upside down.
CGContextTranslateCTM(mainViewContentContext, 0.0, height);
CGContextScaleCTM(mainViewContentContext, 1.0, -1.0);
// draw the image into the bitmap context
CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, fromImage.size.width, fromImage.size.height), [fromImage CGImage]);
// create CGImageRef of the main view bitmap content, and then release that bitmap context
CGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
// convert the finished reflection image to a UIImage
UIImage * theImage = [UIImage imageWithCGImage:reflectionImage];
// image is retained by the property setting above, so we can release the original
CGImageRelease(reflectionImage);
return theImage;
}
@end
使用非常简单:
[cpp]
[refView setImage:[image reflectionWithAlpha:0.5]];
[imageView setImage:[image reflectionWithHeight:50]];
[topRefView setImage:[image reflectionRotatedWithAlpha:0.5]];
效果
第三种:通过CAlayer来处理
- (void)viewDidLoad
{
- [super viewDidLoad];
- [[[self view] layer] setBackgroundColor:[[UIColor blackColor] CGColor]];
- UIImage *balloon = [UIImage imageNamed:@"1.png"]; //改一下图片名就行了
- CALayer *topLayer = [[CALayer alloc] init];
- [topLayer setBounds:CGRectMake(0.0f, 0.0f, 320.0, 240)];
- [topLayer setPosition:CGPointMake(160.0f, 120.0f)];
- [topLayer setContents:(id)[balloon CGImage]];
- [[[self view] layer] addSublayer:topLayer];
- CALayer *reflectionLayer = [[CALayer alloc] init];
- [reflectionLayer setBounds:CGRectMake(0.0f, 0.0f, 320.0, 240.0)];
- [reflectionLayer setPosition:CGPointMake(160.0f, 310.0f)];
- [reflectionLayer setContents:[topLayer contents]];
- [reflectionLayer setValue:[NSNumber numberWithFloat:180.0] forKeyPath:@"transform.rotation.x"];
- CAGradientLayer *gradientLayer = [[CAGradientLayer alloc] init];
- [gradientLayer setBounds:[reflectionLayer bounds]];
- [gradientLayer setPosition:CGPointMake([reflectionLayer bounds].size.width/2, [reflectionLayer bounds].size.height/2)];
- [gradientLayer setColors:[NSArray arrayWithObjects: (id)[[UIColor clearColor] CGColor],(id)[[UIColor blackColor] CGColor], nil]];
- [gradientLayer setStartPoint:CGPointMake(0.5,0.35)];
- [gradientLayer setEndPoint:CGPointMake(0.5,1.0)];
- [reflectionLayer setMask:gradientLayer];
- [[[self view] layer] addSublayer:reflectionLayer];
- // Do any additional setup after loading the view, typically from a nib.
- }