【问题标题】:UIBezierPath and CAShapeLayerUIBezierPath 和 CAShapeLayer
【发布时间】:2018-10-31 20:40:24
【问题描述】:

我想得到一个上角圆角的矩形。为此,我使用UIBezierPathCAShapeLayer

问题是左角是正确的,而右角不是,我不明白为什么会这样,我做错了什么。

使当前代码有效对我来说很重要,通过cornerRadius 或其他方式解决问题,不幸的是,我不感兴趣。

当前结果图片

必填结果图片 .

import UIKit

func getRadians(from degrees: CGFloat) -> CGFloat {
    return degrees * CGFloat.pi / 180
}

let view = UIView()
view.backgroundColor = .green

let width: CGFloat = 800
let height: CGFloat = 400

view.frame = CGRect(x: 0, y: 0, width: width, height: height)

let cornersRadius: CGFloat = 100
var path = UIBezierPath()

path.move(to: CGPoint(x: 0, y: 0))

path.addLine(to: CGPoint(x: width, y: 0))
path.addLine(to: CGPoint(x: width, y: height))

path.addLine(to: CGPoint(x: 0, y: height))
path.addLine(to: CGPoint(x: 0, y: 0))

path = path.reversing()

let topLeft = UIBezierPath()
topLeft.move(to: CGPoint(x: 0, y: cornersRadius))

topLeft.addLine(to: CGPoint(x: 0, y: 0))
topLeft.addLine(to: CGPoint(x: cornersRadius, y: 0))

topLeft.addArc(withCenter: CGPoint(x: cornersRadius, y: cornersRadius), radius: cornersRadius, startAngle: getRadians(from: 270), endAngle: getRadians(from: 180), clockwise: false)
topLeft

let topRight = UIBezierPath()
topRight.move(to: CGPoint(x: width, y: cornersRadius))

topRight.addLine(to: CGPoint(x: width, y: 0))
topRight.addLine(to: CGPoint(x: width - cornersRadius, y: 0))

topRight.addArc(withCenter: CGPoint(x: width - cornersRadius, y: cornersRadius), radius: cornersRadius, startAngle: getRadians(from: 270), endAngle: getRadians(from: 0), clockwise: true)
topRight

path.append(topLeft)
path.append(topRight)

let layer = CAShapeLayer()
layer.path = path.cgPath

view.layer.mask = layer
view

【问题讨论】:

  • bug 在这里:topRight.addLine(to: CGPoint(x: width, y: 0)) topRight.addLine(to: CGPoint(x: width - cornersRadius, y: 0))
  • 我应该如何改变它?
  • 使用单个 UIBezierPath 比尝试将路径添加在一起要容易得多。你在正确的道路上做错了什么是你实际上是在“填充”角落而不是移除它。

标签: ios swift uibezierpath cashapelayer


【解决方案1】:

有一个更简单的方法来实现它。您可以使用以下方法:

init(roundedRect:byRoundingCorners:cornerRadii:)UIBezierPath

更多信息请关注Apple documentation

这里的用法示例:

let cornerRadius = CGFloat(10.0)
let roundedCorners = roundedCorners.union([.topLeft, .topRight])

let path = UIBezierPath(roundedRect:maskRect, byRoundingCorners:roundedCorners, cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))

let maskLayer = CAShapeLayer()
maskLayer.frame = YOUR_VIEW_TO_MASK.bounds
maskLayer.path = maskPath.cgPath

YOUR_VIEW_TO_MASK.layer.mask = maskLayer

【讨论】:

  • 不幸的是,我的任务是让上面的代码生效。我知道我可以用更简单的方法得到圆角,但这不是我需要的。
  • “有效性”是什么意思?代码性能?您提供的代码在分析过程中是否出现瓶颈?
  • 抱歉我的英语不好。正如我在问题文本中所写,我未能使用我的代码将两个角都圆化。不知什么原因,只有左边是四舍五入的。我需要在不改变舍入方式的情况下解决这个问题。
【解决方案2】:

使用单个 UIBezierPath:

let largeRadius: CGFloat = 100.0
let smallRadius: CGFloat = 12.0

let path = UIBezierPath()

// Bottom left
path.move(to: CGPoint(x: 0, y: height - smallRadius)
path.addLine(to: CGPoint(x: 0, y: largeRadius)

// Top left
path.addArc(withCenter: CGPoint(x: largeRadius, y: largeRadius), radius: largeRadius, startAngle: getRadians(from: 270), endAngle: getRadians(from: 0, clockwise: true))

// Top right
path.addLine(to: CGPoint(x: width - largeRadius, y: 0)
path.addArc(withCenter: CGPoint(x: width - largeRadius, y: largeRadius), radius: largeRadius, startAngle: getRadians(from: 0), endAngle: getRadians(from: 90))

// EITHER (rounded bottom corners):
// Bottom right 
path.addLine(to: CGPoint(x: width, y: height - smallRadius)
path.addArc(withCenter: CGPoint(x: width - smallRadius, y: height - smallRadius), radius: smallRadius, startAngle: getRadians(from: 90), endAngle: getRadians(from: 180))

// Bottom left
path.addLine(to: CGPoint(x: smallRadius, y: height - smallRadius))
path.addArc(withCenter: CGPoint(x: smallRadius, y: height - smallRadius), radius: smallRadius, startAngle: getRadians(from: 180), endAngle: getRadians(from: 270))

// OR (square bottom corners):
// Bottom right
path.addLine(to: CGPoint(x: width, y: height))

// Bottom left
path.addLine(to: CGPoint(x: 0, y: height))
path.close()
let layer = CAShapeLayer()
layer.path = path.cgPath

请注意,此代码提供了一种在底部添加较小圆角而不是使用单独的图层蒙版的方法,以及使用方形底角。

我也在对您的 getRadians() 函数做出假设。

【讨论】:

  • 不幸的是,通过从一个大的矩形蒙版中切出圆角来精确地获得圆角对我来说很重要,因为之后蒙版和它的角将分别进行动画处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-24
  • 1970-01-01
  • 2014-08-10
  • 2015-09-05
相关资源
最近更新 更多