Core Graphics で半透明図形を描く

図形を塗りつぶす。

        UIColor.red.setFill()
        UIBezierPath(rect: CGRect(x: 80, y: 80, width: 100, height: 100)).fill()

重ねて描く。

        UIColor.blue.setFill()
        UIBezierPath(rect: CGRect(x: 100, y: 100, width: 100, height: 100)).fill()

ここから半透明で図形を描く。

まず現在の描画文脈 CGContext インスタンスを得る。

        let context = UIGraphicsGetCurrentContext()!

alpha値を変更するので後でもとに戻す。

        context.saveGState()
        defer { context.restoreGState() }

alpha値を指定する。

        context.setAlpha(0.5)

不透明のときと同じように重ねて描く。

        UIColor.yellow.setFill()
        UIBezierPath(rect: CGRect(x: 120, y: 40, width: 100, height: 100)).fill()

        UIColor.cyan.setFill()
        UIBezierPath(rect: CGRect(x: 140, y: 60, width: 100, height: 100)).fill()

半透明の図形が重なる。

f:id:hrt1ro:20181009112424p:plain

さて「半透明図形を重ねる」のではなく、 「不透明図形を重ねたやつを半透明で重ねたい」という要件がある、 ということもあるかもしれない。

CGContext.beginTransparencyLayer(auxiliaryInfo:)APIドキュメントによるとこう書いてある。

The global alpha is set to 1.

setAlpha() の後、TransparencyLayerを beginend で囲めば、 不透明で重ねた図形を 半透明で描くことができる。

        context.beginTransparencyLayer(in: CGRect(x: 120.0, y: 40.0, width: 120.0, height: 120.0), auxiliaryInfo: nil)
        defer { context.endTransparencyLayer() }

こんなかんじ

f:id:hrt1ro:20181009112442p:plain

beginendはネストできるので、beginendの間で setAlpha() すればネストした内と外の alpha値を乗算した半透明で描かれることになる。