Swiftgram/submodules/Display/Source/WallpaperBackgroundNode.swift
2020-03-25 17:59:03 +04:00

92 lines
3.3 KiB
Swift

import Foundation
import UIKit
import AsyncDisplayKit
private let motionAmount: CGFloat = 32.0
public final class WallpaperBackgroundNode: ASDisplayNode {
let contentNode: ASDisplayNode
public var motionEnabled: Bool = false {
didSet {
if oldValue != self.motionEnabled {
if self.motionEnabled {
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
horizontal.minimumRelativeValue = motionAmount
horizontal.maximumRelativeValue = -motionAmount
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
vertical.minimumRelativeValue = motionAmount
vertical.maximumRelativeValue = -motionAmount
let group = UIMotionEffectGroup()
group.motionEffects = [horizontal, vertical]
self.contentNode.view.addMotionEffect(group)
} else {
for effect in self.contentNode.view.motionEffects {
self.contentNode.view.removeMotionEffect(effect)
}
}
if !self.frame.isEmpty {
self.updateScale()
}
}
}
}
public var image: UIImage? {
didSet {
self.contentNode.contents = self.image?.cgImage
}
}
public var rotation: CGFloat = 0.0 {
didSet {
var fromValue: CGFloat = 0.0
if let value = (self.layer.value(forKeyPath: "transform.rotation.z") as? NSNumber)?.floatValue {
fromValue = CGFloat(value)
}
self.contentNode.layer.transform = CATransform3DMakeRotation(self.rotation, 0.0, 0.0, 1.0)
self.contentNode.layer.animateRotation(from: fromValue, to: self.rotation, duration: 0.3)
}
}
public var imageContentMode: UIView.ContentMode {
didSet {
self.contentNode.contentMode = self.imageContentMode
}
}
func updateScale() {
if self.motionEnabled {
let scale = (self.frame.width + motionAmount * 2.0) / self.frame.width
self.contentNode.transform = CATransform3DMakeScale(scale, scale, 1.0)
} else {
self.contentNode.transform = CATransform3DIdentity
}
}
public override init() {
self.imageContentMode = .scaleAspectFill
self.contentNode = ASDisplayNode()
self.contentNode.contentMode = self.imageContentMode
super.init()
self.clipsToBounds = true
self.contentNode.frame = self.bounds
self.addSubnode(self.contentNode)
}
public func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) {
let isFirstLayout = self.contentNode.frame.isEmpty
transition.updatePosition(node: self.contentNode, position: CGPoint(x: size.width / 2.0, y: size.height / 2.0))
transition.updateBounds(node: self.contentNode, bounds: CGRect(origin: CGPoint(), size: size))
if isFirstLayout && !self.frame.isEmpty {
self.updateScale()
}
}
}