用对角线绘制线条填充UIView?

时间:2016-03-02 14:51:15

标签: ios uiview core-graphics

如何像这样填充UIView(用一些对角线绘制的白线)。

enter image description here

PS:我的意图是填补而不是边界。

任何帮助?

4 个答案:

答案 0 :(得分:15)

非常简单的算法......

说你有这些价值......

    let T: CGFloat = 15     // desired thickness of lines
    let G: CGFloat = 30     // desired gap between lines
    let W = rect.size.width
    let H = rect.size.height

令人惊讶的是,就是这么简单......

    var p = -(W > H ? W : H) - T
    while p <= W {

        c.move( to: CGPoint(x: p-T, y: -T) )
        c.addLine( to: CGPoint(x: p+T+H, y: T+H) )
        c.strokePath()
        p += G + T + T
    }

enter image description here

这是一个完整的UIView类:

class Ruled: UIView {

    override func draw(_ rect: CGRect) {

        let T: CGFloat = 15     // desired thickness of lines
        let G: CGFloat = 30     // desired gap between lines
        let W = rect.size.width
        let H = rect.size.height

        guard let c = UIGraphicsGetCurrentContext() else { return }
        c.setStrokeColor(UIColor.orange.cgColor)
        c.setLineWidth(T)

        var p = -(W > H ? W : H) - T
        while p <= W {

            c.move( to: CGPoint(x: p-T, y: -T) )
            c.addLine( to: CGPoint(x: p+T+H, y: T+H) )
            c.strokePath()
            p += G + T + T
        }
    }
}

就是这样!

整个基本算法:

1。从左上角开始,减去最长边

2。绘制对角线,直到你走到右边

美好而轻松! :)

要剪切为矩形:

上面的类只是将它描绘成“UIView的大小”。通常,您希望在视图中,在不同坐标处绘制一些“框”。 (一个很好的例子是日历)。

enter image description here

此外,此示例显式绘制“两个条纹”,而不是在背景颜色上绘制一个条纹:

func simpleStripes(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) {

    let stripeWidth: CGFloat = 20.0 // whatever you want
    let m = stripeWidth / 2.0

    guard let c = UIGraphicsGetCurrentContext() else { return }
    c.setLineWidth(stripeWidth)

    let r = CGRect(x: x, y: y, width: width, height: height)
    let longerSide = width > height ? width : height

    c.saveGState()
    c.clip(to: r)

        var p = x - longerSide
        while p <= x + width {

            c.setStrokeColor(pale blue)
            c.move( to: CGPoint(x: p-m, y: y-m) )
            c.addLine( to: CGPoint(x: p+m+height, y: y+m+height) )
            c.strokePath()

            p += stripeWidth

            c.setStrokeColor(pale gray)
            c.move( to: CGPoint(x: p-m, y: y-m) )
            c.addLine( to: CGPoint(x: p+m+height, y: y+m+height) )
            c.strokePath()

            p += stripeWidth
        }

    c.restoreGState()
}

如果你想动画他们移动......

1,要偏移,只需在启动时从指针中减去。令人惊讶的是,没有其他事情需要改变。

  var p = x - longerSide - offset // animate offset from 0 to stripeWidth

2,细心的程序员更喜欢偏移等于斜接以避免“尖尖的左上角”问题:

  var p = x - longerSide - offset - m // for better-looking top-left corner

enter image description here

3,您可以使用各种颜色的任意数量的条纹,实际上您可以在任意组合中使用不同的条纹宽度。令人惊讶的是,该算法仍然有效且安全。 (如果您有多个宽度,只需将斜角m设置为最大宽度。)

答案 1 :(得分:13)

实现此目的的一种方法是覆盖draw(_:)的{​​{1}}方法并在那里进行自定义绘制。

绘制对角线非常简单,您只需要:

  • 从0到宽度+高度(沿着矩形的水平边缘,然后向上),通过间隙+线宽,从对角线(45º)长度转换为平行于绘制的矩形边缘。

  • 在每次迭代中,从该迭代的给定点绘制一条直线到相对边缘上的点(45°)。我们通过简单地处理矩形的垂直边缘,然后沿着水平方向来获得这一点

