2011-07-06 11 views
18

मैं एक आईपैड ऐप लिख रहा हूं जो पेज दस्तावेजों को प्रस्तुत करता है जैसे पृष्ठ (वास्तविक दस्तावेज़ के बड़े आइकन) के रूप में। जब उपयोगकर्ता संपादन बटन को टैप करता है तो मैं भीड़ के व्यवहार की नकल करना चाहता हूं। यह वही जिग्लू पैटर्न है जो आइकन आईफोन और आईपैड दोनों पर टैप करके उन्हें पकड़ते समय होम स्क्रीन पर बनाते हैं।आईओएस आइकन jiggle एल्गोरिदम

मैंने इंटरनेट की खोज की है और कुछ एल्गोरिदम पाए हैं, लेकिन वे सिर्फ दृश्य को पीछे और आगे बढ़ने का कारण बनाते हैं जो कि ऐप्पल की तरह नहीं है। ऐसा लगता है कि वहां कुछ यादृच्छिकता है क्योंकि प्रत्येक आइकन थोड़ा अलग होता है।

क्या किसी के पास कुछ कोड है या पता है जो एक ही जिग्गल पैटर्न (या इसके बहुत करीब कुछ) फिर से बना सकता है? धन्यवाद!!!

उत्तर

12

ठीक है, इसलिए ओपनप्रिंगबोर्ड कोड ने मेरे लिए काफी कुछ नहीं किया है, लेकिन मैंने मुझे कुछ कोड बनाने की अनुमति दी जो मुझे लगता है कि थोड़ा बेहतर है, अभी भी प्रीफेक्ट नहीं है लेकिन बेहतर है। किसी को भी इस बेहतर बनाने के लिए सुझाव दिया है, मैं उन्हें सुनने के लिए ...

#define degreesToRadians(x) (M_PI * (x)/180.0) 
#define kAnimationRotateDeg 1.0 
#define kAnimationTranslateX 2.0 
#define kAnimationTranslateY 2.0 

- (void)startJiggling:(NSInteger)count { 

    CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians(kAnimationRotateDeg * (count%2 ? +1 : -1))); 
    CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians(kAnimationRotateDeg * (count%2 ? -1 : +1))); 
    CGAffineTransform moveTransform = CGAffineTransformTranslate(rightWobble, -kAnimationTranslateX, -kAnimationTranslateY); 
    CGAffineTransform conCatTransform = CGAffineTransformConcat(rightWobble, moveTransform); 

    self.transform = leftWobble; // starting point 

    [UIView animateWithDuration:0.1 
          delay:(count * 0.08) 
         options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse 
        animations:^{ self.transform = conCatTransform; } 
        completion:nil]; 
} 

- (void)stopJiggling { 
    [self.layer removeAllAnimations]; 
    self.transform = CGAffineTransformIdentity; // Set it straight 
} 
3

openspringboard project देखें।

विशेष रूप से, setIconAnimimation: (BOOL) OpenSpringBoard.m में अनुमान लगा रहा है। इससे आपको कुछ विचार करना चाहिए कि यह कैसे करें।

32


(दृश्य (रों के उपवर्ग में जोड़ना) आप बजना करना चाहते हैं) प्यार होता @ Vic320 का जवाब अच्छा है, लेकिन व्यक्तिगत रूप से मुझे अनुवाद पसंद नहीं है। मैंने अपना कोड एक समाधान प्रदान करने के लिए संपादित किया है जिसे मैं व्यक्तिगत रूप से स्प्रिंगबोर्ड वॉबल प्रभाव की तरह दिखता हूं। ज्यादातर, यह एक छोटे अनियमितता जोड़ने और रोटेशन पर ध्यान केंद्रित कर अनुवाद के बिना, के द्वारा प्राप्त किया है:

#define degreesToRadians(x) (M_PI * (x)/180.0) 
#define kAnimationRotateDeg 1.0 

- (void)startJiggling { 
    NSInteger randomInt = arc4random_uniform(500); 
    float r = (randomInt/500.0)+0.5; 

    CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians((kAnimationRotateDeg * -1.0) - r)); 
    CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians(kAnimationRotateDeg + r)); 

    self.transform = leftWobble; // starting point 

    [[self layer] setAnchorPoint:CGPointMake(0.5, 0.5)]; 

    [UIView animateWithDuration:0.1 
          delay:0 
         options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse 
         animations:^{ 
           [UIView setAnimationRepeatCount:NSNotFound]; 
           self.transform = rightWobble; } 
         completion:nil]; 
} 
- (void)stopJiggling { 
    [self.layer removeAllAnimations]; 
    self.transform = CGAffineTransformIdentity; 
} 


