グラデーションを持つビューに内側の境界線を追加したい。次のコードは動作し、私にこの結果CAGradientLayerにマスクを追加するとUIBezierPathが消える
import UIKit
class InnerGradientBorderView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.clear
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
backgroundColor = UIColor.clear
}
override func draw(_ rect: CGRect) {
super.draw(rect)
addGradientInnerBorder(width: 8, color: FlatWhite())
}
func addGradientInnerBorder(width: CGFloat, color: UIColor) {
// Setup
let topLeftO = CGPoint(x: 0, y: 0)
let topLeftI = CGPoint(x: width, y: width)
let topRightO = CGPoint(x: frame.width, y: 0)
let topRightI = CGPoint(x: frame.width - width, y: width)
let bottomLeftO = CGPoint(x: 0, y: frame.height)
let bottomLeftI = CGPoint(x: width, y: frame.height - width)
let bottomRightO = CGPoint(x: frame.width, y: frame.height)
let bottomRightI = CGPoint(x: frame.width - width, y: frame.height - width)
// Top
let topPoints = [topLeftO, topLeftI, topRightI, topRightO, topLeftO]
let topGradientPoints = [CGPoint(x: 0, y: 0), CGPoint(x: 0, y: 1)]
addGradientToBeizerPath(path: addClosedPathForPoints(points: topPoints), color: color, gradientPoints: topGradientPoints)
// Left
let leftPoints = [topLeftO, topLeftI, bottomLeftI, bottomLeftO, topLeftO]
let leftGradientPoints = [CGPoint(x: 0, y: 0), CGPoint(x: 1, y: 0)]
addGradientToBeizerPath(path: addClosedPathForPoints(points: leftPoints), color: color, gradientPoints: leftGradientPoints)
// Right
let rightPoints = [topRightO, topRightI, bottomRightI, bottomRightO, topRightO]
let rightGradientPoints = [CGPoint(x: 1, y: 0), CGPoint(x: 0, y: 0)]
addGradientToBeizerPath(path: addClosedPathForPoints(points: rightPoints), color: color, gradientPoints: rightGradientPoints)
// Bottom
let bottomPoints = [bottomLeftO, bottomLeftI, bottomRightI, bottomRightO, bottomLeftO]
let bottomGradientPoints = [CGPoint(x: 0, y: 1), CGPoint(x: 0, y: 0)]
addGradientToBeizerPath(path: addClosedPathForPoints(points: bottomPoints), color: color, gradientPoints: bottomGradientPoints)
}
func addClosedPathForPoints(points: [CGPoint]) -> UIBezierPath? {
guard points.count == 5 else { return nil }
let path = UIBezierPath()
path.move(to: points[0])
path.addLine(to: points[1])
path.addLine(to: points[2])
path.addLine(to: points[3])
path.addLine(to: points[4])
path.close()
return path
}
func addGradientToBeizerPath(path: UIBezierPath?, color: UIColor, gradientPoints: [CGPoint]) {
guard let path = path, gradientPoints.count == 2 else { return }
let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [color.cgColor, UIColor.clear.cgColor]
gradient.startPoint = gradientPoints[0]
gradient.endPoint = gradientPoints[1]
// let shapeMask = CAShapeLayer()
// shapeMask.path = path.cgPath
// gradient.mask = shapeMask
self.layer.insertSublayer(gradient, at: 0)
}
}
あなたは縁がgreat.Toが、私は角度のエッジを与えている、それを修正することを見ていないことがわかりますを提供します。私はこの角度で、この勾配にマスクを適用すると、右と下のパスは次のように消える:
私がここでやっているすべては、いくつかのクローズドbezierPathsを使用して、それらにグラデーションを適用しています。グラデーションにマスクがある場合(コメント付きコードのコメントが外されている)、パスの2つが消えます。私は何かを理解していないと感じているので、ここの誰かがCAShapeLayerの使い方を正しく教えてくれればうれしいです。
あなたがいる理由私は理解していません'draw'メソッドの内側から' CAGradientLayer'をビューの 'layer'に追加すると、間違って感じられます。あなたが達成しようとしていることを説明できますか? – Echelon
これを追加するのはサイズ変更可能です。ビューを描画するか再描画する必要があるときはいつでも、 'draw'メソッドが呼び出されるので、私はそこで作業をすると考えました。あなたはより良い実装を念頭に置いていましたか? –
うん、 'layoutSubviews'かどこか。レイヤーの階層を変更するのではなく、レンダリングを実際に実行するためにのみ 'draw'をオーバーライドする必要があります。あなたが 'draw'呼び出しの結果としてレイヤーを挿入し、私が見ることができるものを決して削除しないので、あなたは何百ものレイヤーで終わるでしょうか?私は実際にあなたが達成しようとしていることを理解するために苦労している... – Echelon