swift iOS drawLinearGradient diagonal在视图长度大于宽度时无法正常工作

v09wglhw  于 2024-01-05  发布在  Swift
关注(0)|答案(2)|浏览(136)

我可以用这个简单的例子来说明这个问题。
我有一个需要对角线渐变的视图,它应该从左上角的一种颜色开始,在右下角变成另一种颜色。下面的代码显示了我的尝试:

import UIKit

class GradientView: UIView {

    override func draw(_ rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()!
        context.saveGState()
        context.clip(to: rect)
        
        let topColor = UIColor.red
        let bottomColor = UIColor.green
        
        var tr = CGFloat(0), tg = CGFloat(0), tb = CGFloat(0), ta = CGFloat(0), br = CGFloat(0), bg = CGFloat(0), bb = CGFloat(0), ba = CGFloat(0)//top and bottom component variables
        topColor.getRed(&tr, green: &tg, blue: &tb, alpha: &ta)
        bottomColor.getRed(&br, green: &bg, blue: &bb, alpha: &ba)
        
        let gradient = CGGradient(colorSpace: CGColorSpaceCreateDeviceRGB(), colorComponents: [tr,tg,tb,ta,br,bg,bb,ba], locations: [0.0, 1.0], count: 2)

        context.drawLinearGradient(gradient!, start: CGPoint(x: 0, y: 0), end: CGPoint(x: rect.size.width, y: rect.size.height), options: CGGradientDrawingOptions.drawsAfterEndLocation)

        context.restoreGState()
    }

}

字符串
它的外观如下:


的数据
正如你所看到的,在底部的正方形中,当高度和宽度相同时,它可以正常工作。然而,在顶部的矩形中,当宽度大于高度时,它就不能正常工作了,因为右上角没有任何红色,左下角没有任何绿色。
我该如何解决此问题?

qlzsbp2j

qlzsbp2j1#

为了得到所需的结果,您需要计算连接垂直于矩形对角线的直线的起点和终点。请参见下图:


的数据
以下代码更新计算 dxdy 的值,可用于获取渐变的起点和终点。

class GradientView: UIView {
    override func draw(_ rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()!

        let topColor = UIColor.red
        let bottomColor = UIColor.green

        let ang = atan(bounds.height / bounds.width)
        let len = cos(ang) * bounds.height
        let dx = sin(ang) * len
        let dy = cos(ang) * len

        // Create the gradient using the two colors
        let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: [topColor.cgColor, bottomColor.cgColor] as CFArray, locations: nil)!

        // Draw the gradient basing the start and end points off of the
        // center of the rectangle.
        let start = CGPoint(x: bounds.midX - dx, y: bounds.midY - dy)
        let end = CGPoint(x: bounds.midX + dx, y: bounds.midY + dy)
        context.drawLinearGradient(gradient, start: start, end: end, options: [ .drawsBeforeStartLocation, .drawsAfterEndLocation ])
    }
}

字符串
下面的示例视图(宽、高和正方形)演示了所有三种情况下所需的输出:

let wgv = GradientView(frame: CGRect(x: 0, y: 0, width: 400, height: 100))
let tgv = GradientView(frame: CGRect(x: 0, y: 0, width: 100, height: 400))
let sgv = GradientView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))


结果如下:
wgv:



tgv:



sgv:

rkkpypqq

rkkpypqq2#

假设图层是蒙版边界,你可以使用宽度和高度之间的最大值作为创建渐变时的参考值。
这意味着,始终创建一个方形渐变,其大小是这些值之间的最大值。
这将使渐变始终以45度渲染,而不是你所经历的。问题不在于渐变没有正确绘制,而是因为大小不同,坡度不同。

相关问题