क्रेडिट जहाँ क्रेडिट की वजह से हालांकि, @ Vic320 के जवाब के लिए इस कोड के लिए आधार प्रदान की है कि के लिए बहुत +1।

+0

यदि आपका एंकर पॉइंट कहीं और पर सेट किया गया है, तो 0.5,0.5 के अलावा रोटेशन एंकर पॉइंट के चारों ओर बटन "कक्षा" बना देगा। यह अपने आप से एक अच्छा प्रभाव हो सकता है :) –

+0

हाँ एलेक्स! शायद ओपी के लिए वांछनीय नहीं है लेकिन यह एक अच्छा प्रभाव होगा। – imnk

+1

युगल अधिक अंक: [UIView setAnimationRepeatCount: NSNotFound]; आवश्यक नहीं है, क्योंकि UIViewAnimationOptionRepeat सेट किया गया है। और एनीमेशन को रोकने के लिए, यह करें: [self.layer removeAllAnimimations]; – sdsykes

3

भविष्य में आने वाले अन्य लोगों के लाभ के लिए, मुझे लगा कि @ विक 320 द्वारा दी गई चिल्लाहट बहुत रोबोट थी और इसे मुख्य रूप से की तुलना में यह थोड़ा मजबूत था और कार्बनिक (यादृच्छिक?) पर्याप्त नहीं था। तो साझा करने की भावना में, यहां कोड है जिसे मैंने UIView के अपने उप-वर्ग में बनाया है ... मेरा व्यू कंट्रोलर इन ऑब्जेक्ट्स की एक सरणी रखता है और जब उपयोगकर्ता संपादन बटन को टैप करता है, तो व्यू कंट्रोलर प्रत्येक को स्टार्टजिंग संदेश भेजता है, एक स्टॉपजिंग संदेश द्वारा जब उपयोगकर्ता पूर्ण बटन दबाता है।

- (void)startJiggling 
{ 
    // jiggling code based off the folks on stackoverflow.com: 
    // http://stackoverflow.com/questions/6604356/ios-icon-jiggle-algorithm 

#define degreesToRadians(x) (M_PI * (x)/180.0) 
#define kAnimationRotateDeg 0.1 
    jiggling = YES; 
    [self wobbleLeft]; 
} 

- (void)wobbleLeft 
{ 
    if (jiggling) { 
     NSInteger randomInt = arc4random()%500; 
     float r = (randomInt/500.0)+0.5; 

     CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians((kAnimationRotateDeg * -1.0) - r)); 
     CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians(kAnimationRotateDeg + r)); 

     self.transform = leftWobble; // starting point 

     [UIView animateWithDuration:0.1 
         delay:0 
        options:UIViewAnimationOptionAllowUserInteraction 
       animations:^{ self.transform = rightWobble; } 
       completion:^(BOOL finished) { [self wobbleRight]; } 
      ]; 
    } 
} 

- (void)wobbleRight 
{ 
    if (jiggling) { 

     NSInteger randomInt = arc4random()%500; 
     float r = (randomInt/500.0)+0.5; 

     CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians((kAnimationRotateDeg * -1.0) - r)); 
     CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians(kAnimationRotateDeg + r)); 

     self.transform = rightWobble; // starting point 

     [UIView animateWithDuration:0.1 
         delay:0 
        options:UIViewAnimationOptionAllowUserInteraction 
       animations:^{ self.transform = leftWobble; } 
       completion:^(BOOL finished) { [self wobbleLeft]; } 
     ]; 
    } 

} 
- (void)stopJiggling 
{ 
    jiggling = NO; 
    [self.layer removeAllAnimations]; 
    [self setTransform:CGAffineTransformIdentity]; 
    [self.layer setAnchorPoint:CGPointMake(0.5, 0.5)]; 
} 
2

तो मुझे यकीन है कि मैं (इस है कि मैं की वजह से मैं एक अर्द्ध शुरुआत कर रहा हूँ के बारे में पता नहीं कर रहा हूँ करने के लिए शायद आसान तरीके हैं) गन्दा कोड लिखने के लिए पर चिल्लाए मिल जाएगा, लेकिन यह है Vic320 के एल्गोरिदम का एक और यादृच्छिक संस्करण जो रोटेशन और अनुवाद की मात्रा को बदलता है। यह यादृच्छिक रूप से तय करता है कि यह किस दिशा में पहले घुमाएगा, जो अधिक अधिक यादृच्छिक रूप देता है यदि आपके पास एक साथ कई चीजें हैं। यदि दक्षता आपके लिए एक बड़ी समस्या है, तो इसका उपयोग न करें। यह वही है जो मैं इस तरह से आया था कि मुझे पता है कि यह कैसे करना है।

