使用UIBezierPath平行四边形视图

问题描述 投票:2回答:2

我想创建自定义的平行四边形视图中使用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

ios swift uiview swift4 uibezierpath
2个回答
3
投票

问题是frame内使用draw(_:)的。问题是,frame是“规模和它的父坐标系统视图的位置”(强调)。你怎么这个视图中呈现此形状大体无关与在此视图位于它的父。如果这种观点并不正好是0,它的父为0,你可以体验种植。

但不要用rect参数,无论是。 “你的图绘第一次,这个矩形通常是您的视图的整个可视范围。然而,在随后的绘图操作,矩形可以指定你的观点的一部分。”你有危险,如果操作系统决定只需要更新您的CustomView的一部分形状从根本上改变。

使用bounds,相反,这是鉴于自己的坐标系统相同。而且,使用minXminYmaxXmaxY简化了代码一点。

@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()
    }

}

enter image description here

顺便说一句,我不设置屏蔽。如果你的动画,它似乎可能是低效的不断重置面具每次draw被调用。我个人正好被设置为.clear视图的背景颜色。但是,这不相关的直接的问题。


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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.