我一直對繪畫與內發光的路徑,並以某種方式成功(至少對我的口味)。
我實現了在levinunnick's Smooth-Line-View頂部的繪製代碼。該代碼是MIT許可的,因此您需要將其添加到您的項目中。
目前,您可以指定線的顏色,寬度和你想畫線的平滑度。注意平滑度,使用0到1之間的浮點數。我更改了觸摸方法,因爲我需要從另一個視圖訪問繪圖方法。如果您想恢復到觸摸方式,請檢查原始代碼。
我沒有優化代碼,如果你有更好的主意,只需編輯這個答案。
這裏是.h文件:
@interface LineView : UIView
- (instancetype)initWithFrame:(CGRect)frame andColor:(UIColor *)lineColor andWidth:(CGFloat)lineWidth andSmoothness:(CGFloat)lineSmooth;
- (void)touchStartedWith:(CGPoint)location;
- (void)touchMovedWith:(CGPoint)location;
@end
這是M檔:
#import "LineView.h"
static const CGFloat kPointMinDistance = 0.05f;
static const CGFloat kPointMinDistanceSquared = kPointMinDistance * kPointMinDistance;
@interface LineView()
@property (strong) UIColor *lineColor;
@property (assign) CGFloat lineWidth;
@property (assign) CGFloat lineSmooth;
@property (assign) CGPoint currentPoint;
@property (assign) CGPoint previousPoint;
@property (assign) CGPoint previousPreviousPoint;
@end
@implementation LineView
{
@private
CGMutablePathRef _path;
}
- (instancetype)initWithFrame:(CGRect)frame andColor:(UIColor *)lineColor andWidth:(CGFloat)lineWidth andSmoothness:(CGFloat)lineSmooth
{
self = [super initWithFrame:frame];
if (self) {
_path = CGPathCreateMutable();
if (lineSmooth < 0) lineSmooth = 0;
if (lineSmooth > 1) lineSmooth = 1;
self.backgroundColor = [UIColor clearColor];
self.lineColor = lineColor;
self.lineWidth = lineWidth;
self.lineSmooth = lineWidth * (lineSmooth/4);
self.opaque = NO;
}
return self;
}
- (void)drawRect:(CGRect)rect
{
[self.backgroundColor set];
UIRectFill(rect);
@autoreleasepool {
CGColorRef theColor = self.lineColor.CGColor;
UIColor *theClearOpaque = [[UIColor whiteColor] colorWithAlphaComponent:1];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, _path);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, theColor);
// Outer shadow
CGSize shadowOffset = CGSizeMake(0.1f, -0.1f);
CGFloat shadowBlurRadius = self.lineSmooth;
CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, theColor);
CGContextStrokePath(context);
if (self.lineSmooth > 0) {
// Inner shadow
CGRect bounds = CGPathGetBoundingBox(_path);
CGRect drawBox = CGRectInset(bounds, -2.0f * self.lineWidth, -2.0f * self.lineWidth);
CGContextSaveGState(context);
UIRectClip(drawBox);
CGContextSetShadowWithColor(context, CGSizeZero, 0, NULL);
CGContextSetAlpha(context, CGColorGetAlpha(theClearOpaque.CGColor));
CGContextBeginTransparencyLayer(context, NULL);
{
// Outer shadow
UIColor *oShadow = [theClearOpaque colorWithAlphaComponent:1];
CGContextSetShadowWithColor(context, CGSizeMake(0.1f, -0.1f), self.lineWidth/64 * self.lineSmooth, oShadow.CGColor);
CGContextSetBlendMode(context, kCGBlendModeSourceOut);
CGContextBeginTransparencyLayer(context, NULL);
[oShadow setFill];
// Draw the line again
CGContextAddPath(context, _path);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, oShadow.CGColor);
CGContextStrokePath(context);
CGContextEndTransparencyLayer(context);
}
CGContextEndTransparencyLayer(context);
CGContextRestoreGState(context);
}
}
}
- (void)touchStartedWith:(CGPoint)location
{
self.previousPoint = location;
self.previousPreviousPoint = location;
self.currentPoint = location;
[self touchMovedWith:location];
}
- (void)touchMovedWith:(CGPoint)location
{
CGRect drawBox;
@autoreleasepool {
CGFloat dx = location.x - self.currentPoint.x;
CGFloat dy = location.y - self.currentPoint.y;
if ((dx * dx + dy * dy) < kPointMinDistanceSquared) {
return;
}
self.previousPreviousPoint = self.previousPoint;
self.previousPoint = self.currentPoint;
self.currentPoint = location;
CGPoint mid1 = midPoint(self.previousPoint, self.previousPreviousPoint);
CGPoint mid2 = midPoint(self.currentPoint, self.previousPoint);
CGMutablePathRef subpath = CGPathCreateMutable();
CGPathMoveToPoint(subpath, NULL, mid1.x, mid1.y);
CGPathAddQuadCurveToPoint(subpath, NULL, self.previousPoint.x, self.previousPoint.y, mid2.x, mid2.y);
CGRect bounds = CGPathGetBoundingBox(subpath);
drawBox = CGRectInset(bounds, -2.0f * self.lineWidth, -2.0f * self.lineWidth);
CGPathAddPath(_path, NULL, subpath);
CGPathRelease(subpath);
}
[self setNeedsDisplayInRect:drawBox];
}
- (void)dealloc
{
CGPathRelease(_path);
_path = NULL;
}
@end
它看起來像你正在使用矩形?你會如何做到這一點中風? – ninjaneer 2014-08-09 00:17:09
@Ninja是的,它是矩形,你想在'touchesMoved'中畫線並且有相同的影響嗎? – mohacs 2014-08-09 00:57:46
我不知道這會如何影響性能,但如果它達到了中風路徑的效果,那就沒問題。 – ninjaneer 2014-08-09 00:59:02