Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
937 views
in Technique[技术] by (71.8m points)

ios - Masking a CAShapeLayer creates this weird artifact?

I want to create a smooth progress bar for a to-do list. I used a circle (CGMutablePath) that masks the gray area and there's an obvious arc-like artifact. Not only that but there's also an artifact on the right side of the bar.

Note: I tried to rasterize the layers to no avail.

What causes iOS to do this and how can I smooth this out or get rid of it?

private var circleMask: CAShapeLayer = CAShapeLayer()
override func layoutSubviews() {
    super.layoutSubviews()
    backgroundColor = GradientColor(.leftToRight, frame: self.bounds, colors: GradientFlatRed())
    layer.cornerRadius = bounds.height / 2
    plainProgressBar.layer.cornerRadius = layer.cornerRadius
    layer.shouldRasterize = true
    layer.rasterizationScale = UIScreen.main.scale

    plainProgressBar.layer.shouldRasterize = true
    plainProgressBar.layer.rasterizationScale = UIScreen.main.scale

    createMask()


}

private func createMask() {
    let path = CGMutablePath()
    path.addArc(center: CGPoint(x: bounds.origin.x+25/2, y: bounds.origin.y+25/2), radius: 25/2, startAngle: 0, endAngle: CGFloat(Double.pi*2), clockwise: false)
    path.addRect(bounds)
    circleMask.path = path
    circleMask.backgroundColor = plainMeterColor.cgColor
    circleMask.fillRule = kCAFillRuleEvenOdd
    plainProgressBar.layer.mask = circleMask
}

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The issue is clearly an error in composition of the antialiased edges.

Knee-jerk question: do you have an atypical blend mode set?

Easiest solution: don't use path.addArc and path.addRect to generate two completely distinct shapes. Just use one of the init(roundedRect:... methods and set a corner radius of half your height, stretching the total path beyond the available space to the left to create a hard edge.

Or, if that doesn't appear, construct the path manually as a move, addLine(to:, addArc of only half a circle, then a final addLine(to: and a close. E.g. (thoroughly untested, especially re: start and end angles and clockwise versus anticlockwise versus iOS's upside-down coordinate system)

private func createMask() {
    let path = CGMutablePath()
    path.move(to: CGPoint(x: 0, y:0))
    path.addLine(to: CGPoint(x: bounds.origin.x+25/2, y: 0))
    path.addArc(center: CGPoint(x: bounds.origin.x+25/2, y: bounds.origin.y+25/2), radius: 25/2, startAngle: CGFloat(Double.pi/2.0), endAngle: CGFloat(Double.pi*3.0/2.0), clockwise: false)
    path.addLine(to: CGPoint(x: 0, y: 25))
    path.close()
    ...

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...