【问题标题】:How to show only corners of CALayer rectangle in macOS Objective-c?如何在 macOS Objective-c 中仅显示 CALayer 矩形的角?
【发布时间】:2019-12-11 08:38:49
【问题描述】:

我提到了一些问题thisthis。但无法得到我想要的解决方案, 我可以绘制矩形,但不能只显示矩形的角。

我正在屏蔽矩形以具有笔触颜色和填充颜色,同样我试图使其仅显示 4 个角。

CALayer *rectangleMaskLayer = [CALayer layer];
[self.layer addSublayer:rectangleMaskLayer];    
CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
CGMutablePathRef pathRef = CGPathCreateMutable();
CGRect dispRect = CGRectMake(10, 20, 100, 100);
shapeLayer.fillColor = [NSColor greenColor].CGColor;
shapeLayer.lineWidth = 1;
shapeLayer.strokeColor = [NSColor blackColor].CGColor;
pathRef = CGPathCreateMutable();
CGPoint startTopPoint = CGPointMake(dispRect.origin.x - 5, dispRect.origin.y);
CGPoint endTopPoint = CGPointMake(dispRect.origin.x + dispRect.size.width + 5, dispRect.origin.y);
CGRect innerRect = CGRectMake(dispRect.origin.x + 3, dispRect.origin.y + 3, dispRect.size.width - 3, dispRect.size.height - 3);
CGRect outerRect = CGRectMake(dispRect.origin.x, dispRect.origin.y, dispRect.size.width + 3, dispRect.size.height + 3);
CGPathAddRect(pathRef, NULL, outerRect);
CGPathAddRect(pathRef, NULL, innerRect);
shapeLayer.path = pathRef;
shapeLayer.fillRule = kCAFillRuleEvenOdd;
[afTrarectangleMaskLayerublayer:_trackingPositionShapeLayer];

提前谢谢你

【问题讨论】:

    标签: objective-c macos calayer


    【解决方案1】:

    更新: 错误地没有注意到所需的 macOS,因此添加了 macOS 变体。还保留了 iOS 版本,以防万一。

    ma​​cOS 变体:(NSBezierPath 到 CGPathRef 从here

    #import "ViewController.h"
    #import <QuartzCore/QuartzCore.h>
    
    @interface NSBezierPath (BezierPathQuartzUtilities)
    - (CGPathRef)cgPath;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.view.wantsLayer = YES;
    
        CALayer *root = self.view.layer;
        root.backgroundColor = NSColor.blueColor.CGColor;
    
        CALayer *frameLayer = [self createFrameLayerWithSize:CGSizeMake(200, 200)];
        [root addSublayer:frameLayer];
        frameLayer.position = CGPointMake(CGRectGetMidX(root.bounds), CGRectGetMidY(root.bounds));
    }
    
    - (CALayer *)createFrameLayerWithSize:(CGSize)size {
        CAShapeLayer *layer = CAShapeLayer.new;
        layer.bounds = CGRectMake(0, 0, size.width, size.height);
    
        CGFloat kPiece = 40.0; // << can be configured
        NSBezierPath *path = NSBezierPath.new;
        [path moveToPoint:CGPointMake(0, kPiece)];
        [path lineToPoint:CGPointMake(0, 0)];
        [path lineToPoint:CGPointMake(kPiece, 0)];
        [path moveToPoint:CGPointMake(size.width - kPiece, 0)];
        [path lineToPoint:CGPointMake(size.width, 0)];
        [path lineToPoint:CGPointMake(size.width, kPiece)];
        [path moveToPoint:CGPointMake(size.width, size.height - kPiece)];
        [path lineToPoint:CGPointMake(size.width, size.height)];
        [path lineToPoint:CGPointMake(size.width - kPiece, size.height)];
        [path moveToPoint:CGPointMake(kPiece, size.height)];
        [path lineToPoint:CGPointMake(0, size.height)];
        [path lineToPoint:CGPointMake(0, size.height - kPiece)];
    
        layer.path = [path cgPath];
        layer.strokeColor = NSColor.whiteColor.CGColor; // << can be configured
        layer.fillColor = NSColor.clearColor.CGColor; // !! required for transparency
        layer.lineWidth = 8.0; // << can be configured
        return layer;
    }
    
    @end
    
    @implementation NSBezierPath (BezierPathQuartzUtilities)
    - (CGPathRef)cgPath
    {
        NSInteger i, numElements;
    
        // Need to begin a path here.
        CGPathRef           immutablePath = NULL;
    
        // Then draw the path elements.
        numElements = [self elementCount];
        if (numElements > 0)
        {
            CGMutablePathRef    path = CGPathCreateMutable();
            NSPoint             points[3];
            BOOL                didClosePath = YES;
    
            for (i = 0; i < numElements; i++)
            {
                switch ([self elementAtIndex:i associatedPoints:points])
                {
                    case NSMoveToBezierPathElement:
                        CGPathMoveToPoint(path, NULL, points[0].x, points[0].y);
                        break;
    
                    case NSLineToBezierPathElement:
                        CGPathAddLineToPoint(path, NULL, points[0].x, points[0].y);
                        didClosePath = NO;
                        break;
    
                    case NSCurveToBezierPathElement:
                        CGPathAddCurveToPoint(path, NULL, points[0].x, points[0].y,
                                            points[1].x, points[1].y,
                                            points[2].x, points[2].y);
                        didClosePath = NO;
                        break;
    
                    case NSClosePathBezierPathElement:
                        CGPathCloseSubpath(path);
                        didClosePath = YES;
                        break;
                }
            }
    
            immutablePath = CGPathCreateCopy(path);
            CGPathRelease(path);
        }
    
        return immutablePath;
    }
    @end
    

    iOS 版本:

    这里是一个如何绘制corner-rect图层本身的演示(布局等超出范围)

    这是截图上的演示代码

    @interface ViewController : UIViewController
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        CALayer *root = self.view.layer;
        root.backgroundColor = UIColor.blueColor.CGColor;
    
        CALayer *frameLayer = [self createFrameLayerWithSize:CGSizeMake(200, 200)];
        [root addSublayer:frameLayer];
        frameLayer.position = CGPointMake(CGRectGetMidX(root.bounds), CGRectGetMidY(root.bounds));
    }
    
    - (CALayer *)createFrameLayerWithSize:(CGSize)size {
        CAShapeLayer *layer = CAShapeLayer.new;
        layer.bounds = CGRectMake(0, 0, size.width, size.height);
    
        CGFloat kPiece = 40.0; // << can be configured
        UIBezierPath *path = UIBezierPath.new;
        [path moveToPoint:CGPointMake(0, kPiece)];
        [path addLineToPoint:CGPointMake(0, 0)];
        [path addLineToPoint:CGPointMake(kPiece, 0)];
        [path moveToPoint:CGPointMake(size.width - kPiece, 0)];
        [path addLineToPoint:CGPointMake(size.width, 0)];
        [path addLineToPoint:CGPointMake(size.width, kPiece)];
        [path moveToPoint:CGPointMake(size.width, size.height - kPiece)];
        [path addLineToPoint:CGPointMake(size.width, size.height)];
        [path addLineToPoint:CGPointMake(size.width - kPiece, size.height)];
        [path moveToPoint:CGPointMake(kPiece, size.height)];
        [path addLineToPoint:CGPointMake(0, size.height)];
        [path addLineToPoint:CGPointMake(0, size.height - kPiece)];
    
        layer.path = path.CGPath;
        layer.strokeColor = UIColor.whiteColor.CGColor; // << can be configured
        layer.fillColor = UIColor.clearColor.CGColor; // !! required for transparency
        layer.lineWidth = 8.0; // << can be configured
        return layer;
    }
    @end
    

    【讨论】:

    • 问题被标记为macOS,并且没有NSBezierPath.cgPath 等价物。
    • @Asperi 爱你,兄弟。 :-) 你节省了我的时间。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多