Ser Pounce
Ser Pounce

Reputation: 14571

How to correctly position graphic after flipping it

For the following lightning bolt graphic:

enter image description here

I'm trying to flip it while scaling like such:

CGAffineTransform transform = CGAffineTransformMakeScale(newSize.width / initialSize.width, -1 * (newSize.height / initialSize.height));
CGMutablePathRef mutablePath = CGPathCreateMutableCopyByTransformingPath(shapeLayer.path, &transform);
shapeLayer.path = mutablePath;
CGPathRelease(mutablePath);

This is what happens:

enter image description here

I've tried a bunch of different ways to translate it but to no success:

CGAffineTransform transform = CGAffineTransformMakeTranslation(newSize.width / 2, newSize.height / 2);
transform = CGAffineTransformScale(transform, newSize.width / initialSize.width, -1 * (newSize.height / initialSize.height));
transform = CGAffineTransformTranslate(transform, -newSize.width / 2, -newSize.height / 2);

Does anyone know the correct way to get my graphic back into the bounding box of the view?

Upvotes: -1

Views: 47

Answers (2)

Ser Pounce
Ser Pounce

Reputation: 14571

Matt's response pushed me in the right direction and this is ultimately how I was able to solve the problem:

CGAffineTransform transform = CGAffineTransformMakeScale(newSize.width / initialSize.width, newSize.height / initialSize.height);
            
if (flipped)
{
    transform = CGAffineTransformTranslate(transform, 0, initialSize.height / 2.0);
    transform = CGAffineTransformScale(transform, 1, -1);
    transform = CGAffineTransformTranslate(transform, 0, -initialSize.height / 2.0);
}

Upvotes: 0

matt
matt

Reputation: 535964

It's unclear what you're trying to do, and you have not supplied sufficient code even to generate the interface you've pictured, let alone to discover what the issue may be. However, the simplest thing is probably to transform the shape layer, not the path. The following code draws a non-symmetric shape in the center of the screen, and then flips it horizontally and enlarges it, operating round its center, so that it still in the center of the screen:

let shape = CAShapeLayer()
shape.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
let path = UIBezierPath()
path.move(to: .zero)
path.addLine(to: .init(x: 0, y: 100))
path.addLine(to: .init(x: 100, y: 100))
shape.path = path.cgPath
self.view.layer.addSublayer(shape)
shape.frame.origin = CGPoint(
    x: view.bounds.width / 2 - 50, 
    y: view.bounds.height / 2 - 50
)

let newsize = 1.5
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    shape.transform = CATransform3DMakeScale(-newsize, newsize, 0)
}

If you insist upon transforming the path, then the transform takes place around the origin (the top left), so you would need to move the center of the path to the origin, perform the scale transform, then move the center of the path back to the center.

let shape = CAShapeLayer()
shape.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
let path = UIBezierPath()
path.move(to: .zero)
path.addLine(to: .init(x: 0, y: 100))
path.addLine(to: .init(x: 100, y: 100))
shape.path = path.cgPath
self.view.layer.addSublayer(shape)
shape.frame.origin = CGPoint(
    x: view.bounds.width / 2 - 50, 
    y: view.bounds.height / 2 - 50
)

let newsize = 1.5
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    path.apply(CGAffineTransform(translationX: -50, y: -50))
    path.apply(CGAffineTransform(scaleX: -newsize, y: newsize))
    path.apply(CGAffineTransform(translationX: 50, y: 50))
    shape.path = path.cgPath
}

Upvotes: 1

Related Questions