如何在 SwiftUI 中渲染场强

问题描述 投票:0回答:1

我的应用程序需要渲染场强,即矩形视图中函数 f(x,y) 的值。
我知道我可以渲染线性或径向渐变,请参见here,但我没有找到一种方法来根据函数 f(x,y) 设置视图像素的亮度或不透明度。
我可能可以组装很多子视图的视图,其中每个子视图的亮度或不透明度是根据这样的函数设置的,但这很丑陋,应该有更好的方法。
有什么建议吗?

swiftui gradient opacity
1个回答
0
投票

这是我的解决方案,基于上面lorem ipsum的建议。
此建议需要计算

Image
并将其覆盖在
View
上。

因此,我将以下扩展写入

Image

extension Image {
    
    /// Creates an Image of a given size with a given color. 
    /// The color, without the alpha value, is here hard coded, but could of course be given by a parameter.
    /// The alpha value represents the field function, depending on the (x,y) pixel value.
    /// - Parameters:
    ///   - size: The size of the resulting image
    ///   - alpha: The field function
    init?(size: CGSize, alpha: (_ x: Int, _ y: Int) -> Double) {
        // Set color components as 8 bits in hex. Alpha will be taken from the function parameter.
        // Pixel values are 32 bits: ARGB
        let r: UInt32 = 0x00 << 16
        let g: UInt32 = 0x00 << 8
        let b: UInt32 = 0xFF 
        
        let pixelWidth  = Int(size.width)
        let pixelHeight = Int(size.height)
        var srgbArray: [UInt32] = [] // The pixel array

        // Compute field values
        for y in 0 ..< pixelHeight {
            for x in 0 ..< pixelWidth {
                let fieldStrength = alpha(x, y)
                if fieldStrength < 0 || fieldStrength > 1.0 {
                    return nil // The alpha function did return an illegal value (< 0 or > 1).
                }
                let a = UInt32(fieldStrength * 255.0) << 24 // alpha
                srgbArray.append(a | r | g | b)
            }
        }
        
        // https://forums.swift.org/t/creating-a-cgimage-from-color-array/18634
        let cgImg = srgbArray.withUnsafeMutableBytes { ptr -> CGImage in
            let ctx = CGContext(
                data: ptr.baseAddress,
                width: pixelWidth,
                height: pixelHeight,
                bitsPerComponent: 8,
                bytesPerRow: 4 * pixelWidth,
                space: CGColorSpace(name: CGColorSpace.sRGB)!,
                bitmapInfo: CGBitmapInfo.byteOrder32Little.rawValue + CGImageAlphaInfo.premultipliedFirst.rawValue
            )!
            return ctx.makeImage()!
        }
        
        self.init(
            cgImg,
            scale: 1.0,
            orientation: .up,
            label: Text("Field")
        )
    }
}

Image
初始化为

let image = Image(size: fieldSize, alpha: alpha(x:y:))  

其中函数

alpha
可以是任何函数。在这里,出于演示目的,我使用以下函数:

func alpha(x: Int, y: Int) -> Double {
    Field.borderfield(size: fieldSize, x: x, y: y)
}

struct Field {
    
    static func borderfield(size: CGSize, x: Int, y: Int) -> Double {
        let a = Int(size.width)
        let b = Int(size.height)
        assert(x >= 0 && x <= a)
        assert(y >= 0 && y <= b)
        
        // Compute distance to border
        let dt = b - y  // Distance to top
        let db = y      // Distance to bottom
        let dl = x      // Distance to left
        let dr = a - x  // Distance to right
        let minDistance = min(dt, db, dl, dr)
        
        let d = Double(minDistance)
        let r = d + 1.0 // min r is now 1
        let signalStrength = 1.0/sqrt(r)
        print(signalStrength)
        return signalStrength
    }
    
}  

函数

borderfield
是对显示矩形的带电边框产生的场的非常粗略的近似。
这是图片:

© www.soinside.com 2019 - 2024. All rights reserved.