mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Add call localization
This commit is contained in:
parent
d88c78da57
commit
3fb85da558
@ -4418,6 +4418,7 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Call.Mute" = "mute";
|
||||
"Call.Camera" = "camera";
|
||||
"Call.Video" = "video";
|
||||
"Call.Flip" = "flip";
|
||||
"Call.End" = "end";
|
||||
"Call.Speaker" = "speaker";
|
||||
@ -5646,6 +5647,7 @@ Sorry for the inconvenience.";
|
||||
"Call.CameraConfirmationText" = "Switch to video call?";
|
||||
"Call.CameraConfirmationConfirm" = "Switch";
|
||||
|
||||
"Call.YourCameraOff" = "Your camera is off";
|
||||
"Call.YourMicrophoneOff" = "Your microphone is off";
|
||||
"Call.MicrophoneOff" = "%@'s microphone is off";
|
||||
"Call.CameraOff" = "%@'s camera is off";
|
||||
@ -10867,3 +10869,12 @@ Sorry for the inconvenience.";
|
||||
"Chat.PlayOnceMesasgeClose" = "Close";
|
||||
"Chat.PlayOnceMesasgeCloseAndDelete" = "Close and Delete";
|
||||
"Chat.PlayOnceMesasge.DisableScreenCapture" = "Sorry, you can't play this message while screen recording is active.";
|
||||
|
||||
"Call.EncryptedAlertTitle" = "This call is end-to-end encrypted";
|
||||
"Call.EncryptedAlertText" = "If the emoji on %@'s screen are the same, this call is 100% secure.";
|
||||
"Call.EncryptionKeyTooltip" = "Encryption key of this call";
|
||||
"Call.StatusBusy" = "Line Busy";
|
||||
"Call.StatusDeclined" = "Call Declined";
|
||||
"Call.StatusFailed" = "Call Failed";
|
||||
"Call.StatusEnded" = "Call Ended";
|
||||
"Call.StatusMissed" = "Call Missed";
|
||||
|
@ -43,6 +43,7 @@ swift_library(
|
||||
deps = [
|
||||
"//submodules/Display",
|
||||
"//submodules/MetalEngine",
|
||||
"//submodules/TelegramPresentationData",
|
||||
"//submodules/TelegramUI/Components/Calls/CallScreen",
|
||||
],
|
||||
)
|
||||
@ -188,5 +189,4 @@ xcodeproj(
|
||||
},
|
||||
},
|
||||
default_xcode_configuration = "Debug"
|
||||
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ import MetalEngine
|
||||
import Display
|
||||
import CallScreen
|
||||
import ComponentFlow
|
||||
import TelegramPresentationData
|
||||
|
||||
private extension UIScreen {
|
||||
private static let cornerRadiusKey: String = {
|
||||
@ -24,6 +25,7 @@ private extension UIScreen {
|
||||
public final class ViewController: UIViewController {
|
||||
private var callScreenView: PrivateCallScreen?
|
||||
private var callState: PrivateCallScreen.State = PrivateCallScreen.State(
|
||||
strings: defaultPresentationStrings,
|
||||
lifecycleState: .connecting,
|
||||
name: "Emma Walters",
|
||||
shortName: "Emma",
|
||||
|
@ -157,6 +157,7 @@ final class CallControllerNodeV2: ViewControllerTracingNode, CallControllerNodeP
|
||||
}
|
||||
|
||||
self.callScreenState = PrivateCallScreen.State(
|
||||
strings: presentationData.strings,
|
||||
lifecycleState: .connecting,
|
||||
name: " ",
|
||||
shortName: " ",
|
||||
|
@ -68,6 +68,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/AnimatedTextComponent",
|
||||
"//submodules/AppBundle",
|
||||
"//submodules/UIKitRuntimeUtils",
|
||||
"//submodules/TelegramPresentationData",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Snow.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
@ -3,34 +3,39 @@ import UIKit
|
||||
import Display
|
||||
|
||||
final class BackButtonView: HighlightableButton {
|
||||
private struct Params: Equatable {
|
||||
var text: String
|
||||
|
||||
init(text: String) {
|
||||
self.text = text
|
||||
}
|
||||
}
|
||||
|
||||
private struct Layout: Equatable {
|
||||
var params: Params
|
||||
var size: CGSize
|
||||
|
||||
init(params: Params, size: CGSize) {
|
||||
self.params = params
|
||||
self.size = size
|
||||
}
|
||||
}
|
||||
|
||||
private let iconView: UIImageView
|
||||
private let textView: TextView
|
||||
|
||||
let size: CGSize
|
||||
private var currentLayout: Layout?
|
||||
|
||||
var pressAction: (() -> Void)?
|
||||
|
||||
init(text: String) {
|
||||
override init(frame: CGRect) {
|
||||
self.iconView = UIImageView(image: NavigationBar.backArrowImage(color: .white))
|
||||
self.iconView.isUserInteractionEnabled = false
|
||||
|
||||
self.textView = TextView()
|
||||
self.textView.isUserInteractionEnabled = false
|
||||
|
||||
let spacing: CGFloat = 8.0
|
||||
|
||||
var iconSize: CGSize = self.iconView.image?.size ?? CGSize(width: 2.0, height: 2.0)
|
||||
let iconScaleFactor: CGFloat = 0.9
|
||||
iconSize.width = floor(iconSize.width * iconScaleFactor)
|
||||
iconSize.height = floor(iconSize.height * iconScaleFactor)
|
||||
|
||||
let textSize = self.textView.update(string: text, fontSize: 17.0, fontWeight: UIFont.Weight.regular.rawValue, color: .white, constrainedWidth: 100.0, transition: .immediate)
|
||||
self.size = CGSize(width: iconSize.width + spacing + textSize.width, height: textSize.height)
|
||||
|
||||
self.iconView.frame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((self.size.height - iconSize.height) * 0.5)), size: iconSize)
|
||||
self.textView.frame = CGRect(origin: CGPoint(x: iconSize.width + spacing, y: floorToScreenPixels((self.size.height - textSize.height) * 0.5)), size: textSize)
|
||||
|
||||
super.init(frame: CGRect())
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubview(self.iconView)
|
||||
self.addSubview(self.textView)
|
||||
@ -53,4 +58,31 @@ final class BackButtonView: HighlightableButton {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func update(text: String) -> CGSize {
|
||||
let params = Params(text: text)
|
||||
if let currentLayout = self.currentLayout, currentLayout.params == params {
|
||||
return currentLayout.size
|
||||
}
|
||||
let size = self.update(params: params)
|
||||
self.currentLayout = Layout(params: params, size: size)
|
||||
return size
|
||||
}
|
||||
|
||||
private func update(params: Params) -> CGSize {
|
||||
let spacing: CGFloat = 8.0
|
||||
|
||||
var iconSize: CGSize = self.iconView.image?.size ?? CGSize(width: 2.0, height: 2.0)
|
||||
let iconScaleFactor: CGFloat = 0.9
|
||||
iconSize.width = floor(iconSize.width * iconScaleFactor)
|
||||
iconSize.height = floor(iconSize.height * iconScaleFactor)
|
||||
|
||||
let textSize = self.textView.update(string: params.text, fontSize: 17.0, fontWeight: UIFont.Weight.regular.rawValue, color: .white, constrainedWidth: 100.0, transition: .immediate)
|
||||
let size = CGSize(width: iconSize.width + spacing + textSize.width, height: textSize.height)
|
||||
|
||||
self.iconView.frame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((size.height - iconSize.height) * 0.5)), size: iconSize)
|
||||
self.textView.frame = CGRect(origin: CGPoint(x: iconSize.width + spacing, y: floorToScreenPixels((size.height - textSize.height) * 0.5)), size: textSize)
|
||||
|
||||
return size
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import UIKit
|
||||
import Display
|
||||
import ComponentFlow
|
||||
import AppBundle
|
||||
import TelegramPresentationData
|
||||
|
||||
final class ButtonGroupView: OverlayMaskContainerView {
|
||||
final class Button {
|
||||
@ -85,7 +86,7 @@ final class ButtonGroupView: OverlayMaskContainerView {
|
||||
return result
|
||||
}
|
||||
|
||||
func update(size: CGSize, insets: UIEdgeInsets, minWidth: CGFloat, controlsHidden: Bool, displayClose: Bool, buttons: [Button], notices: [Notice], transition: Transition) -> CGFloat {
|
||||
func update(size: CGSize, insets: UIEdgeInsets, minWidth: CGFloat, controlsHidden: Bool, displayClose: Bool, strings: PresentationStrings, buttons: [Button], notices: [Notice], transition: Transition) -> CGFloat {
|
||||
self.buttons = buttons
|
||||
|
||||
let buttonSize: CGFloat = 56.0
|
||||
@ -190,7 +191,7 @@ final class ButtonGroupView: OverlayMaskContainerView {
|
||||
}
|
||||
}
|
||||
let closeButtonSize = CGSize(width: minWidth, height: buttonSize)
|
||||
closeButtonView.update(text: "Close", size: closeButtonSize, transition: closeButtonTransition)
|
||||
closeButtonView.update(text: strings.Common_Close, size: closeButtonSize, transition: closeButtonTransition)
|
||||
closeButtonTransition.setFrame(view: closeButtonView, frame: CGRect(origin: CGPoint(x: floor((size.width - closeButtonSize.width) * 0.5), y: buttonY), size: closeButtonSize))
|
||||
|
||||
if animateIn && !transition.animation.isImmediate {
|
||||
@ -218,9 +219,9 @@ final class ButtonGroupView: OverlayMaskContainerView {
|
||||
case let .speaker(audioOutput):
|
||||
switch audioOutput {
|
||||
case .internalSpeaker, .speaker:
|
||||
title = "speaker"
|
||||
title = strings.Call_Speaker
|
||||
default:
|
||||
title = "audio"
|
||||
title = strings.Call_Audio
|
||||
}
|
||||
|
||||
switch audioOutput {
|
||||
@ -247,19 +248,19 @@ final class ButtonGroupView: OverlayMaskContainerView {
|
||||
isActive = true
|
||||
}
|
||||
case .flipCamera:
|
||||
title = "flip"
|
||||
title = strings.Call_Flip
|
||||
image = UIImage(bundleImageName: "Call/Flip")
|
||||
isActive = false
|
||||
case let .video(isActiveValue):
|
||||
title = "video"
|
||||
title = strings.Call_Video
|
||||
image = UIImage(bundleImageName: "Call/Video")
|
||||
isActive = isActiveValue
|
||||
case let .microphone(isActiveValue):
|
||||
title = "mute"
|
||||
title = strings.Call_Mute
|
||||
image = UIImage(bundleImageName: "Call/Mute")
|
||||
isActive = isActiveValue
|
||||
case .end:
|
||||
title = "end"
|
||||
title = strings.Call_End
|
||||
image = UIImage(bundleImageName: "Call/End")
|
||||
isActive = false
|
||||
isDestructive = true
|
||||
|
@ -7,6 +7,7 @@ import MetalEngine
|
||||
import ComponentFlow
|
||||
import SwiftSignalKit
|
||||
import UIKitRuntimeUtils
|
||||
import TelegramPresentationData
|
||||
|
||||
public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictureControllerDelegate {
|
||||
public struct State: Equatable {
|
||||
@ -67,6 +68,7 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
case bluetooth
|
||||
}
|
||||
|
||||
public var strings: PresentationStrings
|
||||
public var lifecycleState: LifecycleState
|
||||
public var name: String
|
||||
public var shortName: String
|
||||
@ -77,8 +79,10 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
public var localVideo: VideoSource?
|
||||
public var remoteVideo: VideoSource?
|
||||
public var isRemoteBatteryLow: Bool
|
||||
public var displaySnowEffect: Bool
|
||||
|
||||
public init(
|
||||
strings: PresentationStrings,
|
||||
lifecycleState: LifecycleState,
|
||||
name: String,
|
||||
shortName: String,
|
||||
@ -88,8 +92,10 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
isRemoteAudioMuted: Bool,
|
||||
localVideo: VideoSource?,
|
||||
remoteVideo: VideoSource?,
|
||||
isRemoteBatteryLow: Bool
|
||||
isRemoteBatteryLow: Bool,
|
||||
displaySnowEffect: Bool = false
|
||||
) {
|
||||
self.strings = strings
|
||||
self.lifecycleState = lifecycleState
|
||||
self.name = name
|
||||
self.shortName = shortName
|
||||
@ -100,9 +106,13 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
self.localVideo = localVideo
|
||||
self.remoteVideo = remoteVideo
|
||||
self.isRemoteBatteryLow = isRemoteBatteryLow
|
||||
self.displaySnowEffect = displaySnowEffect
|
||||
}
|
||||
|
||||
public static func ==(lhs: State, rhs: State) -> Bool {
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
if lhs.lifecycleState != rhs.lifecycleState {
|
||||
return false
|
||||
}
|
||||
@ -133,6 +143,9 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
if lhs.isRemoteBatteryLow != rhs.isRemoteBatteryLow {
|
||||
return false
|
||||
}
|
||||
if lhs.displaySnowEffect != rhs.displaySnowEffect {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -218,6 +231,8 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
private var pipVideoCallViewController: UIViewController?
|
||||
private var pipController: AVPictureInPictureController?
|
||||
|
||||
private var snowEffectView: SnowEffectView?
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
self.overlayContentsView = UIView()
|
||||
self.overlayContentsView.isUserInteractionEnabled = false
|
||||
@ -240,7 +255,7 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
self.titleView = TextView()
|
||||
self.statusView = StatusView()
|
||||
|
||||
self.backButtonView = BackButtonView(text: "Back")
|
||||
self.backButtonView = BackButtonView(frame: CGRect())
|
||||
|
||||
self.pipView = PrivateCallPictureInPictureView(frame: CGRect(origin: CGPoint(), size: CGSize()))
|
||||
|
||||
@ -740,16 +755,16 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
var notices: [ButtonGroupView.Notice] = []
|
||||
if !isTerminated {
|
||||
if params.state.isLocalAudioMuted {
|
||||
notices.append(ButtonGroupView.Notice(id: AnyHashable(0 as Int), icon: "Call/CallToastMicrophone", text: "Your microphone is turned off"))
|
||||
notices.append(ButtonGroupView.Notice(id: AnyHashable(0 as Int), icon: "Call/CallToastMicrophone", text: params.state.strings.Call_YourMicrophoneOff))
|
||||
}
|
||||
if params.state.isRemoteAudioMuted {
|
||||
notices.append(ButtonGroupView.Notice(id: AnyHashable(1 as Int), icon: "Call/CallToastMicrophone", text: "\(params.state.shortName)'s microphone is turned off"))
|
||||
notices.append(ButtonGroupView.Notice(id: AnyHashable(1 as Int), icon: "Call/CallToastMicrophone", text: params.state.strings.Call_MicrophoneOff(params.state.shortName).string))
|
||||
}
|
||||
if params.state.remoteVideo != nil && params.state.localVideo == nil {
|
||||
notices.append(ButtonGroupView.Notice(id: AnyHashable(2 as Int), icon: "Call/CallToastCamera", text: "Your camera is turned off"))
|
||||
notices.append(ButtonGroupView.Notice(id: AnyHashable(2 as Int), icon: "Call/CallToastCamera", text: params.state.strings.Call_YourCameraOff))
|
||||
}
|
||||
if params.state.isRemoteBatteryLow {
|
||||
notices.append(ButtonGroupView.Notice(id: AnyHashable(3 as Int), icon: "Call/CallToastBattery", text: "\(params.state.shortName)'s battery is low"))
|
||||
notices.append(ButtonGroupView.Notice(id: AnyHashable(3 as Int), icon: "Call/CallToastBattery", text: params.state.strings.Call_BatteryLow(params.state.shortName).string))
|
||||
}
|
||||
}
|
||||
|
||||
@ -759,7 +774,7 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
}*/
|
||||
let displayClose = false
|
||||
|
||||
let contentBottomInset = self.buttonGroupView.update(size: params.size, insets: params.insets, minWidth: wideContentWidth, controlsHidden: currentAreControlsHidden, displayClose: displayClose, buttons: buttons, notices: notices, transition: transition)
|
||||
let contentBottomInset = self.buttonGroupView.update(size: params.size, insets: params.insets, minWidth: wideContentWidth, controlsHidden: currentAreControlsHidden, displayClose: displayClose, strings: params.state.strings, buttons: buttons, notices: notices, transition: transition)
|
||||
|
||||
var expandedEmojiKeyRect: CGRect?
|
||||
if self.isEmojiKeyExpanded {
|
||||
@ -777,7 +792,7 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
alphaTransition = genericAlphaTransition
|
||||
}
|
||||
|
||||
emojiExpandedInfoView = EmojiExpandedInfoView(title: "This call is end-to-end encrypted", text: "If the emoji on \(params.state.shortName)'s screen are the same, this call is 100% secure.")
|
||||
emojiExpandedInfoView = EmojiExpandedInfoView(title: params.state.strings.Call_EncryptedAlertTitle, text: params.state.strings.Call_EncryptedAlertText(params.state.shortName).string)
|
||||
self.emojiExpandedInfoView = emojiExpandedInfoView
|
||||
emojiExpandedInfoView.alpha = 0.0
|
||||
Transition.immediate.setScale(view: emojiExpandedInfoView, scale: 0.5)
|
||||
@ -824,13 +839,15 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
}
|
||||
}
|
||||
|
||||
let backButtonSize = self.backButtonView.update(text: params.state.strings.Common_Back)
|
||||
|
||||
let backButtonY: CGFloat
|
||||
if currentAreControlsHidden {
|
||||
backButtonY = -self.backButtonView.size.height - 12.0
|
||||
backButtonY = -backButtonSize.height - 12.0
|
||||
} else {
|
||||
backButtonY = params.insets.top + 12.0
|
||||
}
|
||||
let backButtonFrame = CGRect(origin: CGPoint(x: params.insets.left + 10.0, y: backButtonY), size: self.backButtonView.size)
|
||||
let backButtonFrame = CGRect(origin: CGPoint(x: params.insets.left + 10.0, y: backButtonY), size: backButtonSize)
|
||||
transition.setFrame(view: self.backButtonView, frame: backButtonFrame)
|
||||
transition.setAlpha(view: self.backButtonView, alpha: currentAreControlsHidden ? 0.0 : 1.0)
|
||||
|
||||
@ -914,7 +931,7 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
emojiTooltipView = current
|
||||
} else {
|
||||
emojiTooltipTransition = emojiTooltipTransition.withAnimation(.none)
|
||||
emojiTooltipView = EmojiTooltipView(text: "Encryption key of this call")
|
||||
emojiTooltipView = EmojiTooltipView(text: params.state.strings.Call_EncryptionKeyTooltip)
|
||||
animateIn = true
|
||||
self.emojiTooltipView = emojiTooltipView
|
||||
self.addSubview(emojiTooltipView)
|
||||
@ -1192,15 +1209,15 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
|
||||
switch terminatedState.reason {
|
||||
case .busy:
|
||||
titleString = "Line Busy"
|
||||
titleString = params.state.strings.Call_StatusBusy
|
||||
case .declined:
|
||||
titleString = "Call Declined"
|
||||
titleString = params.state.strings.Call_StatusDeclined
|
||||
case .failed:
|
||||
titleString = "Call Failed"
|
||||
titleString = params.state.strings.Call_StatusFailed
|
||||
case .hangUp:
|
||||
titleString = "Call Ended"
|
||||
titleString = params.state.strings.Call_StatusEnded
|
||||
case .missed:
|
||||
titleString = "Call Missed"
|
||||
titleString = params.state.strings.Call_StatusMissed
|
||||
}
|
||||
default:
|
||||
displayAudioLevelBlob = !params.state.isRemoteAudioMuted
|
||||
@ -1358,5 +1375,75 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/*if params.state.displaySnowEffect {
|
||||
let snowEffectView: SnowEffectView
|
||||
if let current = self.snowEffectView {
|
||||
snowEffectView = current
|
||||
} else {
|
||||
snowEffectView = SnowEffectView(frame: CGRect())
|
||||
self.snowEffectView = snowEffectView
|
||||
self.maskContents.addSubview(snowEffectView)
|
||||
}
|
||||
transition.setFrame(view: snowEffectView, frame: CGRect(origin: CGPoint(), size: params.size))
|
||||
snowEffectView.update(size: params.size)
|
||||
} else {
|
||||
if let snowEffectView = self.snowEffectView {
|
||||
self.snowEffectView = nil
|
||||
snowEffectView.removeFromSuperview()
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
final class SnowEffectView: UIView {
|
||||
private let particlesLayer: CAEmitterLayer
|
||||
|
||||
override init(frame: CGRect) {
|
||||
let particlesLayer = CAEmitterLayer()
|
||||
self.particlesLayer = particlesLayer
|
||||
self.particlesLayer.backgroundColor = nil
|
||||
self.particlesLayer.isOpaque = false
|
||||
|
||||
particlesLayer.emitterShape = .circle
|
||||
particlesLayer.emitterMode = .surface
|
||||
particlesLayer.renderMode = .oldestLast
|
||||
|
||||
let image1 = UIImage(named: "Call/Snow")?.cgImage
|
||||
|
||||
let cell1 = CAEmitterCell()
|
||||
cell1.contents = image1
|
||||
cell1.name = "Snow"
|
||||
cell1.birthRate = 92.0
|
||||
cell1.lifetime = 20.0
|
||||
cell1.velocity = 59.0
|
||||
cell1.velocityRange = -15.0
|
||||
cell1.xAcceleration = 5.0
|
||||
cell1.yAcceleration = 40.0
|
||||
cell1.emissionRange = 90.0 * (.pi / 180.0)
|
||||
cell1.spin = -28.6 * (.pi / 180.0)
|
||||
cell1.spinRange = 57.2 * (.pi / 180.0)
|
||||
cell1.scale = 0.06
|
||||
cell1.scaleRange = 0.3
|
||||
cell1.color = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0).cgColor
|
||||
|
||||
particlesLayer.emitterCells = [cell1]
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.layer.addSublayer(particlesLayer)
|
||||
self.clipsToBounds = true
|
||||
self.backgroundColor = nil
|
||||
self.isOpaque = false
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func update(size: CGSize) {
|
||||
self.particlesLayer.frame = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)
|
||||
self.particlesLayer.emitterSize = CGSize(width: size.width * 3.0, height: size.height * 2.0)
|
||||
self.particlesLayer.emitterPosition = CGPoint(x: size.width * 0.5, y: -325.0)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user