使用UIBezierPath的平行四边形视图

时间:2019-02-02 19:06:10

标签: ios swift uiview swift4 uibezierpath

我想用创建自定义的平行四边形视图UIBezierPath,但没有得到一个完美的。

以下是我的自定义视图代码

class CustomView: UIView {
    override func draw(_ rect: CGRect) {
        let offset  = 60.0;
        let path = UIBezierPath()

           path.move(to: CGPoint(x: self.frame.origin.x + CGFloat(offset), y: self.frame.origin.y))
           path.addLine(to: CGPoint(x: self.frame.width + self.frame.origin.x  , y: self.frame.origin.y))
           path.addLine(to: CGPoint(x: self.frame.origin.x + self.frame.width - CGFloat(offset) , y: self.frame.origin.y + self.frame.height))
           path.addLine(to: CGPoint(x: self.frame.origin.x, y: self.frame.origin.y + self.frame.height))


        // Close the path. This will create the last line automatically.
         path.close()
        UIColor.red.setFill()
        path.fill()

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path.cgPath
        self.layer.mask = shapeLayer;

    }
}

然后我使用创建视图

let customView = CustomView()
customView.frame = CGRect(origin: CGPoint(x: 10, y: 20), size: CGSize(width: 250, height: 250))
self.view.addSubview(customView)

但我得到这样的视图,它不是一个完美的平行四边形。

enter image description here

2 个答案:

答案 0 :(得分:3)

问题是使用framedraw(_:)。的问题是,{{} 1}是“的大小和视图的的位置在它的父坐标系统”(强调)。在此视图中如何渲染此形状通常与该视图在其超级视图中的位置无关。而如果这一观点不会发生是在0,0它的父,你可以体验种植。

但不要用rect参数,无论是。 “第一次绘制视图时,此矩形通常是视图的整个可见范围。但是,在随后的绘制操作中,矩形可能仅指定视图的一部分。”如果操作系统决定只需要更新frame的一部分,则可能会发生形状的根本改变。

改为使用bounds,它位于视图自己的坐标系中。并且,使用CustomViewminXminY,和maxX简化了代码比特。

maxY

enter image description here

顺便说一句,我没有设置面具。如果您正在制作动画,则每次调用@IBDesignable class CustomView: UIView { @IBInspectable var offset: CGFloat = 60 { didSet { setNeedsDisplay() } } @IBInspectable var fillColor: UIColor = .red { didSet { setNeedsDisplay() } } override func draw(_ rect: CGRect) { let path = UIBezierPath() path.move(to: CGPoint(x: bounds.minX + offset, y: bounds.minY)) path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY)) path.addLine(to: CGPoint(x: bounds.maxX - offset, y: bounds.maxY)) path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY)) // Close the path. This will create the last line automatically. path.close() fillColor.setFill() path.fill() } } 时不断重置遮罩似乎无效。我个人只是设置视图的背景色为draw。但这与眼前的问题无关。

答案 1 :(得分:2)

正如@Losiowaty所建议的,数学运算已关闭,因为右上角超出了框架的边界。 (不知道为什么clipToBounds =虚假不工作;但是这只是一个调试建议 - 不是一个解决方案)。试试这个:

class CustomView: UIView {
    override func draw(_ rect: CGRect) {
        let offset: CGFloat = 60.0;

        let path = UIBezierPath()

        let width = self.bounds.width - offset

        let upperLeftPoint = CGPoint(x: self.bounds.origin.x + offset, y: self.bounds.origin.y)
        let upperRightPoint = CGPoint(x: self.bounds.origin.x + width, y: self.bounds.origin.y)

        let lowerRightPoint = CGPoint(x: width - offset, y: self.bounds.size.height)
        let lowerLeftPoint = CGPoint(x: self.bounds.origin.x, y: self.bounds.size.height)

        path.move(to: upperLeftPoint)
        path.addLine(to: upperRightPoint)
        path.addLine(to: lowerRightPoint)
        path.addLine(to: lowerLeftPoint)
        path.addLine(to: upperLeftPoint)

        // Close the path. This will create the last line automatically.
        path.close()
        UIColor.red.setFill()
        path.fill()

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path.cgPath
        self.layer.mask = shapeLayer;
    }
}