123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- //
- // YYTextMagnifier.m
- // YYKit <https://github.com/ibireme/YYKit>
- //
- // Created by ibireme on 15/2/25.
- // Copyright (c) 2015 ibireme.
- //
- // This source code is licensed under the MIT-style license found in the
- // LICENSE file in the root directory of this source tree.
- //
- #import "YYTextMagnifier.h"
- #import "YYCGUtilities.h"
- #define kCaptureDisableFadeTime 0.1
- @interface _YYTextMagnifierCaret : YYTextMagnifier {
- UIImageView *_contentView;
- UIImageView *_coverView;
- }
- @end
- @implementation _YYTextMagnifierCaret
- #define kMultiple 1.2
- #define kDiameter 113.0
- #define kPadding 7.0
- #define kSize CGSizeMake(kDiameter + kPadding * 2, kDiameter + kPadding * 2)
- - (instancetype)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- _contentView = [UIImageView new];
- _contentView.frame = CGRectMake(kPadding, kPadding, kDiameter, kDiameter);
- _contentView.layer.cornerRadius = kDiameter / 2;
- _contentView.clipsToBounds = YES;
- [self addSubview:_contentView];
-
- _coverView = [UIImageView new];
- _coverView.frame = (CGRect){.origin = CGPointZero, .size = kSize};
- _coverView.image = [self.class coverImage];
- [self addSubview:_coverView];
- return self;
- }
- - (instancetype)init {
- self = [self initWithFrame:CGRectZero];
- self.frame = (CGRect){.size = [self sizeThatFits:CGSizeZero]};
- return self;
- }
- - (YYTextMagnifierType)type {
- return YYTextMagnifierTypeCaret;
- }
- - (CGSize)sizeThatFits:(CGSize)size {
- return kSize;
- }
- - (void)setSnapshot:(UIImage *)snapshot {
- if (self.captureFadeAnimation) {
- [_contentView.layer removeAnimationForKey:@"contents"];
- CABasicAnimation *animation = [CABasicAnimation animation];
- animation.duration = kCaptureDisableFadeTime;
- animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
- [_contentView.layer addAnimation:animation forKey:@"contents"];
- }
- _contentView.image = snapshot;
- }
- - (UIImage *)snapshot {
- return _contentView.image;
- }
- - (CGSize)snapshotSize {
- CGFloat length = floor(kDiameter / 1.2);
- return CGSizeMake(length, length);
- }
- - (CGSize)fitSize {
- return [self sizeThatFits:CGSizeZero];
- }
- + (UIImage *)coverImage {
- static UIImage *image;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- CGSize size = kSize;
- CGRect rect = (CGRect) {.size = size, .origin = CGPointZero};
- rect = CGRectInset(rect, kPadding, kPadding);
-
- UIGraphicsBeginImageContextWithOptions(size, NO, 0);
- CGContextRef context = UIGraphicsGetCurrentContext();
-
- CGPathRef boxPath = CGPathCreateWithRect(CGRectMake(0, 0, size.width, size.height), NULL);
- CGPathRef fillPath = CGPathCreateWithEllipseInRect(rect, NULL);
- CGPathRef strokePath = CGPathCreateWithEllipseInRect(CGRectPixelHalf(rect), NULL);
-
- // inner shadow
- CGContextSaveGState(context); {
- CGFloat blurRadius = 25;
- CGSize offset = CGSizeMake(0, 15);
- CGColorRef shadowColor = [UIColor colorWithWhite:0 alpha:0.16].CGColor;
- CGColorRef opaqueShadowColor = CGColorCreateCopyWithAlpha(shadowColor, 1.0);
- CGContextAddPath(context, fillPath);
- CGContextClip(context);
- CGContextSetAlpha(context, CGColorGetAlpha(shadowColor));
- CGContextBeginTransparencyLayer(context, NULL); {
- CGContextSetShadowWithColor(context, offset, blurRadius, opaqueShadowColor);
- CGContextSetBlendMode(context, kCGBlendModeSourceOut);
- CGContextSetFillColorWithColor(context, opaqueShadowColor);
- CGContextAddPath(context, fillPath);
- CGContextFillPath(context);
- } CGContextEndTransparencyLayer(context);
- CGColorRelease(opaqueShadowColor);
- } CGContextRestoreGState(context);
-
- // outer shadow
- CGContextSaveGState(context); {
- CGContextAddPath(context, boxPath);
- CGContextAddPath(context, fillPath);
- CGContextEOClip(context);
- CGColorRef shadowColor = [UIColor colorWithWhite:0 alpha:0.32].CGColor;
- CGContextSetShadowWithColor(context, CGSizeMake(0, 1.5), 3, shadowColor);
- CGContextBeginTransparencyLayer(context, NULL); {
- CGContextAddPath(context, fillPath);
- [[UIColor colorWithWhite:0.7 alpha:1.000] setFill];
- CGContextFillPath(context);
- } CGContextEndTransparencyLayer(context);
- } CGContextRestoreGState(context);
-
- // stroke
- CGContextSaveGState(context); {
- CGContextAddPath(context, strokePath);
- [[UIColor colorWithWhite:0.6 alpha:1] setStroke];
- CGContextSetLineWidth(context, CGFloatFromPixel(1));
- CGContextStrokePath(context);
- } CGContextRestoreGState(context);
-
- CFRelease(boxPath);
- CFRelease(fillPath);
- CFRelease(strokePath);
-
- image = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
-
- });
- return image;
- }
- #undef kMultiple
- #undef kDiameter
- #undef kPadding
- #undef kSize
- @end
- @interface _YYTextMagnifierRanged : YYTextMagnifier {
- UIImageView *_contentView;
- UIImageView *_coverView;
- }
- @end
- @implementation _YYTextMagnifierRanged
- #define kMultiple 1.2
- #define kSize CGSizeMake(141, 60)
- #define kPadding CGFloatPixelHalf(6.0)
- #define kRadius 6.0
- #define kHeight 32.0
- #define kArrow 14.0
- - (instancetype)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- _contentView = [UIImageView new];
- _contentView.frame = CGRectMake(kPadding, kPadding, kSize.width - 2 * kPadding, kHeight);
- _contentView.layer.cornerRadius = kRadius;
- _contentView.clipsToBounds = YES;
- [self addSubview:_contentView];
-
- _coverView = [UIImageView new];
- _coverView.frame = (CGRect){.origin = CGPointZero, .size = kSize};
- _coverView.image = [self.class coverImage];
- [self addSubview:_coverView];
-
- self.layer.anchorPoint = CGPointMake(0.5, 1.2);
- return self;
- }
- - (instancetype)init {
- self = [self initWithFrame:CGRectZero];
- self.frame = (CGRect){.size = [self sizeThatFits:CGSizeZero]};
- return self;
- }
- - (YYTextMagnifierType)type {
- return YYTextMagnifierTypeRanged;
- }
- - (CGSize)sizeThatFits:(CGSize)size {
- return kSize;
- }
- - (void)setSnapshot:(UIImage *)snapshot {
- if (self.captureFadeAnimation) {
- [_contentView.layer removeAnimationForKey:@"contents"];
- CABasicAnimation *animation = [CABasicAnimation animation];
- animation.duration = kCaptureDisableFadeTime;
- animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
- [_contentView.layer addAnimation:animation forKey:@"contents"];
- }
- _contentView.image = snapshot;
- }
- - (UIImage *)snapshot {
- return _contentView.image;
- }
- - (CGSize)snapshotSize {
- CGSize size;
- size.width = floor((kSize.width - 2 * kPadding) / kMultiple);
- size.height = floor(kHeight / kMultiple);
- return size;
- }
- - (CGSize)fitSize {
- return [self sizeThatFits:CGSizeZero];
- }
- + (UIImage *)coverImage {
- static UIImage *image;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- CGSize size = kSize;
- CGRect rect = (CGRect) {.size = size, .origin = CGPointZero};
-
- UIGraphicsBeginImageContextWithOptions(size, NO, 0);
- CGContextRef context = UIGraphicsGetCurrentContext();
-
- CGPathRef boxPath = CGPathCreateWithRect(rect, NULL);
-
- CGMutablePathRef path = CGPathCreateMutable();
- CGPathMoveToPoint(path, NULL, kPadding + kRadius, kPadding);
- CGPathAddLineToPoint(path, NULL, size.width - kPadding - kRadius, kPadding);
- CGPathAddQuadCurveToPoint(path, NULL, size.width - kPadding, kPadding, size.width - kPadding, kPadding + kRadius);
- CGPathAddLineToPoint(path, NULL, size.width - kPadding, kHeight);
- CGPathAddCurveToPoint(path, NULL, size.width - kPadding, kPadding + kHeight, size.width - kPadding - kRadius, kPadding + kHeight, size.width - kPadding - kRadius, kPadding + kHeight);
- CGPathAddLineToPoint(path, NULL, size.width / 2 + kArrow, kPadding + kHeight);
- CGPathAddLineToPoint(path, NULL, size.width / 2, kPadding + kHeight + kArrow);
- CGPathAddLineToPoint(path, NULL, size.width / 2 - kArrow, kPadding + kHeight);
- CGPathAddLineToPoint(path, NULL, kPadding + kRadius, kPadding + kHeight);
- CGPathAddQuadCurveToPoint(path, NULL, kPadding, kPadding + kHeight, kPadding, kHeight);
- CGPathAddLineToPoint(path, NULL, kPadding, kPadding + kRadius);
- CGPathAddQuadCurveToPoint(path, NULL, kPadding, kPadding, kPadding + kRadius, kPadding);
- CGPathCloseSubpath(path);
-
- CGMutablePathRef arrowPath = CGPathCreateMutable();
- CGPathMoveToPoint(arrowPath, NULL, size.width / 2 - kArrow, CGFloatPixelFloor(kPadding) + kHeight);
- CGPathAddLineToPoint(arrowPath, NULL, size.width / 2 + kArrow, CGFloatPixelFloor(kPadding) + kHeight);
- CGPathAddLineToPoint(arrowPath, NULL, size.width / 2, kPadding + kHeight + kArrow);
- CGPathCloseSubpath(arrowPath);
-
- // inner shadow
- CGContextSaveGState(context); {
- CGFloat blurRadius = 25;
- CGSize offset = CGSizeMake(0, 15);
- CGColorRef shadowColor = [UIColor colorWithWhite:0 alpha:0.16].CGColor;
- CGColorRef opaqueShadowColor = CGColorCreateCopyWithAlpha(shadowColor, 1.0);
- CGContextAddPath(context, path);
- CGContextClip(context);
- CGContextSetAlpha(context, CGColorGetAlpha(shadowColor));
- CGContextBeginTransparencyLayer(context, NULL); {
- CGContextSetShadowWithColor(context, offset, blurRadius, opaqueShadowColor);
- CGContextSetBlendMode(context, kCGBlendModeSourceOut);
- CGContextSetFillColorWithColor(context, opaqueShadowColor);
- CGContextAddPath(context, path);
- CGContextFillPath(context);
- } CGContextEndTransparencyLayer(context);
- CGColorRelease(opaqueShadowColor);
- } CGContextRestoreGState(context);
-
- // outer shadow
- CGContextSaveGState(context); {
- CGContextAddPath(context, boxPath);
- CGContextAddPath(context, path);
- CGContextEOClip(context);
- CGColorRef shadowColor = [UIColor colorWithWhite:0 alpha:0.32].CGColor;
- CGContextSetShadowWithColor(context, CGSizeMake(0, 1.5), 3, shadowColor);
- CGContextBeginTransparencyLayer(context, NULL); {
- CGContextAddPath(context, path);
- [[UIColor colorWithWhite:0.7 alpha:1.000] setFill];
- CGContextFillPath(context);
- } CGContextEndTransparencyLayer(context);
- } CGContextRestoreGState(context);
-
- // arrow
- CGContextSaveGState(context); {
- CGContextAddPath(context, arrowPath);
- [[UIColor colorWithWhite:1 alpha:0.95] set];
- CGContextFillPath(context);
- } CGContextRestoreGState(context);
-
- // stroke
- CGContextSaveGState(context); {
- CGContextAddPath(context, path);
- [[UIColor colorWithWhite:0.6 alpha:1] setStroke];
- CGContextSetLineWidth(context, CGFloatFromPixel(1));
- CGContextStrokePath(context);
- } CGContextRestoreGState(context);
-
- CFRelease(boxPath);
- CFRelease(path);
- CFRelease(arrowPath);
-
- image = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
-
- });
- return image;
- }
- #undef kMultiple
- #undef kSize
- #undef kPadding
- #undef kRadius
- #undef kHeight
- #undef kArrow
- @end
- @implementation YYTextMagnifier
- + (id)magnifierWithType:(YYTextMagnifierType)type {
- switch (type) {
- case YYTextMagnifierTypeCaret :return [_YYTextMagnifierCaret new];
- case YYTextMagnifierTypeRanged :return [_YYTextMagnifierRanged new];
- }
- return nil;
- }
- - (id)initWithFrame:(CGRect)frame {
- // class cluster
- if ([self isMemberOfClass:[YYTextMagnifier class]]) {
- @throw [NSException exceptionWithName:NSStringFromClass([self class]) reason:@"Attempting to instantiate an abstract class. Use a concrete subclass instead." userInfo:nil];
- return nil;
- }
- self = [super initWithFrame:frame];
- return self;
- }
- @end
|