직선
직선을 그리기 위해서는 lineTo 메소드를 사용합니다.

lineTo(x, y)

이 메소드는 x,y 두가지 인자를 포함하는데. 이 좌표는 직선의 끝점을 나타냅니다.
현재 위치로부터 x,y 좌표까지의 직선을 그려주는 겁니다.

시작점을 바꾸기 위해서는 앞서 살펴보았던 moveTo 메소드를 이용하면 됩니다.

  1. // Filled triangle  
  2. ctx.beginPath();  
  3. ctx.moveTo(25,25);  
  4. ctx.lineTo(105,25);  
  5. ctx.lineTo(25,105);  
  6. ctx.fill();  
  7.   
  8. // Stroked triangle  
  9. ctx.beginPath();  
  10. ctx.moveTo(125,125);  
  11. ctx.lineTo(125,45);  
  12. ctx.lineTo(45,125);  
  13. ctx.closePath();  
  14. ctx.stroke();  

위의 코드를 살펴보면 두개의 삼각형을 그리는 path도형인데요.
첫번째는 내부가 꽉찬 삼각형, 두번째는 내부가 비어있는 삼각형을 그리도록 되어있습니다.

주의할점은 라인을 2개만 사용하여 삼각형을 그렸다는건데요 앞서 살펴보았던 fill 메소드의 특성상
closePath메소드를 사용하지 않아도 자동적으로 도형을 완성시켜줍니다.

시작점과 마지막까지 그린점을 직선으로 이어주어 두개의 선으로 완전한 하나의 도형을 완성시켜주는셈입니다
[사진출처]모질라 캔바스 튜토리얼

물론 라인을 두개만 사용하지않고 끝까지 그려서 완성시켜주셔도 무방합니다.
path도형을 그리기 위해서 우리는 몇가지 단계가 필요합니다.

beginPath()
closePath()
stroke()
fill()

path도형을 그리기 위한 첫번째 단계로는 beginPath 메소드를 부르는것입니다.
내부적으로 path도형은 라인,원 등으로 구성된 하위 paths의 목록으로 구성됩니다.
이 메쏘드가 호출될때마다 목록은 초기화 되고 새로운 도형그리기를 시작할수가 있습니다.

두번째단계는 실제로 경로를 지정하는 함수를 호출합니다.

세번째 단계는 선택적인 단계인데 , closePath함수를 호출하는것입니다.
이 함수는 현재 상태에서 직선거리로 도형을 완성하려 할것입니다.
만약 도형이 이미 완성되어있거나 리스트에 한점밖에 그리지 않았다면
이 함수는 아무것도 동작하지 않습니다.

마지막단계는 stroke또는 fill 메소드를 부르는 겁니다.
둘중 한 메소드를 사용하게되면 실제 캔버스에 도형을 그리게 됩니다. 
stroke 는 도형의 아웃라인을 그리는데 사용 하고 fill 은 도형은 한가지 색으로 채우는데 
사용됩니다.

note : fill메소드를 사용하게되면 closePath메소드를 사용하지 않았더라도 도형이 완성됩니다.

