Swift CoreGraphics Gradient减慢应用程序

时间:2017-09-01 19:02:44

标签: ios swift graphics core-graphics gradient

我对Swift的CoreGraphics很新,所以我可能会在这里做很多错事,但我找不到像我这样的问题,所以我决定发布自己的问题。

我正在使用CoreGraphics在屏幕上的特定位置绘制圆圈。当我只使用cgContext.addEllipse(in: rect)时,我可以渲染一百个圆圈没问题。但是,我在网上找到了一个快速径向渐变代码块,可以为其他2D圆圈添加3D效果。以下代码是我自己修改的代码块,适用于我的应用程序:

func drawSphere(in rect: CGRect, withColor color: CGColor, withContext ctx: CGContext) {
    let locations: [CGFloat] = [0.0, 1.0]

    let colors = [UIColor.white.cgColor, color]

    let colorspace = CGColorSpaceCreateDeviceRGB()

    let gradient = CGGradient(colorsSpace: colorspace,
                              colors: colors as CFArray, locations: locations)

    var startPoint = CGPoint()
    var endPoint = CGPoint()
    startPoint.x = rect.minX
    startPoint.y = rect.minY
    endPoint.x = rect.minX + rect.width / 4
    endPoint.y = rect.minY + rect.height / 4
    let startRadius: CGFloat = 0
    let endRadius: CGFloat = rect.width / 2.0

    ctx.drawRadialGradient (gradient!, startCenter: startPoint,
                                 startRadius: startRadius, endCenter: endPoint, 
                                 endRadius: endRadius,
                                 options: .drawsBeforeStartLocation)
}

这在视觉上很有效。但是,我的设备慢慢爬行,甚至难以用这种方法渲染单个球体。当我在屏幕上拖动时,球体应该与我的拖动一起移动,但是当我使用上面的渲染代码时,我看到帧的下降非常明显。

以下是调用上述函数的上下文:

func drawPlanet(_ planet: Planet, withContext ctx: CGContext) {

    let distance = MathHelper.hypot3(x: planet.x, y: planet.y, z: flatDistance + planet.z)

    let angularDiameter = MathHelper.angularDiameter(diameter: planet.diameter, distance: distance)
    let angularX = MathHelper.angularDiameter(diameter: planet.x, distance: distance)
    let angularY = MathHelper.angularDiameter(diameter: planet.y, distance: distance)
    let fieldOfView = MathHelper.toRadians(fov)

    let pitchRad = MathHelper.toRadians(pitch)
    let yawRad = MathHelper.toRadians(yaw)
    let pitchedY = distance * tan(pitchRad)
    let yawedX = distance * tan(yawRad)

    let adjustedDiameter = Double(frame.width) * angularDiameter / fieldOfView
    let adjustedX = Double(frame.width) * angularX / fieldOfView
    let adjustedY = Double(frame.width) * angularY / fieldOfView

    let middleX = Double(frame.width) / 2.0 + yawedX
    let middleY = Double(frame.height) / 2.0 + pitchedY

    let rect = CGRect(x: middleX - adjustedX - adjustedDiameter / 2, y: middleY - adjustedY - adjustedDiameter / 2, width: adjustedDiameter, height: adjustedDiameter)

    if (rect.minX < frame.maxX || rect.maxX > frame.minX) && (rect.minY < frame.maxY || rect.maxY > frame.minY) {
        ctx.beginPath()

        ctx.setLineWidth(1)
        ctx.setStrokeColor(planet.color.cgColor)
        ctx.setFillColor(planet.color.cgColor)

        drawSphere(in: rect, withColor: planet.color.cgColor, withContext: ctx)

        if planet.selected {
            ctx.beginPath()

            ctx.setLineWidth(2)
            ctx.setStrokeColor(UIColor.white.cgColor)

            ctx.addRect(rect)
            ctx.drawPath(using: .stroke)
        }

        //ctx.closePath()
    }
}

以下是调用 函数的上下文:

override func draw(_ rect: CGRect) {
    guard let ctx = UIGraphicsGetCurrentContext() else { return }

    ctx.setFillColor(UIColor.black.cgColor)
    ctx.fill(rect)

    for planet in currentGalaxy.planets {
        drawPlanet(planet, withContext: ctx)
    }
}

我不是在不断重新绘制屏幕。我只会在设备更改其方向或触发view.setNeedsDisplay()时调用UIGestureRecognizer

我想我的代码在某处有一些明显的低效率,但我不知道效率低下的地方。任何帮助将不胜感激。谢谢!

0 个答案:

没有答案