iOS中SKShapeNode应用CIGaussianFilter后模糊偏移问题
解决SKShapeNode高斯模糊后偏移的问题
导致模糊后图像偏移的核心原因有两点:
- 将
barra从原场景移到SKEffectNode时,未处理父子节点间的坐标转换,导致位置错乱。 CIGaussianBlur滤镜会向外扩展图像边缘(扩展尺寸等于模糊半径),未做补偿的话会让视觉上出现偏移。
方案一:坐标转换+偏移补偿
调整SKEffectNode和barra的位置,同时补偿模糊带来的边缘扩展偏移:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let blurRadius: CGFloat = 20.0 let blur = CIFilter(name:"CIGaussianBlur", parameters: ["inputRadius": blurRadius]) effectsNode = SKEffectNode() effectsNode.filter = blur effectsNode.blendMode = .alpha effectsNode.shouldCenterFilter = true effectsNode.shouldEnableEffects = true effectsNode.shouldRasterize = false // 将SKEffectNode的锚点设为与barra一致,避免坐标偏移 effectsNode.anchorPoint = CGPoint(x: 0.5, y: 0.5) // 记录barra原来在场景中的位置 let originalPosition = barra.position // 将barra在effectsNode中的位置设为原点,确保在effectsNode内居中 barra.position = .zero // 设置effectsNode的位置为barra原来的位置 effectsNode.position = originalPosition // 补偿模糊扩展的偏移:模糊后图像向四周扩展了blurRadius,所以将effectsNode往右下移动对应距离 effectsNode.position.x += blurRadius effectsNode.position.y += blurRadius effectsNode.addChild(barra) addChild(effectsNode) }
方案二:添加裁剪滤镜限制尺寸
在高斯模糊后添加CICrop滤镜,将图像裁剪回原节点尺寸,从根源避免偏移:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let blurRadius: CGFloat = 20.0 // 创建高斯模糊滤镜 let blurFilter = CIFilter(name:"CIGaussianBlur", parameters: ["inputRadius": blurRadius]) // 创建裁剪滤镜,将模糊后的图像裁剪回barra的原始尺寸 let cropFilter = CIFilter(name: "CICrop")! cropFilter.setValue(blurFilter?.outputImage, forKey: kCIInputImageKey) // 用barra的frame作为裁剪区域 cropFilter.setValue(CIVector(cgRect: barra.frame), forKey: kCIInputRectangleKey) effectsNode = SKEffectNode() effectsNode.filter = cropFilter effectsNode.blendMode = .alpha effectsNode.shouldCenterFilter = true effectsNode.shouldEnableEffects = true effectsNode.shouldRasterize = false // 处理坐标转换:保持位置一致 effectsNode.anchorPoint = barra.anchorPoint effectsNode.position = barra.position barra.position = .zero effectsNode.addChild(barra) addChild(effectsNode) }
额外注意事项
- 上述代码会自动将
barra从原父节点移到SKEffectNode中;若需保留原节点,需先复制barra再添加到effectsNode。 - 当模糊半径较大时,方案二的裁剪效果更稳定,不会出现视觉上的边缘拉伸问题。
内容的提问来源于stack exchange,提问作者Laurent Crivello
相关产品推荐
相关产品推荐

