프로그래밍/Objective-C2010. 7. 29. 09:46
* Quartz 라이브러리

  - 아이폰 OS에서 그래픽 기능을 구현하기 위한 C 라이브러리

  - 그림을 그리기 위해서는 그림을 그릴 대상인 CGContextRef가 필요하다. 그림을 그리기 위한 모든 정보를 저장하는 컨텍스트임. 그래픽카드를 추상화한 개념이라고 생각하면 된다

view : drawRect( ) -> CGContextRef에서 상속받음

  - Quartz API를 이용해 객체를 생성, 뷰가 아닌 다른 곳에 그림을 그릴 수 있다

  - 뷰에 그림을 그리기 위해서는 drawRect 메소드를 이용해서

CGContextRef 변수명 = UIGraphicsGetCurrentContext();

    와 같이 해주면 변수명이 CGContextRef 객체가 된다. 

  - touchesBegan 등에서도 그릴 수는 있다. 다만 CGContextRef가 없기 때문에 drawRect()를 빌려서 사용해야 한다


* drawRect

  - 다음과 같은 경우에 자동으로 호출된다
뷰 위를 부분적으로 덮고 있던 또 다른 뷰가 이동하거나 사라질때
숨겨져 있던 뷰의 hidden 속성을 NO로 설정해서 다시 나타나도록 했을 때
뷰를 스크린 밖으로 스크롤했다가 돌아올때
setNeedsDisplay나 setNeedsDisplayInRect를 호출했을 때

  - 패러미터
CGContextSetRGBStrokeColor(그래픽컨텍스트,R,G,B,A):선의 색상
CGContextSetLineWidth(그래픽컨텍스트, 두께)
CGContextStrokePath(그래픽 컨텍스트)
CGContextSetRGBFillColor(그래픽컨텍스트,R,G,B,A): 면색


* 작도 함수

  - 선 그리기
CGContextMoveToPoint(그래픽컨텍스트객체, x, y)
CGContextAddLineToPoint(그래픽컨텍스트객체, x, y) : 계속해서 이어서 그린다
CGContextSetLineDash(그래픽컨텍스트객체, 시작위치, 실수배열, 개수);

  - 사각형 그리기
CGContextFillRect(그래픽컨텍스트객체, CGRect 타입 변수)

  - 원 그리기
CGContextAddEllipseInRect(그래픽컨텍스트객체, CGRect 타입 변수)

  - 다각형은 선을 연속해서 그리면 됨


* 선 그리는 예제 코드(TestView.m)

#import "TestView.h"

@implementation TestView

- (id)initWithFrame:(CGRect)frame 
{
    if ((self = [super initWithFrame:frame])) 
{
        // Initialization code
    }
    return self;
}

-(IBAction)Line
{
mode = 1;
[self setNeedsDisplay];
}

-(IBAction)Rect
{
mode = 2;
[self setNeedsDisplay];
}

-(IBAction)Polygon
{
mode = 3;
[self setNeedsDisplay];
}

-(void) drawLine:(CGContextRef)context 
{
// 선 색상 설정
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

// 선 두께
CGContextSetLineWidth(context, 1.0);
// 선 그리기
CGContextMoveToPoint(context, 10.0, 30.0);
CGContextAddLineToPoint(context, 310.0, 30.0);
CGContextStrokePath(context);
CGContextSetLineWidth(context, 1.0);
// 두번째 선
CGContextSetLineWidth(context, 4.0);
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextMoveToPoint(context, 10.0, 50.0);
CGContextAddLineToPoint(context, 310.0, 50.0);
CGContextStrokePath(context);
// 점선
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGFloat dash[] = {5.0, 10.0, 15.0, 20.0};
CGContextSetLineDash(context, 0.0, dash, 4);
CGContextMoveToPoint(context, 10.0, 70.0);
CGContextAddLineToPoint(context, 310.0, 70.0);
CGContextStrokePath(context);
CGContextSetLineDash(context, 0.0, NULL, 0); // 점선을 그리게 해주는 방법
// 배열 이용하기
CGPoint lines[] =
{
CGPointMake(10.0, 90.0),
CGPointMake(60.0, 140.0),
CGPointMake(110.0, 130.0),
CGPointMake(160.0, 190.0),
CGPointMake(210.0, 200.0),
CGPointMake(260.0, 90.0),
CGPointMake(310.0, 200.0),
};
CGContextSetLineWidth(context, 5.0);
CGContextAddLines(context, lines, sizeof(lines)/sizeof(lines[0])); // 배열의 갯수 구하는 방법이지만 
                                                                                                      // 포인터 배열에서는 사용하지 말 것.
CGContextStrokePath(context);
}

-(void) drawRectangle:(CGContextRef)context 
{
// 선 색상
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

// 채우기 색
CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 1.0);
// 선 두께
CGContextSetLineWidth(context, 2.0);
// 경로에 사각형 추가
CGContextAddRect(context, CGRectMake(30.0, 30.0, 60.0, 60.0));
CGContextStrokePath(context);
// 사각형 채우기
CGContextFillRect(context, CGRectMake(130.0, 30.0, 60.0, 60.0));
CGContextStrokeRectWithWidth(context, CGRectMake(230.0, 30.0, 60.0, 60.0), 4.0);
}

