NSImageView is hoping when from the location when

2020-05-01 09:00发布

I am rotating an NSImageView from its center which is working perfectly however when I start the animation the NSImageView hops from its location to a random location. I do not know why is it happening. Please help.

I am elaborating how I am doing it all. Also, I am providing a Github link so that you may run it if you want.

github project link

Code:

// on button press animation will be started
-(void)buttonPressed:(id)sender{

    // setting the anchor point of the view
    _img.layer.anchorPoint = CGPointMake(0.5f, 0.5f);

    // calling the animation function
    [self startRefreshAnimation];
}

// in order to repeate the animation
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    [self startRefreshAnimation];
}

// the function that will handel all the animation stuff
-(void)startRefreshAnimation {

    CABasicAnimation *anim2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    anim2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

    NSNumber* toValue = [NSNumber numberWithFloat:0 * (M_PI / 180.0f)];
    NSNumber* fromValue = [NSNumber numberWithFloat:(360.0f) * (M_PI / 180.0f)];


    anim2.fromValue = toValue;
    anim2.toValue = fromValue;


    anim2.duration = 1.0f;
    anim2.delegate = self;
    [_img.layer addAnimation:anim2 forKey:@"transform"];
}

3条回答
我只想做你的唯一
2楼-- · 2020-05-01 09:29

The code looks fine to me for the animation task u require. Just move the anchorPoint line, like this:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application

    _img.layer.anchorPoint = CGPointMake(0.5f, 0.5f);   
}

EDIT: Basically, the position of a layer is specified in terms of the location of the layer's anchorPoint. When you set the position of the layer, you are then setting the location of the center of the layer in its superlayer's coordinate system. Because the position is relative to the anchorPoint of the layer, changing that anchorPoint while maintaining the same position moves the layer. So, you will have to set the anchorPoint before rendering the subview.


Also, for infinite repeat, you can avoid writing animationDidStop method, by using this property:

anim2.repeatCount = HUGE_VALF;
查看更多
一夜七次
3楼-- · 2020-05-01 09:29

Set the anchor of the layer so that it rotates around the correct centre, then immediately re-position it to account for the new anchor point (otherwise it will change its position):

    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
    rotateAnimation.toValue = CGFloat(-M_PI * 2.0)
    rotateAnimation.duration = 1.0

    viewToRotate.layer?.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    viewToRotate.layer?.position = viewToRotate.center

    viewToRotate.layer?.addAnimation(rotateAnimation, forKey: nil)

With...

extension NSView {
var center: CGPoint {
    get {
        return CGPointMake(NSMidX(self.frame), NSMidY(self.frame))
    }
}
查看更多
Viruses.
4楼-- · 2020-05-01 09:36

You need to set the position of the layer, on the Image View. Add this in the buttonPressed method:

//Position of the imgView
CGRect frame = _img.layer.frame;

float xCoord = frame.origin.x + frame.size.width;
float yCoord = frame.origin.y + frame.size.height;

CGPoint myPoint = CGPointMake(xCoord, yCoord);
_img.layer.position = myPoint;

[self startRefreshAnimation]

that way, you can move the imageView around in the .xib, and the animation will take place the correct spot.

Edit: The solution by @Nishant is so much prettier..

查看更多
登录 后发表回答