किसी को भी सोचने के लिए कि आपको #import <QuartzCore/QuartzCore.h> की आवश्यकता है और इसे अपने लिंक किए गए पुस्तकालयों में जोड़ें। अन्य उत्तर से प्रेरित - - एक स्पष्ट एनीमेशन का उपयोग कर

#define degreesToRadians(x) (M_PI * (x)/180.0) 

- (void)startJiggling:(NSInteger)count { 
    double kAnimationRotateDeg = (double)(arc4random()%5 + 5)/10; 
    double kAnimationTranslateX = (arc4random()%4); 
    double kAnimationTranslateY = (arc4random()%4); 

    CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians(kAnimationRotateDeg * (count%2 ? +1 : -1))); 
    CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians(kAnimationRotateDeg * (count%2 ? -1 : +1))); 
    int leftOrRight = (arc4random()%2); 
    if (leftOrRight == 0){ 
     CGAffineTransform moveTransform = CGAffineTransformTranslate(rightWobble, -kAnimationTranslateX, -kAnimationTranslateY); 
     CGAffineTransform conCatTransform = CGAffineTransformConcat(rightWobble, moveTransform); 
     self.transform = leftWobble; // starting point 

     [UIView animateWithDuration:0.1 
           delay:(count * 0.08) 
          options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse 
         animations:^{ self.transform = conCatTransform; } 
         completion:nil]; 
    } else if (leftOrRight == 1) { 
     CGAffineTransform moveTransform = CGAffineTransformTranslate(leftWobble, -kAnimationTranslateX, -kAnimationTranslateY); 
     CGAffineTransform conCatTransform = CGAffineTransformConcat(leftWobble, moveTransform); 
     self.transform = rightWobble; // starting point 

     [UIView animateWithDuration:0.1 
           delay:(count * 0.08) 
          options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse 
         animations:^{ self.transform = conCatTransform; } 
         completion:nil]; 
    } 
} 

- (void)stopJiggling { 
    [self.layer removeAllAnimations]; 
    self.transform = CGAffineTransformIdentity; // Set it straight 
} 
+0

मुझे अपनी पसंद को यादृच्छिक बनाने के लिए पसंद है कि किस दिशा में जिगलिंग शुरू होनी चाहिए। मैं अपने कोड को समान रूप से अपडेट करने जा रहा हूं !! – tobinjim

6

पूर्णता के लिए, यहाँ कैसे मैं अपने CALayer उपवर्ग एनिमेटेड है।

-(void)stopJiggle 
{ 
    [self removeAnimationForKey:@"jiggle"]; 
} 

-(void)startJiggle 
{ 
    const float amplitude = 1.0f; // degrees 
    float r = (rand()/(float)RAND_MAX) - 0.5f; 
    float angleInDegrees = amplitude * (1.0f + r * 0.1f); 
    float animationRotate = angleInDegrees/180. * M_PI; // Convert to radians 

    NSTimeInterval duration = 0.1; 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; 
    animation.duration = duration; 
    animation.additive = YES; 
    animation.autoreverses = YES; 
    animation.repeatCount = FLT_MAX; 
    animation.fromValue = @(-animationRotate); 
    animation.toValue = @(animationRotate); 
    animation.timeOffset = (rand()/(float)RAND_MAX) * duration; 
    [self addAnimation:animation forKey:@"jiggle"]; 
} 
2

मैंने ऐप्पल स्ट्रिंगबोर्ड इंजीनियर किया, और उनकी एनीमेशन थोड़ा संशोधित किया, और नीचे कोड वास्तव में अच्छी चीजें है।

+ (CAAnimationGroup *)jiggleAnimation { 
CAKeyframeAnimation *position = [CAKeyframeAnimation animation]; 
position.keyPath = @"position"; 
position.values = @[ 
        [NSValue valueWithCGPoint:CGPointZero], 
        [NSValue valueWithCGPoint:CGPointMake(-1, 0)], 
        [NSValue valueWithCGPoint:CGPointMake(1, 0)], 
        [NSValue valueWithCGPoint:CGPointMake(-1, 1)], 
        [NSValue valueWithCGPoint:CGPointMake(1, -1)], 
        [NSValue valueWithCGPoint:CGPointZero] 
        ]; 
position.timingFunctions = @[ 
          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut] 
          ]; 
position.additive = YES; 

