2013-03-26 12 views
10

Potrzebuję wiedzieć, w jaki sposób można skalować w dół lub w górę CGPath, aby pasował do UIView?Skalowanie CGPath do dopasowania UIVIew

Ustaw kolor tła na żółty, aby zobaczyć widok wyraźnie

self.frame = CGRectMake(0, 0, 181, 154); 
self.backgroundColor = [UIColor yellowColor]; 

Draw CAShapeLayer

CAShapeLayer *shape = [CAShapeLayer layer]; 
shape.path = aPath; 

shape.strokeColor = [[UIColor blueColor] CGColor]; 
shape.lineWidth = 5; 
shape.fillColor = [[UIColor clearColor] CGColor]; 

[self.layer addSublayer:shape]; 

Potem dostać to: enter image description here

Co chcę to: enter image description here

Dziękujemy Deweloperom :)

+0

Jak uzyskać ścieżkę w pierwszym miejsce? W zależności od tego, jak skonfigurowana jest ścieżka, może to być proste ustawienie ramki na warstwie kształtu. – DBD

+0

@DBD Użyłem tej klasy, [link] (https://github.com/arielelkin/PocketSVG) – MAMN84

Odpowiedz

25

Zakładam, że chcesz całkowicie wypełnić (bez zniekształcania) kształt, aby pasował do widoku. Zakładam również, że masz już warstwę kształtu ze ścieżką, ponieważ pytanie jest oznaczone jako CAShapeLayer.


W takim przypadku należy uzyskać ramkę ograniczającą ścieżki warstw kształtów i obliczyć odpowiedni współczynnik skali, który zostanie zastosowany do ścieżki.

W zależności od proporcji kształtu i widoku, który ma być dopasowany, będą to szerokości lub wysokości określające współczynnik skali.

Po wybraniu współczynnika skali utworzymy przekształcenie, które zostanie zastosowane do ścieżki. Ponieważ ścieżka nie może zaczynać się od (0,0), tłumaczysz również (przesuwasz) ścieżkę w transformacji do początku obwiedni.

Jeśli chcesz, aby nowa ścieżka znajdowała się pośrodku widoku, musisz obliczyć, ile go przenieść. Możesz skomentować ten kod, jeśli go nie potrzebujesz, ale umieściłem go również dla innych osób czytających tę odpowiedź.

W końcu masz nową ścieżkę, więc wszystko, co musisz zrobić, to stworzyć nową warstwę kształtu, przypisać ścieżkę, odpowiednio ją uszyć i dodać do widoku.

// I'm assuming that the view and original shape layer is already created 
CGRect boundingBox = CGPathGetBoundingBox(shapeLayer.path); 

CGFloat boundingBoxAspectRatio = CGRectGetWidth(boundingBox)/CGRectGetHeight(boundingBox); 
CGFloat viewAspectRatio = CGRectGetWidth(viewToFitIn.frame)/CGRectGetHeight(viewToFitIn.frame); 

CGFloat scaleFactor = 1.0; 
if (boundingBoxAspectRatio > viewAspectRatio) { 
    // Width is limiting factor 
    scaleFactor = CGRectGetWidth(viewToFitIn.frame)/CGRectGetWidth(boundingBox); 
} else { 
    // Height is limiting factor 
    scaleFactor = CGRectGetHeight(viewToFitIn.frame)/CGRectGetHeight(boundingBox); 
} 


// Scaling the path ... 
CGAffineTransform scaleTransform = CGAffineTransformIdentity; 
// Scale down the path first 
scaleTransform = CGAffineTransformScale(scaleTransform, scaleFactor, scaleFactor); 
// Then translate the path to the upper left corner 
scaleTransform = CGAffineTransformTranslate(scaleTransform, -CGRectGetMinX(boundingBox), -CGRectGetMinY(boundingBox)); 

// If you want to be fancy you could also center the path in the view 
// i.e. if you don't want it to stick to the top. 
// It is done by calculating the heigth and width difference and translating 
// half the scaled value of that in both x and y (the scaled side will be 0) 
CGSize scaledSize = CGSizeApplyAffineTransform(boundingBox.size, CGAffineTransformMakeScale(scaleFactor, scaleFactor)); 
CGSize centerOffset = CGSizeMake((CGRectGetWidth(viewToFitIn.frame)-scaledSize.width)/(scaleFactor*2.0), 
           (CGRectGetHeight(viewToFitIn.frame)-scaledSize.height)/(scaleFactor*2.0)); 
scaleTransform = CGAffineTransformTranslate(scaleTransform, centerOffset.width, centerOffset.height); 
// End of "center in view" transformation code 

CGPathRef scaledPath = CGPathCreateCopyByTransformingPath(shapeLayer.path, 
                  &scaleTransform); 

// Create a new shape layer and assign the new path 
CAShapeLayer *scaledShapeLayer = [CAShapeLayer layer]; 
scaledShapeLayer.path = scaledPath; 
scaledShapeLayer.fillColor = [UIColor blueColor].CGColor; 
[viewToFitIn.layer addSublayer:scaledShapeLayer]; 

CGPathRelease(scaledPath); // release the copied path 

w moim przykładzie kodu (i kształtu) wyglądało to

enter image description here

+0

Dziękuję, "centrum w widoku" naprawdę pomogło. – MAMN84

+0

Rozwiązuję podobny problem i nie miałem pojęcia, że ​​API istnieje na 'CGPath'. Milion dzięki za to! – cbowns

+0

Jesteś ratownikiem dzięki! – dbanksdesign

0

Swift 4.0 wersji Davida Rönnqvist za odpowiedź

func resizepath(Fitin frame : CGRect , path : CGPath) -> CGPath{ 


      let boundingBox = path.boundingBox 
      let boundingBoxAspectRatio = boundingBox.width/boundingBox.height 
      let viewAspectRatio = frame.width/frame.height 
      var scaleFactor : CGFloat = 1.0 
      if (boundingBoxAspectRatio > viewAspectRatio) { 
       // Width is limiting factor 

       scaleFactor = frame.width/boundingBox.width 
      } else { 
       // Height is limiting factor 
       scaleFactor = frame.height/boundingBox.height 
      } 


      var scaleTransform = CGAffineTransform.identity 
      scaleTransform = scaleTransform.scaledBy(x: scaleFactor, y: scaleFactor) 
      scaleTransform.translatedBy(x: -boundingBox.minX, y: -boundingBox.minY) 

     let scaledSize = boundingBox.size.applying(CGAffineTransform (scaleX: scaleFactor, y: scaleFactor)) 
     let centerOffset = CGSize(width: (frame.width - scaledSize.width)/scaleFactor * 2.0, height: (frame.height - scaledSize.height)/scaleFactor * 2.0) 
     scaleTransform = scaleTransform.translatedBy(x: centerOffset.width, y: centerOffset.height) 
     //CGPathCreateCopyByTransformingPath(path, &scaleTransform) 
     let scaledPath = path.copy(using: &scaleTransform) 


     return scaledPath! 
    } 
Powiązane problemy