Как встряхнуть текстовое поле в быстром 4? [Дубликат]

Это очень распространенная проблема, с которой мы сталкиваемся, борясь с «таинствами» JavaScript.

Давайте начнем с простой функции JavaScript:

function foo(){
// do something 
 return 'wohoo';
}

let bar = foo(); // bar is 'wohoo' here

Это простой синхронный вызов функции (где каждая строка кода выполняется одна за другой в последовательность), и результат будет таким же, как ожидалось.

Теперь добавим немного завихрения, введя небольшую задержку в нашей функции, чтобы все строки кода не выполнялись последовательно. Таким образом, он будет эмулировать асинхронное поведение функции:

function foo(){
 setTimeout( ()=>{
   return 'wohoo';
  }, 1000 )
}

let bar = foo() // bar is undefined here

Итак, вы идете, эта задержка просто сломала функциональность, которую мы ожидали! Но что именно произошло? Ну, на самом деле это довольно логично, если вы посмотрите на код. функция foo() после выполнения ничего не возвращает (таким образом, возвращаемое значение равно undefined), но оно запускает таймер, который выполняет функцию после 1s, чтобы вернуть «wohoo». Но, как вы можете видеть, значение, присвоенное бару, является немедленно возвращенным материалом из foo (), а не что-либо еще, что приходит позже.

Итак, как мы решаем эту проблему?

Давайте попросим нашу функцию для ОБЕЩАНИЯ. Обещание действительно о том, что это означает: это означает, что функция гарантирует, что вы предоставите любой результат, который он получит в будущем. поэтому давайте посмотрим на это в нашей маленькой проблеме выше:

function foo(){
   return new Promise( (resolve, reject) => { // I want foo() to PROMISE me something
    setTimeout ( function(){ 
      // promise is RESOLVED , when exececution reaches this line of code
       resolve('wohoo')// After 1 second, RESOLVE the promise with value 'wohoo'
    }, 1000 )
  })
}

let bar ; 
foo().then( res => {
 bar = res;
 console.log(bar) // will print 'wohoo'
});

Таким образом, резюме - для решения асинхронных функций, таких как вызовы на основе ajax и т. д., вы можете использовать обещание resolve значение (которое вы намерены вернуть). Таким образом, короче говоря, вы разрешаете значение вместо возврата в асинхронных функциях.

44
задан rakeshbs 16 January 2015 в 18:26
поделиться

7 ответов

Вы можете изменить duration и repeatCount и настроить его. Это то, что я использую в своем коде. Изменение fromValue и toValue изменяет расстояние, перемещенное в дрожании.

let animation = CABasicAnimation(keyPath: "position")
animation.duration = 0.07
animation.repeatCount = 4
animation.autoreverses = true
animation.fromValue = NSValue(cgPoint: CGPoint(x: viewToShake.center.x - 10, y: viewToShake.center.y))
animation.toValue = NSValue(cgPoint: CGPoint(x: viewToShake.center.x + 10, y: viewToShake.center.y))

viewToShake.layer.add(animation, forKey: "position")
103
ответ дан Vasily 25 August 2018 в 22:34
поделиться

Это основано на CABasicAnimation, оно также содержит звуковой эффект:

extension UIView{
    var audioPlayer = AVAudioPlayer()
    func vibrate(){
        let animation = CABasicAnimation(keyPath: "position")
        animation.duration = 0.05
        animation.repeatCount = 5
        animation.autoreverses = true
        animation.fromValue = NSValue(CGPoint: CGPointMake(self.center.x - 5.0, self.center.y))
        animation.toValue = NSValue(CGPoint: CGPointMake(self.center.x + 5.0, self.center.y))
        self.layer.addAnimation(animation, forKey: "position")
        // audio part
        do {
            audioPlayer =  try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(mySoundFileName, ofType: "mp3")!))
            audioPlayer.prepareToPlay()
            audioPlayer.play()

        } catch {
            print("∙ Error playing vibrate sound..")
        }
    }
}
0
ответ дан Alessandro Ornano 25 August 2018 в 22:34
поделиться

