Код:
enum GradientDirection {
case up
case left
case upLeft
case upRight
}
extension SKTexture {
convenience init(size: CGSize, color1: CIColor, color2: CIColor, direction: GradientDirection = .up) {
let coreImageContext = CIContext(options: nil)
let gradientFilter = CIFilter(name: "CILinearGradient")
gradientFilter!.setDefaults()
var startVector:CIVector
var endVector:CIVector
switch direction {
case .up:
startVector = CIVector(x: size.width/2, y: 0)
endVector = CIVector(x: size.width/2, y: size.height)
case .left:
startVector = CIVector(x: size.width, y: size.height/2)
endVector = CIVector(x: 0, y: size.height/2)
case .upLeft:
startVector = CIVector(x: size.width, y: 0)
endVector = CIVector(x: 0, y: size.height)
case .upRight:
startVector = CIVector(x: 0, y: 0)
endVector = CIVector(x: size.width, y: size.height)
}
gradientFilter!.setValue(startVector, forKey: "inputPoint0")
gradientFilter!.setValue(endVector, forKey: "inputPoint1")
gradientFilter!.setValue(color1, forKey: "inputColor0")
gradientFilter!.setValue(color2, forKey: "inputColor1")
let imgRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
let cgimg = coreImageContext.createCGImage(gradientFilter!.outputImage!, from: imgRect)!
print("cgimg: ", cgimg) // *** Observer this output ***** 103.0 width and height
self.init(cgImage: cgimg)
}
}
Инициализатор вызова:
// e.g. CGSize(width: 102.69999694824219, height: 102.69999694824219)
let textureSize = CGSize(width: self.frame.width, height: self.frame.height)
let shapeTexture = SKTexture(size: textureSize, color1: bottomColor, color2: topColor, direction: .upRight)
Передача width/height: 102.69999694824219
, выдача shapeTexture
с width/height: 103
. Похоже, что coreImageContext.createCGImage
округляет 102.69999694824219
до 103.0
.
Это приводит к незначительным неожиданным выводам. Как я могу обойти это округление? Или есть какой-то другой способ создания градиентного изображения для узлов?
Подробнее Код:
class BubbleNode: SKShapeNode {
private var backgroundNode: SKCropNode!
var label: SKLabelNode!
private var state: BubbleNodeState!
private let BubbleAnimationDuration = 0.2
private let BubbleIconPercentualInset = 0.4
var model: BubbleModel! {
didSet {
self.label.text = model.name
}
}
override init() {
super.init()
}
convenience init(withRadius radius: CGFloat) {
self.init()
self.init(circleOfRadius: radius)
state = .normal
self.configure()
}
private func configure() {
self.name = "mybubble"
physicsBody = SKPhysicsBody(circleOfRadius: 4 + self.path!.boundingBox.size.width / 2.0)
physicsBody!.isDynamic = true
physicsBody!.affectedByGravity = false
physicsBody!.allowsRotation = false
physicsBody!.mass = 0.3
physicsBody!.friction = 0.0
physicsBody!.linearDamping = 3
backgroundNode = SKCropNode()
backgroundNode.isUserInteractionEnabled = false
backgroundNode.position = CGPoint.zero
backgroundNode.zPosition = 0
self.addChild(backgroundNode)
label = SKLabelNode(fontNamed: "")
label.preferredMaxLayoutWidth = self.frame.size.width - 16
label.numberOfLines = 0
label.position = CGPoint.zero
label.fontColor = .white
label.fontSize = 10
label.isUserInteractionEnabled = false
label.verticalAlignmentMode = .center
label.horizontalAlignmentMode = .center
label.zPosition = 2
self.addChild(label)
}
func addGradientNode(withRadius radius: CGFloat) {
let gradientNode = SKShapeNode(path: self.path!)
gradientNode.zPosition = 1
gradientNode.fillColor = .white
gradientNode.strokeColor = .clear
let bottomColor = CIColor(red: 0.922, green: 0.256, blue: 0.523, alpha: 1)
let topColor = CIColor(red: 0.961, green: 0.364, blue: 0.155, alpha: 1)
let textureSize = CGSize(width: self.frame.width, height: self.frame.height)
let shapeTexture = SKTexture(size: textureSize, color1: bottomColor, color2: topColor, direction: .upRight)
gradientNode.fillTexture = shapeTexture
self.addChild(gradientNode)
print("path: ", self.path!)
print("textureSize: ", textureSize)
print("shapeTexture: ", shapeTexture)
}
}