我对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
。
我想我的代码在某处有一些明显的低效率,但我不知道效率低下的地方。任何帮助将不胜感激。谢谢!