CAEmitterCell
CAGradientLayer
CAGradientLayer
继承自 CALayer
,它主要功能是能实现渐变的颜色。
let gradientLayer = CAGradientLayer();
gradientLayer.frame = view.bounds;
view.layer.addSublayer(gradientLayer)
gradientLayer.colors = [UIColor.cyan.cgColor, UIColor.orange.cgColor];
// 渐变颜色的区间分布,locations的数组长度和color一致,一般不用设置,默认是nil,会平均分布。
//gradientLayer.locations = [0.1, 0.2]
//映射locations中第一个位置,用单位向量表示,比如(0,0)表示从左上角开始变化。默认值是(0.5,0.0)。
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
//表示到右下角变化结束。默认值是(0.5,1.0)。
gradientLayer.endPoint = CGPoint(x: 1, y: 1)
CAGradientLayer
为粒子发射图层。该图层主要用于控制粒子展现范围、粒子发射位置、粒子发射形状、渲染模式等属性。
CAEmitterLayer
CAEmitterCell
粒子发射单元,用于对粒子系统中的单个粒子做更加精细的控制。比如控制粒子的移动速度、方向、范围。
粒子火焰效果
let emitterCell = CAEmitterCell()
emitterCell.name = "fire"// 粒子的名字
emitterCell.emissionLongitude = .pi
emitterCell.velocity = -1 // 粒子速度。负数表明向上燃烧,速度越大,火苗喷涌速度越快
emitterCell.velocityRange = 50 // 粒子速度范围
emitterCell.emissionRange = 1.1 // 周围发射角度
emitterCell.yAcceleration = -200 // 粒子 y 方向的加速度分量
emitterCell.scaleSpeed = 0.3 // 缩放比例 超大火苗
emitterCell.color = UIColor(red: 0.8, green: 0.4, blue: 0.2, alpha: 0.1).cgColor
//一般放一张图片,是我们粒子要展示的内容。图片要小,不然卡
emitterCell.contents = UIImage(named: "image")?.cgImage
// emitterCell.birthRate = 500 (火焰效果中每秒粒子的组成个数,个数越多,火焰越大越逼真。)
// 每个粒子存活时长
//emitterCell.lifetime = 5
let emitterLayer = CAEmitterLayer()
emitterLayer.position = view.center
//发射器的尺寸
emitterLayer.emitterSize = CGSize(width: 5, height: 5)
//渲染模式
emitterLayer.renderMode = .additive
//发射的模式
emitterLayer.emitterMode = .outline
//发射的形状,有6种值,分别是点、线、矩形、立方体、圆形、球形。
emitterLayer.emitterShape = .line
emitterLayer.emitterCells = [emitterCell]
view.layer.addSublayer(emitterLayer)
//粒子产生系数,默认为1,想关掉就设为0,这样就没有粒子产生了
emitterLayer.setValue(500, forKeyPath: "emitterCells.fire.birthRate")
emitterLayer.setValue(1, forKeyPath: "emitterCells.fire.lifetime")
霓虹效果
let emitterCell = CAEmitterCell()
emitterCell.emissionLongitude = .pi * 2
emitterCell.velocity = 50
emitterCell.velocityRange = 50
emitterCell.scaleSpeed = -0.2
emitterCell.scale = 0.1
emitterCell.greenSpeed = -0.1
emitterCell.redSpeed = -0.2
emitterCell.blueSpeed = 0.1
emitterCell.alphaSpeed = -0.2
//每秒粒子产生个数的乘数因子,会和layer的birthRate相乘, 然后确定每秒产生的粒子个数
emitterCell.birthRate = 100
emitterCell.lifetime = 4
emitterCell.color = UIColor.white.cgColor
emitterCell.contents = UIImage(named: "image")?.cgImage
let emitterLayer = CAEmitterLayer()
emitterLayer.position = view.center
emitterLayer.emitterSize = CGSize(width: 2, height: 2)
emitterLayer.renderMode = .backToFront
emitterLayer.emitterMode = .outline
emitterLayer.emitterShape = .circle
emitterLayer.emitterCells = [emitterCell]
view.layer.addSublayer(emitterLayer)
直播点赞粒子动画
let emitterLayer = CAEmitterLayer()
//发射器在xy平面的中心位置
emitterLayer.emitterPosition = CGPoint(x: UIScreen.main.bounds.width * 0.5, y: UIScreen.main.bounds.height - 200)
//发射器的尺寸大小
emitterLayer.emitterSize = CGSize(width: 30, height: 30)
//渲染模式
emitterLayer.renderMode = .unordered
//开启三维效果
emitterLayer.preservesDepth = true
var emitterCells = [CAEmitterCell]()
//创建粒子
for i in 1...9 {
//发射单元
let emitterCell = CAEmitterCell()
//粒子的创建速率
emitterCell.birthRate = 0.5
//粒子存活时间
emitterCell.lifetime = 10
//粒子的生存时间容差
emitterCell.lifetimeRange = 5
//颜色
//stepCell.color = UIColor(red: CGFloat(arc4random() % 256) / 255.0, green: CGFloat(arc4random() % 256) / 255.0, blue: CGFloat(arc4random() % 256) / 255.0, alpha: 1.0).cgColor
//粒子显示的内容
emitterCell.contents = UIImage(named: "image\(i)")?.cgImage
//粒子的名字
emitterCell.name = String(i)
//粒子的运动速度
emitterCell.velocity = 100
//粒子的速度容差
emitterCell.velocityRange = 50
//旋转速度
emitterCell.spin = CGFloat(Double.pi / 2)
//透明度每过一秒就是减少0.1
emitterCell.alphaSpeed = -0.1
emitterCell.alphaRange = -0.1
//粒子在xy平面的发射角度
emitterCell.emissionLongitude = CGFloat(.pi + Double.pi / 2)
//粒子发射角度容差
emitterCell.emissionRange = CGFloat(Double.pi / 4)
//缩放比例
emitterCell.scale = 0.7
emitterCell.scaleRange = 0.3
emitterCells.append(emitterCell)
}
emitterLayer.emitterCells = emitterCells
view.layer.addSublayer(emitterLayer)
CAGradientLayer
光波扫描动画
let gradientLayer = CAGradientLayer()
gradientLayer.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
//光波方向
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 0)
//设置光波颜色梯度
gradientLayer.locations = [0.0, 0.02, 0.02]
gradientLayer.colors = [UIColor.clear.cgColor, UIColor.black.cgColor, UIColor.clear.cgColor]
view.layer.addSublayer(gradientLayer)
let gradientAnimation = CABasicAnimation()
gradientAnimation.keyPath = "locations"
gradientAnimation.fromValue = [0.0, 0.02, 0.02]
gradientAnimation.toValue = [0.98, 0.98, 1.0]
gradientAnimation.duration = 3
gradientAnimation.repeatCount = 10
gradientLayer.add(gradientAnimation, forKey: nil)
实践:音响音量跳动动画
import UIKit
class ViewController: UIViewController {
var gradientLayers = [CAGradientLayer]()
var randomColors = [UIColor]()
override func viewDidLoad() {
super.viewDidLoad()
let audioBarNum: CGFloat = 15
let audioBarW: CGFloat = (UIScreen.main.bounds.size.width - 10 * (audioBarNum + 1)) / audioBarNum
for i in 0...15 {
randomColors.append(UIColor(red: CGFloat(arc4random() % 256) / 255.0, green: CGFloat(arc4random() % 256) / 255.0, blue: CGFloat(arc4random() % 256) / 255.0, alpha: 1.0))
let audioBar = UIView()
audioBar.frame = CGRect(x: 10 + CGFloat(i) * (audioBarW + 10), y: 300, width: audioBarW, height: 100)
audioBar.backgroundColor = randomColors[i]
view.addSubview(audioBar)
let gradientLayer = CAGradientLayer()
gradientLayer.frame = audioBar.bounds
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 0, y: 1)
audioBar.layer.addSublayer(gradientLayer)
gradientLayers.append(gradientLayer)
}
Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(colorChange), userInfo: nil, repeats: true)
}
@objc func colorChange() {
for layer in gradientLayers {
let index = Int(arc4random_uniform(11))
let color = randomColors[index]
layer.colors = [UIColor.clear.cgColor, color.cgColor]
layer.locations = [0, 1.0]
let gradientAnimation = CABasicAnimation()
gradientAnimation.keyPath = "locations"
let beginValue = Float(arc4random_uniform(11)) / 10
gradientAnimation.fromValue = [beginValue, beginValue]
gradientAnimation.toValue = [1.0, 1.0]
gradientAnimation.duration = 0.5
layer.add(gradientAnimation, forKey: nil)
}
}
}