-(void) drawPolygon:(CGContextRef)context 
{
CGPoint center;
// 선 색상
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

// 채우기 색
CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
// 선 두께
CGContextSetLineWidth(context, 1.0);
// 별 그리기
center = CGPointMake(80.0, 100.0);
CGContextMoveToPoint(context, center.x, center.y + 30.0);
for(int i = 1; i < 5; ++i)
{
CGFloat x = 30.0 * sinf(i * 4.0 * M_PI / 5.0); // M_PI -> Objective-C에서 매크로로 정의해둔 
        // 원주율 값
CGFloat y = 30.0 * cosf(i * 4.0 * M_PI / 5.0);
CGContextAddLineToPoint(context, center.x + x, center.y + y);
}
CGContextClosePath(context);
CGContextFillPath(context);
// 별 + 원 그리기
center = CGPointMake(160.0, 100.0);
CGContextMoveToPoint(context, center.x, center.y + 30.0);
for(int i = 1; i < 5; ++i)
{
CGFloat x = 30.0 * sinf(i * 4.0 * M_PI / 5.0);
CGFloat y = 30.0 * cosf(i * 4.0 * M_PI / 5.0);
CGContextAddLineToPoint(context, center.x + x, center.y + y);
}
CGContextAddEllipseInRect(context,CGRectMake(130, 70, 60,60));
CGContextClosePath(context);
CGContextEOFillPath(context);
// 5각형 그리기
center = CGPointMake(240.0, 100.0);
CGContextMoveToPoint(context, center.x, center.y + 30.0);
for(int i = 1; i < 6; ++i)
{
CGFloat x = 30.0 * sinf(i * 2.0 * M_PI / 6.0);
CGFloat y = 30.0 * cosf(i * 2.0 * M_PI / 6.0);
CGContextAddLineToPoint(context, center.x + x, center.y + y);
}
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
}

- (void)drawRect:(CGRect)rect 
{
CGContextRef context = UIGraphicsGetCurrentContext();
if(mode==1)
[self drawLine:context];
else if(mode==2)
[self drawRectangle:context];
else
[self drawPolygon:context];
    // Drawing code
}


* 베지어 곡선

  - CGContextAddCurveToPoint 를 이용해서 그린다

  - 3개의 좌표를 대입하게 되는데 이 좌표는 첫번째 제어점, 두번째 제어점, 종료점이다

1. 앞의 예제에 툴바 버튼을 1개 추가

2. IBAction 메소드 추가하고 앞에 만든 툴바 버튼과 연결
-(IBAction)Bazier;

3. 메소드 구현

-(IBAction)Bazier
{
mode = 4;
[self setNeedsDisplay];
}

-(void) drawBezier:(CGContextRef)context 
{
// 색상 설정
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
// 선 두께
CGContextSetLineWidth(context, 2.0);
// 원 그리기 (하단)
CGContextAddEllipseInRect(context,CGRectMake(60, 20, 200,200));
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextDrawPath(context, kCGPathFillStroke);
CGContextStrokePath(context);
// 베지어 곡선 그리기
CGPoint s = CGPointMake(60.0, 120.0);
CGPoint cp1 = CGPointMake(130.0, 230.0);
CGPoint cp2 = CGPointMake(190.0, 10.0);
CGPoint e = CGPointMake(260.0, 120.0);
CGContextMoveToPoint(context, s.x, s.y);
CGContextAddCurveToPoint(context, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y);
CGContextSaveGState(context);
// 반원 그리기 (상단)
CGContextAddArc(context,160,120,100,0,M_PI,true);
CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextDrawPath(context, kCGPathFillStroke);
CGContextStrokePath(context);
}

- (void)drawRect:(CGRect)rect 
{
CGContextRef context = UIGraphicsGetCurrentContext();
if(mode==1)
[self drawLine:context];
else if(mode==2)
[self drawRectangle:context];
else if(mode ==3)
[self drawPolygon:context];
else
[self drawBezier:context];
    // Drawing code
}


* Core Animation

  - 간단 예제
#import <QuartzCore/CAAnimation.h>
#import <QuartzCore/CAMediaTimingFunction.h>

#import "AniTest.h"


@implementation AniTest

-(IBAction)ani1 // 투명도 보
{
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"opacity"];
float from = 0.1;
float to = 1.0;
ani.fromValue = [NSNumber numberWithFloat:from];
ani.toValue = [NSNumber numberWithFloat:to];
ani.duration = 1.0;
ani.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
ani.delegate = self;
ani.autoreverses = YES;
[imgView.layer addAnimation:ani forKey:nil];
imgView.layer.opacity = 1.0;
}

-(IBAction)ani2 // 위치 보
{
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"position"];
CGPoint from = CGPointMake(50,50); 
CGPoint to = CGPointMake(250,250); 
ani.fromValue = [NSValue valueWithCGPoint:from];
ani.toValue = [NSValue valueWithCGPoint:to];
ani.duration = 1.0;
ani.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
ani.delegate = self;
ani.autoreverses = YES;
[imgView.layer addAnimation:ani forKey:nil];
imgView.layer.position = to;
}

-(IBAction)ani3 // 크기 보간
{
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"bounds"];
CGRect from = imgView.layer.bounds;
CGRect to = CGRectMake(20,20,120,120);
ani.fromValue = [NSValue valueWithCGRect:from];
ani.toValue = [NSValue valueWithCGRect:to];
ani.duration = 1.0;
ani.delegate = self;
ani.autoreverses = YES;
[imgView.layer addAnimation:ani forKey:nil];
}

-(IBAction)ani4 // 키프레임 커브 좌표 보간이동
{
CAKeyframeAnimation *ani = [CAKeyframeAnimation animationWithKeyPath:@"position"];
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath,NULL, 50,200);
CGPathAddCurveToPoint(thePath,NULL,
 100.0,50.0,
 220.0,350.0,
 270.0,200.0);
ani.path = thePath;
ani.calculationMode = kCAAnimationPaced;
ani.duration = 3.0;
ani.delegate = self;
[imgView.layer addAnimation:ani forKey:nil];
CFRelease(thePath);
}

- (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        // Initialization code
    }
    return self;
}


Posted by windship