CAKeyframeAnimation *rotation = [CAKeyframeAnimation animation]; 
rotation.keyPath = @"transform.rotation"; 
rotation.values = @[ 
        @0, 
        @0.03, 
        @0, 
        [NSNumber numberWithFloat:-0.02] 
        ]; 
rotation.timingFunctions = @[ 
          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut] 
          ]; 

CAAnimationGroup *group = [[CAAnimationGroup alloc] init]; 
group.animations = @[ position, rotation ]; 
group.duration = 0.3; 
group.repeatCount = HUGE_VALF; 
group.beginTime = arc4random() % 30/100.f; 
return group; 
} 

मूल एप्पल बजना एनीमेशन:

CAKeyframeAnimation *position = [CAKeyframeAnimation animation]; 
position.beginTime = 0.8; 
position.duration = 0.25; 
position.values = @[[NSValue valueWithCGPoint:CGPointMake(-1, -1)], 
        [NSValue valueWithCGPoint:CGPointMake(0, 0)], 
        [NSValue valueWithCGPoint:CGPointMake(-1, 0)], 
        [NSValue valueWithCGPoint:CGPointMake(0, -1)], 
        [NSValue valueWithCGPoint:CGPointMake(-1, -1)]]; 
position.calculationMode = @"linear"; 
position.removedOnCompletion = NO; 
position.repeatCount = CGFLOAT_MAX; 
position.beginTime = arc4random() % 25/100.f; 
position.additive = YES; 
position.keyPath = @"position"; 

CAKeyframeAnimation *transform = [CAKeyframeAnimation animation]; 
transform.beginTime = 2.6; 
transform.duration = 0.25; 
transform.valueFunction = [CAValueFunction functionWithName:kCAValueFunctionRotateZ]; 
transform.values = @[@(-0.03525565),@(0.03525565),@(-0.03525565)]; 
transform.calculationMode = @"linear"; 
transform.removedOnCompletion = NO; 
transform.repeatCount = CGFLOAT_MAX; 
transform.additive = YES; 
transform.beginTime = arc4random() % 25/100.f; 
transform.keyPath = @"transform"; 

[self.dupa.layer addAnimation:position forKey:nil]; 
[self.dupa.layer addAnimation:transform forKey:nil]; 
+0

हे भगवान, मैं तुमसे प्यार करता हूँ, यह सही है – Jota

2

स्विफ्ट 4 में मूल एप्पल बजना कोड @mientus, अवधि (यानी गति), विस्थापन (यानी स्थिति परिवर्तन) को समायोजित करने के वैकल्पिक पैरामीटर और डिग्री (साथ यानी रोटेशन राशि)।

private func degreesToRadians(_ x: CGFloat) -> CGFloat { 
    return .pi * x/180.0 
} 

func startWiggle(
    duration: Double = 0.25, 
    displacement: CGFloat = 1.0, 
    degreesRotation: CGFloat = 2.0 
    ) { 
    let negativeDisplacement = -1.0 * displacement 
    let position = CAKeyframeAnimation.init(keyPath: "position") 
    position.beginTime = 0.8 
    position.duration = duration 
    position.values = [ 
     NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement)), 
     NSValue(cgPoint: CGPoint(x: 0, y: 0)), 
     NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: 0)), 
     NSValue(cgPoint: CGPoint(x: 0, y: negativeDisplacement)), 
     NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement)) 
    ] 
    position.calculationMode = "linear" 
    position.isRemovedOnCompletion = false 
    position.repeatCount = Float.greatestFiniteMagnitude 
    position.beginTime = CFTimeInterval(Float(arc4random()).truncatingRemainder(dividingBy: Float(25))/Float(100)) 
    position.isAdditive = true 

    let transform = CAKeyframeAnimation.init(keyPath: "transform") 
    transform.beginTime = 2.6 
    transform.duration = duration 
    transform.valueFunction = CAValueFunction(name: kCAValueFunctionRotateZ) 
    transform.values = [ 
     degreesToRadians(-1.0 * degreesRotation), 
     degreesToRadians(degreesRotation), 
     degreesToRadians(-1.0 * degreesRotation) 
    ] 
    transform.calculationMode = "linear" 
    transform.isRemovedOnCompletion = false 
    transform.repeatCount = Float.greatestFiniteMagnitude 
    transform.isAdditive = true 
    transform.beginTime = CFTimeInterval(Float(arc4random()).truncatingRemainder(dividingBy: Float(25))/Float(100)) 

    self.layer.add(position, forKey: nil) 
    self.layer.add(transform, forKey: nil) 
} 
संबंधित मुद्दे