CAShapeLayer
UIBezierPath
override func draw(_ rect: CGRect) {
//贝济埃曲线
let bezierPath = UIBezierPath()
//线条粗细
bezierPath.lineWidth = 5
//线条颜色
UIColor.cyan.setStroke()
//头尾形状
bezierPath.lineCapStyle = .square
//线条拐角
bezierPath.lineJoinStyle = .round
//绘制起始点
bezierPath.move(to: CGPoint(x: 50, y: 200))
bezierPath.addLine(to: CGPoint(x: 300, y: 300))
bezierPath.addArc(withCenter: CGPoint(x: 200, y: 150), radius: 50, startAngle: 0, endAngle: .pi * 4 / 3, clockwise: true)
//绘制闭合曲线
bezierPath.close()
//填充色
UIColor.orange.setFill()
//填充 填充色
bezierPath.fill()
bezierPath.stroke()
}
绘制动态图表
绘制折线动画
import UIKit
class FileView: UIView {
private var chartLine = CAShapeLayer()
private var pathAnimation = CABasicAnimation()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
clipsToBounds = true
chartLine.lineCap = .round
chartLine.lineJoin = .round
chartLine.fillColor = UIColor.white.cgColor
chartLine.lineWidth = 10
//属性为0,表明该动画效果开始绘制折线图时时一点点绘制,而非一次绘制完成
chartLine.strokeEnd = 0
layer.addSublayer(chartLine)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
let line = UIBezierPath()
line.lineWidth = 10
line.lineCapStyle = .square
line.lineJoinStyle = .round
line.move(to: CGPoint(x: 50, y: 80))
line.addLine(to: CGPoint(x: 150, y: 180))
line.addLine(to: CGPoint(x: 180, y: 90))
line.addLine(to: CGPoint(x: 300, y: 260))
chartLine.path = line.cgPath
chartLine.strokeColor = UIColor.cyan.cgColor
pathAnimation.keyPath = "strokeEnd"
pathAnimation.timingFunction = CAMediaTimingFunction(name: .linear)
pathAnimation.fromValue = 0
pathAnimation.toValue = 1
pathAnimation.autoreverses = false
pathAnimation.duration = 5
}
// 调用此方法开始划线动画
func drawChartLine() {
chartLine.strokeEnd = 1
chartLine.add(pathAnimation, forKey: nil)
}
}
绘制柱状图动画
import UIKit
class FileView: UIView {
private var chartLine = CAShapeLayer()
private var pathAnimation = CABasicAnimation()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
clipsToBounds = true
chartLine.lineCap = .round
chartLine.lineJoin = .round
chartLine.fillColor = UIColor.lightGray.cgColor
chartLine.lineWidth = 30
chartLine.strokeEnd = 0
layer.addSublayer(chartLine)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
let line = UIBezierPath()
line.lineWidth = 30
line.lineCapStyle = .square
line.lineJoinStyle = .round
for i in 0...5 {
let x = CGFloat(60 + 70 * i)
let y = CGFloat(100 + 20 * i)
line.move(to: CGPoint(x: x, y: 215))
line.addLine(to: CGPoint(x: x, y: y))
}
chartLine.path = line.cgPath
chartLine.strokeColor = UIColor.cyan.cgColor
pathAnimation.keyPath = "strokeEnd"
pathAnimation.timingFunction = CAMediaTimingFunction(name: .linear)
pathAnimation.fromValue = 0
pathAnimation.toValue = 1
pathAnimation.autoreverses = false
pathAnimation.duration = 5
}
// 调用此方法开始划线动画
func drawChartLine() {
chartLine.strokeEnd = 1
chartLine.add(pathAnimation, forKey: nil)
}
}
调用 drawChartLine
方法绘制折线图动画和绘制柱状图动画开始执行动画
import UIKit
class ViewController: UIViewController {
private lazy var fileView: FileView = {
let view = FileView(frame: self.view.bounds)
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(fileView)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
fileView.drawChartLine()
}
}
CAReplicatorLayer
主要用于图层的快速复制
旋转动画
import UIKit
class ViewController: UIViewController {
var replicatorLayer = CAReplicatorLayer()
private lazy var imageView: UIView = {
let view = UIView(frame: CGRect(x: (UIScreen.main.bounds.size.width - 50 ) / 2 + 150, y: (UIScreen.main.bounds.size.height - 50) / 2, width: 50, height: 50))
view.backgroundColor = .cyan
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(imageView)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let path = UIBezierPath()
path.addArc(withCenter: view.center, radius: 150, startAngle: 0, endAngle: .pi * 2, clockwise: true)
path.close()
let animation = CAKeyframeAnimation(keyPath: "position")
animation.path = path.cgPath
animation.duration = 10
animation.repeatCount = MAXFLOAT
//设置100个layer图层
replicatorLayer.instanceCount = 100
//动画每0.2s复制一个layer图层
replicatorLayer.instanceDelay = 0.2
view.layer.addSublayer(replicatorLayer)
imageView.layer.add(animation, forKey: nil)
}
}
音量跳动动画
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let replicatorLayer = CAReplicatorLayer()
replicatorLayer.frame = CGRect(x: 30, y: 50, width: 300, height: 200)
//复制10份图层
replicatorLayer.instanceCount = 10;
//设置复制图层之间的渐变效果。设置图层沿x方向,每隔20个点复制一份。
replicatorLayer.instanceTransform = CATransform3DMakeTranslation(20, 0, 0)
//图层复制间隔0.2s
replicatorLayer.instanceDelay = 0.2
//剪切掉图层超出生效范围之外的部分
replicatorLayer.masksToBounds = true
replicatorLayer.backgroundColor = UIColor.black.cgColor
let layer = CALayer()
layer.frame = CGRect(x: 14, y: 200, width: 10, height: 100)
layer.backgroundColor = UIColor.red.cgColor
replicatorLayer.addSublayer(layer)
view.layer.addSublayer(replicatorLayer)
let animation = CABasicAnimation(keyPath: "position.y")
animation.duration = 0.5
//音量高度在200-180的范围内波动
animation.fromValue = 200
animation.toValue = 180
animation.autoreverses = true
animation.repeatCount = MAXFLOAT
layer.add(animation, forKey: nil)
}
}