간단히 삼각형을 그리기 위해서는 다음과같은 순서를 사용하면 됩니다.


  • ctx.beginPath();  
  • ctx.moveTo(75,50);  
  • ctx.lineTo(100,75);  
  • ctx.lineTo(100,25);  
  • ctx.fill(); 

  • moveTo
    매우 유용한 함수중에 하나인 moveTo 함수는 사실 아무것도 그리지 않는 함수입니다.
    하지만 이 함수는 리스트에서 도형을 그리는 위치를 옮겨주는 기능을 가지고있기에
    매우 중요합니다.

    이 함수는 두가지 인수를 받아 사용하는데 새로운 그림 시작 좌표를 x,y로 받습니다.

    beginPath 메쏘드가 불려지거나 캔버스가 초기화 되었을때 시작점은 좌표 0,0로 셋팅됩니다.
    대부분의 경우 moveTo 함수는 시작점을 어딘가 다른곳으로 옮길때 사용되며.
    도형과 연결되지않은 임의의 점으로도 이동이 가능합니다.
    아래의 이미지를 보시면 스마일을 그릴때 moveTo 함수로 이동하는 부분을 붉은라인으로
    표시하였습니다.
    [출처] 모질라 디벨로퍼 센터

    1. ctx.beginPath();  
    2. ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle  
    3. ctx.moveTo(110,75);  
    4. ctx.arc(75,75,35,0,Math.PI,false);   // Mouth (clockwise)  
    5. ctx.moveTo(65,65);  
    6. ctx.arc(60,65,5,0,Math.PI*2,true);  // Left eye  
    7. ctx.moveTo(95,65);  
    8. ctx.arc(90,65,5,0,Math.PI*2,true);  // Right eye  
    9. ctx.stroke();  
    그리드 

    도형을 그리기전에 우리는 먼저 캔버스의 그리드 혹은 좌표공간에대해서 이해할 필요가 있습니다.
    html의 기본 캔버스는 150*150 사이즈를 가진다고 이전에 설명하였습니다.
    우리가 알고있는 일반적인 수학의 2차원 평면은 가로 세로 (편의상 X Y 라고 하겠습니다.) 축을 가지고있고
    시작점은 좌측 하단에 위치해 있습니다만. 
    html의 기본 좌표는 화면의 좌측 상단에 시작점을 가지고 있습니다. 
    아래의 이미지를 보시면 이해가 쉬우실것같습니다.

    [출처] 모질라 디벨로퍼 센터

    위의 특이점만 이해하신다면 화면상의 좌표 계산에는 큰 어려움이 없겠습니다.

    도형그리기

    SVG와 다르게 캔버스는 매우 원시적인형태인 사각형 도형만을 지원합니다. 다른 도형들은 하나이상의
    경로들을 조합하여 만들어야만하지요. 
    하지만 다행스럽게도 우리는 이런 복잡한 도형들을 그리기위한 많은 다양한 함수들을 가지고 있습니다.


    사각형

    사각형을그려보기전에 먼저 세가지 함수를 살펴보도록 하겠습니다.

    fillRect(x,y,width,height) : 색칠된 사각형을 그립니다.
    strokeRect(x,y,width,height) : 사각형태의 아웃라인을 그립니다.
    clearRect(x,y,width,height) : 특정영역을 완전히 투명하게 지웁니다.

    세가지 함수는 각각 같은 파라메터를 가지고있습니다 x,y 는 위에서 설명한 캔버스 좌상단을 원점으로한
    좌표를 말하고 width, height는 각 사각형의 크기를 말해줍니다.

    그럼 세가지 함수를 사용하는 간단한 예제를 보도록 하겠습니다.


    1. function draw(){  
    2.   var canvas = document.getElementById('canvas');  
    3.   if (canvas.getContext){  
    4.     var ctx = canvas.getContext('2d');  
    5.   
    6.     ctx.fillRect(25,25,100,100);  
    7.     ctx.clearRect(45,45,60,60);  
    8.     ctx.strokeRect(50,50,50,50);  
    9.   }  
    10. }  

    먼저 fillRect함수로 까만 100*100 사이즈의 검은사각형을 그려주었습니다.
    그리고 clearRect 함수로 검은 사각형의 내부에 60*60 사이즈만큼 배경을 지워준뒤에
    그안에 50*50 사이즈의 사각형 라인을 그려넣은겁니다.

    1. <html>  
    2.  <head>  
    3.   <script type="application/javascript">  
    4.     function draw() {  
    5.       var canvas = document.getElementById("canvas");  
    6.       if (canvas.getContext) {  
    7.         var ctx = canvas.getContext("2d");  
    8.   
    9.         ctx.fillStyle = "rgb(200,0,0)";  
    10.         ctx.fillRect (10, 10, 55, 50);  
    11.   
    12.         ctx.fillStyle = "rgba(0, 0, 200, 0.5)";  
    13.         ctx.fillRect (30, 30, 55, 50);  
    14.       }  
    15.     }  
    16.   </script>  
    17.  </head>  
    18.  <body onload="draw();">  
    19.    <canvas id="canvas" width="150" height="150"></canvas>  
    20.  </body>  
    21. </html>  

    미리보기

    간단한 설명을 하자면 

    캔버스를 만들고 그곳에 2d컨텍스트를 받아온뒤

    fillStyle 메소드와 fillRect 메소드를 이용하여 빨간색과 파란색 사각형을 그려주는 예제입니다.

    각각의 메소드에 관해서는 각자 자료를 찾아보거나 한국HTML5그룹 api 게시판에서 차후에 정리하여

    올릴계획입니다.


    위의 사각형은 범위의 일부분이 겹치게 되는데요.

    속성에따라 겹치는 부위가 위로 올라가거나 아래로 내려가거나 겹치는 부분만 비울수도 있고

    여러가지 변수가 존재하지만 해당내용은 다음번 강좌에서 다루도록 하겠습니다.

    위의 소스를 실행해보시면 두가지 영역이 겹치는 곳은 색이 합쳐지도록 되어있습니다.

    '모바일 WEB 관련 > HTML5' 카테고리의 다른 글

    [Canvas] canvas 6. path도형 그리기  (0) 2011.01.08
    [Canvas] canvas 5. 도형 그리기  (0) 2011.01.08
    [Canvas] canvas 3. getContext  (0) 2011.01.08
    [Canvas] canvas 2. 기본사용법.  (2) 2011.01.08
    [Canvas] canvas 1. 소개  (0) 2011.01.08

    캔바스는 여러가지  랜더링이 존재하는데 그중에 우리는 현재 정의가 어느정도 된 2D랜더링 부분에 대해서 집중하고자 합니다.

    물론 차후에는 좀더 다양한 종류의 렌더링이 지원될것인데, 예를들면 OpenGL 에 기반한 3D컨텍스트 등이 준비중입니다.


    canvas는 기본적으로 비어있는데 이를 사용하기 위해서 우리는 스크립트로 canvas에 접근할 필요성이 있습니다.

    canvas엘리먼트에는 그림그리는데 필요한 기능을 가진 getContext 라는 DOM 메소드가 존재합니다.

    1. var canvas = document.getElementById('tutorial');  
    2. var ctx = canvas.getContext('2d');  

    위의 예제에서 우리는 tutorial 이라는 id를 가진 canvas 를 DOM 노드를 이용해 접근하였고 

    해당객체에서 getContext 메쏘드를이용해 2d 컨텍스트에 접근하였습니다.


    지원확인

    1. var canvas = document.getElementById('tutorial');  
    2. if (canvas.getContext){  
    3.   var ctx = canvas.getContext('2d');  
    4.   // drawing code here  
    5. else {  
    6.   // canvas-unsupported code here  
    7. }  

    getContext 메쏘드를 확인하는것으로 간단하게 현재 브라우저가 지원하는 지 아닌지 여부를 판단할수있습니다.

    간단 템플릿

    1. <html>  
    2.   <head>  
    3.     <title>Canvas tutorial</title>  
    4.     <script type="text/javascript">  
    5.       function draw(){  
    6.         var canvas = document.getElementById('tutorial');  
    7.         if (canvas.getContext){  
    8.           var ctx = canvas.getContext('2d');  
    9.         }  
    10.       }  
    11.     </script>  
    12.     <style type="text/css">  
    13.       canvas { border: 1px solid black; }  
    14.     </style>  
    15.   </head>  
    16.   <body onload="draw();">  
    17.     <canvas id="tutorial" width="150" height="150"></canvas>  
    18.   </body>  
    19. </html> 

    미리보기

    위의 코드를 실행해보면 간단한 박스가 나타나는것을 볼수있습니다.

    캔버스를 사용하는 뼈대라고 볼수 있습니다. 캔버스를 생성하고. 스크립트로 컨텍스트를 받아왔으며, 간단한

    스타일시트로 스타일도 주었습니다. 

    앞으로 사용하게될 많은 캔버스들이 이 기본구조를 크게 벗어나지는 않을것입니다.

    '모바일 WEB 관련 > HTML5' 카테고리의 다른 글

    [Canvas] canvas 6. path도형 그리기  (0) 2011.01.08
    [Canvas] canvas 5. 도형 그리기  (0) 2011.01.08
    [Canvas] canvas 4. 간단한예제  (0) 2011.01.08
    [Canvas] canvas 2. 기본사용법.  (2) 2011.01.08
    [Canvas] canvas 1. 소개  (0) 2011.01.08

    기본사용법.

    <canvas id="tutorial" width="150" height="150"></canvas>

    캔바스는 기본적으로 위와같이 사용하게 됩니다. 

    HTML 엘레멘트 공통인 ID attribute를 빼면 width , height 두가지 요소만 가지고 있는 셈입니다.

    가로세로 크기를 지정하지않으면 기본적으로 300*150의 공간을 가지고 있고

    자바스크립트,CSS어느것으로도 쉽게 캔버스를 컨트롤 할수있습니다.

    CSS로는 일반적인 이미지 태그처럼 추가적인 각종 스타일을 지정할수 있습니다.(margin,border,background 등등)


    대체 속성

    canvas는 기본적으로 지원하는 브라우저가 아직까지는 일반적이지는 않기때문에 지원하지 않는 브라우저를위해

    아주 간단하게 대체 문구나 이미지등을 삽입 할수 있게 되어 있습니다.

    1. <canvas id="stockGraph" width="150" height="150">  
    2.   current stock price: $3.15 +0.15  
    3. </canvas>  
    4.   
    5. <canvas id="clock" width="150" height="150">  
    6.   <img src="images/clock.png" width="150" height="150" alt=""/>  
    7. </canvas>  

    위의 두가지 canvas 요소들은 각각 canvas를 지원하지 않는 브라우저에서 보았을경우

    current stock price: $3.15 +0.15 

    이런텍스트를 출력하거나

    <img src="images/clock.png" width="150" height="150" alt=""/>

    이런 이미지를 출력하게 됩니다. 


    그리고 당연한 얘기지만. 대체속성이 필요없다고 하더라도 </canvas>는 항상 붙여야 합니다.

    '모바일 WEB 관련 > HTML5' 카테고리의 다른 글

    [Canvas] canvas 6. path도형 그리기  (0) 2011.01.08
    [Canvas] canvas 5. 도형 그리기  (0) 2011.01.08
    [Canvas] canvas 4. 간단한예제  (0) 2011.01.08
    [Canvas] canvas 3. getContext  (0) 2011.01.08
    [Canvas] canvas 1. 소개  (0) 2011.01.08

    canvas는 스크립트를 사용해서 그래픽등을 컨트롤 할수있는 새로운 HTML엘레멘트 입니다.

    그림이나 사진 간단한 애니매이션들을 표현할수있습니다.


    canvas는 처음  Apple for the Mac OS X Dashboard 에서 소개되었고 그 이후

    사파리 , 겍코기반브라우저 등에서 지원하기 시작하였으며 HTML5로 잘 알려진 

    WhatWG Web applications 1.0 의 일부에 포함되어 있습니다.


    canvas는 html과 자바스크립트에대한 어느정도의 지식을 갖춘사람은 큰 어려움없이 접할수 있습니다.


    현재 canvas는 파이어폭스1.5이상,오페라9,사파리,구글크롬, 겍코기반브라우저 등에서 동작합니다.

    (IE는 9버젼부터 지원예정입니다)

    /**
     *  @file SurfaceView.h
     *  A View that implements a CoreSurface buffer
     *  The buffer is created automatically in initWithFrame: with the size
     *  passed to it and 5-6-5 RGB format.
     *  The memory can be accessed with the pixels property, and after modifying
     *  it you must call setNeedsDisplay on it for it to update.
     */
     
    #import <UIKit/UIKit.h>
    #import <CoreSurface/CoreSurface.h>
     
    @interface SurfaceView : UIView
    {
        CALayer *surfaceLayer;
        unsigned short *pixels;
        CoreSurfaceBufferRef surfaceBuffer;
    }
     
    @property (nonatomic, readonly) unsigned short *pixels;
     
    @end
     
     
     
    /**
     *  @file SurfaceView.m
     *  Implementation of SurfaceView
     */
     
    #import "SurfaceView.h"
     
    @implementation SurfaceView
     
    - (id)initWithFrame:(CGRect)frame {
        frame.origin.x /= 2;
        frame.origin.y /= 2;
       
        if (self = [super initWithFrame:frame]) {
            // Create Surface
            int w = frame.size.width, h = frame.size.height;
            surfaceBuffer = CoreSurfaceBufferCreate((CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
                [NSNumber numberWithInt:w],         kCoreSurfaceBufferWidth,
                [NSNumber numberWithInt:h],         kCoreSurfaceBufferHeight,
                [NSNumber numberWithInt:'L565'],    kCoreSurfaceBufferPixelFormat,
                [NSNumber numberWithInt:2*w*h],     kCoreSurfaceBufferAllocSize,
                [NSNumber numberWithBool:YES],      kCoreSurfaceBufferGlobal,
                [NSNumber numberWithInt:2*w],       kCoreSurfaceBufferPitch,
                @"PurpleGFXMem",                    kCoreSurfaceBufferMemoryRegion,
                nil]);
           
            // Create layer for surface
            CGRect frame2 = CGRectMake(frame.origin.x, frame.origin.y,
                                       frame.size.width+1, frame.size.height+1);
            CoreSurfaceBufferLock(surfaceBuffer, 3);
            surfaceLayer = [[CALayer layer] retain];
            [surfaceLayer setMagnificationFilter:0];
            [surfaceLayer setEdgeAntialiasingMask:0];
            [surfaceLayer setFrame:frame2];
            [surfaceLayer setContents:surfaceBuffer];
            [surfaceLayer setOpaque:YES];
            [[self _layer] addSublayer:surfaceLayer];
            CoreSurfaceBufferUnlock(surfaceBuffer);
           
            // Get base address
            pixels = CoreSurfaceBufferGetBaseAddress(surfaceBuffer);
        }
        return self;
    }
     
    - (void)dealloc {
        [surfaceLayer release];
        [super dealloc];
    }
     
    - (void)drawRect:(CGRect)rect {
        // It will break if you remove this empty function
    }
     
    - (unsigned short*)pixels {
        return pixels;
    }
    @end

    /** 
     *  @file SurfaceView.h
     *  A View that implements a CoreSurface buffer
     *  The buffer is created automatically in initWithFrame: with the size
     *  passed to it and 5-6-5 RGB format.
     *  The memory can be accessed with the pixels property, and after modifying
     *  it you must call setNeedsDisplay on it for it to update.
     */
     
    #import <UIKit/UIKit.h>
    #import <CoreSurface/CoreSurface.h>

    @interface SurfaceView : UIView 
    {
        CALayer *surfaceLayer;
        unsigned short *pixels;
        CoreSurfaceBufferRef surfaceBuffer;
    }

    @property (nonatomic, readonly) unsigned short *pixels;

    @end



    /** 
     *  @file SurfaceView.m
     *  Implementation of SurfaceView
     */
     
    #import "SurfaceView.h"

    @implementation SurfaceView

    - (id)initWithFrame:(CGRect)frame {
        frame.origin.x /= 2;
        frame.origin.y /= 2;
        
        if (self = [super initWithFrame:frame]) {
            // Create Surface
            int w = frame.size.width, h = frame.size.height;
            surfaceBuffer = CoreSurfaceBufferCreate((CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
                [NSNumber numberWithInt:w],         kCoreSurfaceBufferWidth,
                [NSNumber numberWithInt:h],         kCoreSurfaceBufferHeight,
                [NSNumber numberWithInt:'L565'],    kCoreSurfaceBufferPixelFormat,
                [NSNumber numberWithInt:2*w*h],     kCoreSurfaceBufferAllocSize,
                [NSNumber numberWithBool:YES],      kCoreSurfaceBufferGlobal,
                [NSNumber numberWithInt:2*w],       kCoreSurfaceBufferPitch,
                @"PurpleGFXMem",                    kCoreSurfaceBufferMemoryRegion,
                nil]);
            
            // Create layer for surface
            CGRect frame2 = CGRectMake(frame.origin.x, frame.origin.y, 
                                       frame.size.width+1, frame.size.height+1);
            CoreSurfaceBufferLock(surfaceBuffer, 3);
            surfaceLayer = [[CALayer layer] retain];
            [surfaceLayer setMagnificationFilter:0];
            [surfaceLayer setEdgeAntialiasingMask:0];
            [surfaceLayer setFrame:frame2];
            [surfaceLayer setContents:surfaceBuffer];
            [surfaceLayer setOpaque:YES];
            [[self _layer] addSublayer:surfaceLayer];
            CoreSurfaceBufferUnlock(surfaceBuffer);
            
            // Get base address
            pixels = CoreSurfaceBufferGetBaseAddress(surfaceBuffer);
        }
        return self;
    }

    - (void)dealloc {
        [surfaceLayer release];
        [super dealloc];
    }

    - (void)drawRect:(CGRect)rect {
        // It will break if you remove this empty function
    }

    - (unsigned short*)pixels {
        return pixels;
    }
    @end
    * 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;
    }


    + Recent posts