这样的事情应该达到预期的效果:

UIView

输出:

enter image description here

(假设视图有红色class StripeyView : UIView { let lineGap: CGFloat = 7 let lineWidth: CGFloat = 3 let lineColor = UIColor.white override func draw(_ rect: CGRect) { let ctx = UIGraphicsGetCurrentContext()! // flip y-axis of context, so (0,0) is the bottom left of the context ctx.scaleBy(x: 1, y: -1) ctx.translateBy(x: 0, y: -bounds.size.height) // generate a slightly larger rect than the view, // to allow the lines to appear seamless let renderRect = bounds.insetBy(dx: -lineWidth * 0.5, dy: -lineWidth * 0.5) // the total distance to travel when looping (each line starts at a point that // starts at (0,0) and ends up at (width, height)). let totalDistance = renderRect.size.width + renderRect.size.height // loop through distances in the range 0 ... totalDistance for distance in stride(from: 0, through: totalDistance, // divide by cos(45º) to convert from diagonal length by: (lineGap + lineWidth) / cos(.pi / 4)) { // the start of one of the stripes ctx.move(to: CGPoint( // x-coordinate based on whether the distance is less than the width of the // rect (it should be fixed if it is above, and moving if it is below) x: distance < renderRect.width ? renderRect.origin.x + distance : renderRect.origin.x + renderRect.width, // y-coordinate based on whether the distance is less than the width of the // rect (it should be moving if it is above, and fixed if below) y: distance < renderRect.width ? renderRect.origin.y : distance - (renderRect.width - renderRect.origin.x) )) // the end of one of the stripes ctx.addLine(to: CGPoint( // x-coordinate based on whether the distance is less than the height of // the rect (it should be moving if it is above, and fixed if it is below) x: distance < renderRect.height ? renderRect.origin.x : distance - (renderRect.height - renderRect.origin.y), // y-coordinate based on whether the distance is less than the height of // the rect (it should be fixed if it is above, and moving if it is below) y: distance < renderRect.height ? renderRect.origin.y + distance : renderRect.origin.y + renderRect.height )) } // stroke all of the lines added ctx.setStrokeColor(lineColor.cgColor) ctx.setLineWidth(lineWidth) ctx.strokePath() } }

您可以调整backgroundColorlineGap属性以生成不同的结果。

答案 2 :(得分:1)

最简单的绘制斜线的代码:

import UIKit

@IBDesignable
class SlashPatternView: UIView {
@IBInspectable
var lineWidth: CGFloat = 1 { didSet { setNeedsLayout() } }

@IBInspectable
var squareSize: CGFloat = 1 { didSet { setNeedsLayout() } }

@IBInspectable
var lineColor: UIColor = .white { didSet { setNeedsLayout() }}

var slashes: UIImage {
    let size = squareSize
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: size, height: size))
    return renderer.image { context in
        let cgcontext = context.cgContext

        cgcontext.addLines(between: [CGPoint(x: 0, y: size/2), CGPoint(x: size/2, y: 0)])
        cgcontext.addLines(between: [CGPoint(x: size/2, y: size), CGPoint(x: size, y: size/2)])

        cgcontext.setStrokeColor(lineColor.cgColor)
        cgcontext.setLineCap(.square)
        cgcontext.setLineWidth(lineWidth)
        cgcontext.strokePath()
    }
}
override func layoutSubviews() {
    super.layoutSubviews()
}


override func draw(_ rect: CGRect) {
    backgroundColor?.setFill()
    UIRectFill(rect)
    slashes.drawAsPattern(in: rect)
}
}

答案 3 :(得分:-3)

对我来说最简单的方法是在UIView(like this)中放置背景图像。第二种解决方案是使用Core Graphics Framework绘制线条(更高效,但需要编写更多代码)。

希望这有帮助!