CATransform3D
CATransform3DMakeRotation
angle
:动画的旋转角度
x
、y
、 z
:分别代表动画旋转时的旋转轴心
UIView.animate(withDuration: 5) {
//修改锚点位置。锚点的默认值为 (0.5, 0.5),取值范围为 0~1 之间。
self.imageView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
self.imageView.layer.transform = CATransform3DMakeRotation(.pi / 3, 1, 1, 0)
}
CATransform3D
矩阵
struct CATransform3D
{
CGFloat m11(x缩放), m12(和m21一起决定z轴的旋转), m13(和m31一起决定y轴的旋转), m14;
CGFloat m21(和m12一起决定z轴的旋转), m22(y轴方向进行缩放), m23, m24;
CGFloat m31(和m13一起决定y轴的旋转), m32, m33(z轴方向进行缩放), m34(透视效果,m34 = -1 / D,D越小,透视效果越明显,必须在有旋转效果的前提下,才会看到透视效果。);
CGFloat m41(x轴方向进行平移), m42(y轴方向进行平移), m43(z轴方向进行平移), m44;
}
UIView.animate(withDuration: 5) {
var transform = CATransform3DIdentity
transform.m34 = -1 / 20
transform.m31 = 3
transform.m13 = 3
self.imageView.layer.transform = CATransform3DScale(transform, 1, 1, 1)
}
Cover Flow 效果代码实现
import UIKit
class ViewController: UIViewController {
private lazy var imageView: UIImageView = {
let image = UIImageView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
image.image = UIImage(named: "0")
image.layer.anchorPoint.y = 0
return image
}()
private lazy var imageView2: UIImageView = {
let image = UIImageView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
image.image = UIImage(named: "0")
image.layer.anchorPoint.y = 0
return image
}()
private lazy var imageView3: UIImageView = {
let image = UIImageView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
image.image = UIImage(named: "0")
image.layer.anchorPoint.y = 0
return image
}()
private lazy var imageViews = [imageView, imageView2, imageView3]
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(imageView)
view.addSubview(imageView2)
view.addSubview(imageView3)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for i in 0..<imageViews.count {
var imageTransform = CATransform3DIdentity
imageTransform.m34 = -0.005
imageTransform = CATransform3DTranslate(imageTransform, 0, 50, 0)
imageTransform = CATransform3DScale(imageTransform, 0.95, 0.6, 1)
if i == 0 {
imageTransform = CATransform3DRotate(imageTransform, .pi / 4 / 2, 0, 1, 0)
} else if i == 1 {
imageTransform = CATransform3DRotate(imageTransform, -.pi / 4 / 2, 0, 1, 0)
}
let animation = CABasicAnimation(keyPath: "transform")
animation.fromValue = NSValue(caTransform3D: imageViews[i].layer.transform)
animation.toValue = NSValue(caTransform3D: imageTransform)
animation.duration = 1
let position = CABasicAnimation(keyPath: "position")
if i == 0 {
position.toValue = NSValue(cgPoint: CGPoint(x: 100, y: 10))
} else if i == 1 {
position.toValue = NSValue(cgPoint: CGPoint(x: 300, y: 10))
} else {
position.toValue = NSValue(cgPoint: CGPoint(x: 200, y: 20))
}
let group = CAAnimationGroup()
group.duration = 1
group.repeatCount = 1
group.isRemovedOnCompletion = false
group.fillMode = .forwards
group.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
group.animations = [animation, position]
imageViews[i].layer.add(group, forKey: "\(i)")
}
}
}

