4

スピニングホイールに勢いをつけるのに苦労しています。
私はこのホイール(このようなものを持っており、シングルタッチイベントを使用してホイールを中心の周りで回転させています。
ここでは問題ありませんが、タッチ(ドラッグ)が終了したとき。ホイールの勢いを維持し、動きを楽にしてほしい。

私にいくつかの指針を与えることができる人は誰でも、それは必ずしもObjective-cである必要はありません。AS3、javascript、またはJAVAでも十分です。

* UPDATE(ホイールを回転させるためのコード)*

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        rotation = _startAngle = atan2(384 - touchPoint.y, 512 - touchPoint.x);
    };

    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
        CGPoint touchPoint = [[touches anyObject] locationInView:self.view];
        rotation = atan2(384 - touchPoint.y, 512 - touchPoint.x);
        rotation = fmod(rotation - _startAngle, M_PI * 2.0f);
        [wheel setTransform:CGAffineTransformMakeRotation(_circleRotationOffset + rotation)];   
    };

    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
        _circleRotationOffset = fmod(_circleRotationOffset + rotation, M_PI * 2);
    };
4

3 に答える 3

5

摩擦のために勢いを弱めたい。摩擦は速度の関数である力です。つまり、技術的には微分方程式が進行しているのです。解決策はおそらく手で振ることでより簡単に到達できるので、それはあまり考えて投資する価値はありません。

したがって、現在の角度と現在の角速度を保存します。1秒間にn回(おそらくNSTimerまたはを介してCADisplayLink)角速度を角度に追加し、角速度に何かを掛けて、0.995などのように小さくします。1.0に近い定数を使用すると、速度が低下するまでに時間がかかります。1.0を超えると、明らかに加速します。これは事実上オイラー統合の一形態ですが、繰り返しになりますが、心配する価値はありません。

角速度に最小の上限を設定して、たとえば0.01ラジアン/秒を下回った場合に、0にスナップダウンすることも価値があります。これにより、摩擦のモデルがわずかに変更され、適切な瞬間に動摩擦から静摩擦にジャンプします。 、および浮動小数点精密緩衝地帯として機能します。

ドラッグから初速度を取得するには、ホイールの中心からドラッグの開始までのベクトルを計算し、そのベクトルを90度回転させ、それとドラッグベクトルを使用して内積を行い、距離に応じてスケーリングします。センター。

于 2012-01-16T18:18:42.813 に答える
1

私はなんとか素晴らしい結果を得ることができました。
私がそれをどのようにしたか、もっと微調整する必要がありますが、これが基本です:

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        CGPoint touchPoint = [[touches anyObject] locationInView:self.view];
        rotation = _startAngle = atan2(384 - touchPoint.y, 512 - touchPoint.x);
        [_history removeAllObjects];
    };

    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
        CGPoint touchPoint = [[touches anyObject] locationInView:self.view];
        [_history insertObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithDouble:CFAbsoluteTimeGetCurrent()], @"time", [NSValue valueWithCGPoint:touchPoint], @"point", [NSNumber numberWithFloat: _circleRotationOffset + rotation], @"rotation", nil] atIndex:0];
        if ([_history count] == 3) {
            [_history removeLastObject];
        }

        rotation = atan2(384 - touchPoint.y, 512 - touchPoint.x) - _startAngle;
        [circleImage setTransform:CGAffineTransformMakeRotation(_circleRotationOffset +         rotation)]; 
    };

    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {   
        CGPoint tp = [[touches anyObject] locationInView:self.view];
        _circleRotationOffset += rotation;

        NSDictionary *lo = [_history lastObject];
        CGPoint pp = [[lo objectForKey:@"point"] CGPointValue];
        double timeDif = CFAbsoluteTimeGetCurrent() - [[lo objectForKey:@"time"] doubleValue];
        float lastRotation = [[lo objectForKey:@"rotation"] floatValue];

        // Calculate strength
        float dist = sqrtf(((pp.x - tp.x) * (pp.x - tp.x)) + ((pp.y - tp.y) * (pp.y - tp.y)));
        float strength = MIN(1.0f, dist / 80.0f) * (timeDif / .025) * M_PI;

        float p = _circleRotationOffset;
        float dif = _circleRotationOffset - lastRotation;
        BOOL inc = dif > 0;
        if (dif > 3 || dif < -3) { // Some correction
            inc = !inc;
        }

        if (inc) {
            _circleRotationOffset += strength;  
        } else {
            _circleRotationOffset -= strength;
        }

        [circleImage.layer removeAllAnimations];
        CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
        animation.duration = MAX(strength / 2.5, 1.0f);
        animation.cumulative = YES;
        animation.repeatCount = 1;
        animation.values = [NSArray arrayWithObjects:          
                    [NSNumber numberWithFloat:p], 
                    [NSNumber numberWithFloat: _circleRotationOffset], nil]; 
        animation.keyTimes = [NSArray arrayWithObjects:    
                      [NSNumber numberWithFloat:0], 
                      [NSNumber numberWithFloat:1.0], nil]; 
        animation.timingFunctions = [NSArray arrayWithObjects:
                             [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], nil];
        animation.removedOnCompletion = YES;
        animation.delegate = self;
        animation.fillMode = kCAFillModeForwards;

        [circleImage.layer addAnimation:animation forKey:@"rotate"];
    };
于 2012-01-17T09:47:33.187 に答える
1

次のようなコードでUIImageViewを回転させている場合:これを
[UIView beginAnimations:@"rotateImage" context:nil];
[UIView setAnimationDuration:4.0];
wheelImageView.transform = CGAffineTransformMakeRotation(3.14159265*5);
[UIView commitAnimations];

使用[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
すると、アニメーションが速く始まり、時間の経過とともに遅くなり始めます。

UIViewAnimationCurveの詳細については、ここをクリックしてください

于 2012-01-16T18:28:46.040 に答える