實現一
使用一個繼承自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] www.2cto.com 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]];
效果