В любом представлении используется следующая функция.

extension UIView {
    func shake() {
        let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        animation.duration = 0.6
        animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
        layer.add(animation, forKey: "shake")
    }
}
99
ответ дан Andrej 25 August 2018 в 22:34
поделиться

Я думаю, что все это опасно.

Если ваша анимация встряски основана на действии пользователя и что действие пользователя запускается во время анимации.

CRAAAAAASH

Вот мой способ в Swift 4:

static func shake(view: UIView, for duration: TimeInterval = 0.5, withTranslation translation: CGFloat = 10) {
    let propertyAnimator = UIViewPropertyAnimator(duration: duration, dampingRatio: 0.3) {
        view.transform = CGAffineTransform(translationX: translation, y: 0)
    }

    propertyAnimator.addAnimations({
        view.transform = CGAffineTransform(translationX: 0, y: 0)
    }, delayFactor: 0.2)

    propertyAnimator.startAnimation()
}

Может быть, не самый чистый, но этот метод может быть многократно срабатывает и легко понятен

8
ответ дан Corey Pett 25 August 2018 в 22:34
поделиться
extension CALayer {

    func shake(duration: NSTimeInterval = NSTimeInterval(0.5)) {

        let animationKey = "shake"
        removeAnimationForKey(animationKey)

        let kAnimation = CAKeyframeAnimation(keyPath: "transform.translation.x")
        kAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        kAnimation.duration = duration

        var needOffset = CGRectGetWidth(frame) * 0.15,
        values = [CGFloat]()

        let minOffset = needOffset * 0.1

        repeat {

            values.append(-needOffset)
            values.append(needOffset)
            needOffset *= 0.5
        } while needOffset > minOffset

        values.append(0)
        kAnimation.values = values
        addAnimation(kAnimation, forKey: animationKey)
    }
}

Как использовать:

[UIView, UILabel, UITextField, UIButton & etc].layer.shake(NSTimeInterval(0.7))
3
ответ дан Dmitriiy Mitrophanskiy 25 August 2018 в 22:34
поделиться

Swift 3.0

extension UIView {
        func shake(){
            let animation = CABasicAnimation(keyPath: "position")
            animation.duration = 0.07
            animation.repeatCount = 3
            animation.autoreverses = true
            animation.fromValue = NSValue(cgPoint: CGPoint(x: self.center.x - 10, y: self.center.y))
            animation.toValue = NSValue(cgPoint: CGPoint(x: self.center.x + 10, y: self.center.y))
            self.layer.add(animation, forKey: "position")
        }
    }

Чтобы использовать

self.vwOffer.shake()
9
ответ дан Hardik Thakkar 25 August 2018 в 22:34
поделиться

Или вы можете использовать это, если хотите больше параметров (в swift 3 и swift 4):

public extension UIView {

    func shake(count : Float = 4,for duration : TimeInterval = 0.5,withTranslation translation : Float = 5) {

        let animation : CABasicAnimation = CABasicAnimation(keyPath: "transform.translation.x")
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        animation.repeatCount = count
        animation.duration = duration/TimeInterval(animation.repeatCount)
        animation.autoreverses = true
        animation.fromValue = NSValue(cgPoint: CGPoint(x: -translation, y: self.center.y))
        animation.toValue = NSValue(cgPoint: CGPoint(x: translation, y: self.center.y))
        layer.add(animation, forKey: "shake")
    }  
}

Вы можете вызвать эту функцию на любых UIView, UIButton, UILabel, UITextView и т. д. Таким образом

yourView.shake()

Или, если вы хотите добавить в анимацию некоторые настраиваемые параметры:

yourView.shake(count: 5, for: 1.5, withTranslation: 10)
34
ответ дан RomOne 25 August 2018 в 22:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: