ios - core graphics绘图时如何跳过一个区域(cutout)

标签 ios swift uikit core-graphics

我想绘制一些项目,但为圆形区域留下真正的 alpha 透明度切口。我想要实现的目标:

黄色是显示渗色的示例背景。

切口宽度实际上比圆弧笔划宽,因此它们不会完全相交。我需要真正的剪切,因为我要保存为透明图像。

我想也许我可以使用 setBlendMode() 但我相信只有当我希望我的切口与弧的宽度完全相同时它才会起作用。但是我试图解决它的要点是:

随后是 Swift 工作簿。非常感谢有关实现这一目标的任何提示。

import Foundation
import UIKit

var dimen: CGFloat = 200.0;
var strokeWidth: CGFloat = 20.0;
var cutoutWidth: CGFloat = 30.0;

class DonutView : UIView
{
    override func draw(_ rect: CGRect)
    {

        // cutout
        let cutoutColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1)
        cutoutColor.setFill()
        let cutoutPath = UIBezierPath(ovalIn: CGRect(x: dimen-cutoutWidth, y: dimen/2-cutoutWidth/2, width: cutoutWidth, height: cutoutWidth))
        cutoutPath.fill()

//        let context = UIGraphicsGetCurrentContext()!
//        context.setBlendMode(.sourceOut)

        let ringOffset = cutoutWidth/2;
        let circleWidth = dimen - ringOffset*2;

        // ring
        let ringPath = UIBezierPath(ovalIn: CGRect(x: ringOffset, y: ringOffset, width: circleWidth, height: circleWidth))
        let ringColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.3)
        ringColor.setStroke()
        ringPath.lineWidth = strokeWidth
        ringPath.stroke()

        // arc
        let arcRect = CGRect(x: ringOffset, y: ringOffset, width: circleWidth, height: circleWidth)
        let arcPath = UIBezierPath()
        arcPath.addArc(withCenter: CGPoint(x: arcRect.midX, y: arcRect.midY), radius: arcRect.width / 2, startAngle: -90 * CGFloat.pi/180, endAngle: 37 * CGFloat.pi/180, clockwise: true)

        let arcColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
        arcColor.setStroke()
        arcPath.lineWidth = strokeWidth
        arcPath.stroke()
    }
}

var view = DonutView(frame: CGRect.init(x: 0, y: 0, width: dimen, height: dimen))
view.backgroundColor = UIColor.yellow

// View these elements
view

(编辑:我应该在一开始就说明这一点:这是最终为 WatchKit 创建一个 UIImage)

最佳答案

How to clear circle in CGContext in iOS 的帮助下

import Foundation
import UIKit
import PlaygroundSupport

var dimen: CGFloat = 200.0;
var strokeWidth: CGFloat = 20.0;
var cutoutWidth: CGFloat = 30.0;

class DonutView : UIImageView
{
    override init(frame: CGRect) {
        super.init(frame: frame)

        UIGraphicsBeginImageContextWithOptions(CGSize(width: dimen, height: dimen), false, 1)
        let context = UIGraphicsGetCurrentContext()!

        let ringOffset = cutoutWidth/2;
        let circleWidth = dimen - ringOffset*2;

        // ring
        let ringPath = UIBezierPath(ovalIn: CGRect(x: ringOffset, y: ringOffset, width: circleWidth, height: circleWidth))
        let ringColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.3)
        ringColor.setStroke()
        ringPath.lineWidth = strokeWidth
        ringPath.stroke()

        // arc
        let arcRect = CGRect(x: ringOffset, y: ringOffset, width: circleWidth, height: circleWidth)
        let arcPath = UIBezierPath()
        arcPath.addArc(withCenter: CGPoint(x: arcRect.midX, y: arcRect.midY), radius: arcRect.width / 2, startAngle: -90 * CGFloat.pi/180, endAngle: 37 * CGFloat.pi/180, clockwise: true)        
        let arcColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
        arcColor.setStroke()
        arcPath.lineWidth = strokeWidth
        arcPath.stroke()

        // Cutout circle
        context.setFillColor(UIColor.clear.cgColor)
        context.setBlendMode(.clear)        
        context.addEllipse(in: CGRect(x: dimen-cutoutWidth, y: dimen/2-cutoutWidth/2, width: cutoutWidth, height: cutoutWidth))
        context.drawPath(using: .fill)
        context.setBlendMode(.normal)

        image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()        
        }

    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

var view = DonutView(frame: CGRect.init(x: 0, y: 0, width: dimen, height: dimen))
view.backgroundColor = UIColor.yellow

// View these elements
view

关于ios - core graphics绘图时如何跳过一个区域(cutout),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58063193/

相关文章:

ios - 错误 :Storyboard doesn't contain a view controller with identifier 'jailBrokenViewController' '

ios - 使用缓存文件的 Xcode 模拟器

swift - switch 性能优于枚举情况 O(1)

ios - 捕获 UIView 的图像(renderInContext 无法正常工作)

ios - 呈现 UIAlertController (以操作表样式)导致神秘的自动布局警告

ios - 设置 UIButton 大小以在 Storyboard 上显示

iOS不同的bundle id映射到同一个应用程序

iphone - NSMutableArray 不更新

ios - 有没有可能在 Xcode 8 中运行我的 swift 2 项目?

swift - Swift 中协议(protocol)的类型约束问题