CATransition
let transition = CATransition()
transition.duration = 2
//设置动画类型
transition.type = .moveIn
//设置当前动画转场方向
transition.subtype = .fromTop
view.layer.add(transition, forKey: nil)
CATransitionType
动画类型
-
fade
淡入淡出效果 -
push
推送效果 -
reveal
揭开效果 -
moveIn
移动效果
CATransitionSubtype
动画转场方向
fromRight
fromLeft
fromTop
fromBottom
视图过渡动画
视图控制器过渡动画实现
UIViewControllerAnimatedTransitioning
UINavigationControllerDelegate
TransitionAnimation.swift
import UIKit
class TransitionAnimation: NSObject, UIViewControllerAnimatedTransitioning {
// MARK: - UIViewControllerAnimatedTransitioning
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 2
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let fromVC = (transitionContext.viewController(forKey: .from))!
let toVC = transitionContext.viewController(forKey: .to)!
let fromVCRect = transitionContext.initialFrame(for: fromVC)
let toVCRect = CGRect(x: 0, y: fromVCRect.size.height * 2, width: fromVCRect.size.width, height: fromVCRect.size.height)
let fromView = fromVC.view!
let toView = toVC.view!
fromView.frame = fromVCRect
toView.frame = toVCRect
transitionContext.containerView.addSubview(fromView)
transitionContext.containerView.addSubview(toView)
UIView.animate(withDuration: 2, animations: {
toView.frame = fromVCRect
toView.alpha = 1
}) { (finish) in
transitionContext.completeTransition(true)
}
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: CGFloat(arc4random() % 256) / 255.0, green: CGFloat(arc4random() % 256) / 255.0, blue: CGFloat(arc4random() % 256) / 255.0, alpha: 1.0)
navigationController?.delegate = self
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.navigationController?.pushViewController(ViewController(), animated: true)
}
// MARK: - UINavigationControllerDelegate
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return TransitionAnimation()
}
}
侧滑栏动画实现
import UIKit
import Accelerate
class SliderViewController: UIViewController {
private lazy var blurView: UIView = {
let view = UIView(frame: self.view.bounds)
return view
}()
private lazy var contentView: UIView = {
let view = UIView(frame: CGRect(x: -UIScreen.main.bounds.size.width * 0.5, y: 0, width: UIScreen.main.bounds.size.width * 0.5, height: UIScreen.main.bounds.size.height))
view.backgroundColor = .cyan
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(blurView)
view.addSubview(contentView)
}
func show() {
var windowView = UIView()
windowView = UIApplication.shared.windows.first!.rootViewController?.view! as! UIView
blurView.layer.contents = blurImage(imageFromView(windowView)).cgImage
view.alpha = 1
UIView.animate(withDuration: 0.5, animations: {
self.contentView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width * 0.5, height: UIScreen.main.bounds.size.height)
self.contentView.alpha = 0.9
})
}
func dismiss() {
UIView.animate(withDuration: 0.5, animations: {
self.contentView.frame = CGRect(x: -UIScreen.main.bounds.size.width * 0.5, y: 0, width: UIScreen.main.bounds.size.width * 0.5, height: UIScreen.main.bounds.size.height)
self.contentView.alpha = 0.9
}) { (finish) in
self.view.alpha = 0
}
}
// 蒙版模糊效果
func blurImage(_ image: UIImage) -> UIImage {
//设置图片模糊效果半径
let blurRadix: UInt32 = 7
let img = image.cgImage!
let bitmapData = img.dataProvider?.data
//import Accelerate
var inputBuffer = vImage_Buffer()
//获取图片的data数据内容、width、height、每行字节数
inputBuffer.data = UnsafeMutableRawPointer(mutating: CFDataGetBytePtr(bitmapData))
inputBuffer.width = vImagePixelCount(bitPattern: (img.width))
inputBuffer.height = vImagePixelCount(bitPattern: (img.height))
inputBuffer.rowBytes = img.bytesPerRow
//构建一片空间大小和原始图片所占空间相同大小的数据空间
let pixelBuffer = malloc(img.bytesPerRow * img.height)
var outputBuffer = vImage_Buffer()
outputBuffer.data = pixelBuffer
outputBuffer.width = vImagePixelCount(bitPattern: (img.width))
outputBuffer.height = vImagePixelCount(bitPattern: (img.height))
outputBuffer.rowBytes = img.bytesPerRow
//生成模糊效果的图片
vImageBoxConvolve_ARGB8888(&inputBuffer, &outputBuffer, nil, 0, 0, blurRadix, blurRadix, nil, vImage_Flags(kvImageEdgeExtend))
//构建RGB模糊空间
let colorSpace = CGColorSpaceCreateDeviceRGB()
let w = outputBuffer.width
let h = outputBuffer.height
let ctx = CGContext(data: outputBuffer.data, width: Int(w), height: Int(h), bitsPerComponent: 8, bytesPerRow: outputBuffer.rowBytes, space: colorSpace, bitmapInfo: (image.cgImage?.bitmapInfo.rawValue)!)
let imageRef = ctx?.makeImage()
let newImage = UIImage(cgImage: imageRef!)
free(pixelBuffer)
return newImage
}
// UIView 生成 UIImage
func imageFromView(_ view: UIView) -> UIImage {
UIGraphicsBeginImageContext(view.frame.size)
let content = UIGraphicsGetCurrentContext()!
view.layer.render(in: content)
let newImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
}
网友评论