위와 같이 선이 그려지는 그리기 애니메이션을 생성하는 방법입니다.

 

파워포인트의 나타나기 효과로는 선이 그려지는 효과를 구현하기 어렵습니다.

 

파워포인트 2019 이상에서는 새로운 그리기 메뉴가 있고  여러가지 펜 및 잉크 기능이 소개되었습니다.

 

특히 잉크를 재생할 수 있는 Ink Replay 기능이 추가되었습니다.

 

이 잉크 재생기능을 활용해서 원하는 모양대로 화면에 선을 그어주는 애니메이션을 구현해보도록 하겠습니다.

 

만약 직선을 그리려면 잉크를 그릴 때 눈금자를 대고 직접 그려줄 수 있습니다.

 

Shift-F6 으로 눈금자 모드를 켜고 Alt+방향키로 15도씩 회전할 수 있습니다.

그런데 자를 대고 선을 긋는 것은 비효율적이고 자를 회전하는 것이 무척 번거로운 작업입니다.

그래서 미리 그려진 Freeform 도형을 따라서 잉크 도형을 추가하도록 해보았습니다.

 

첨부파일(Freeform2Ink.pptm)을 파일속성에서 '차단해제'하고 매크로 허용해서 열어주세요.

 

1. 먼저 빈슬라이드의 화면에 원하는 모양의 자유형(Freeform) 도형을 그려줍니다. 그리고 도형이름은 Freeform 1로 설정합니다.

현재로서는 직선이 적절하고 90도 각도가 아니고 다른 각도의 대각선(사선)이어도 됩니다.

선의 형태는 점선이 좋겠습니다. 나중에 안보이게 숨겨도 되겠습니다.

 

 

2. 그 다음 화면 바깥에 그리기 기능을 이용해서 잉크선을 하나 그려 놓습니다. 그리고 이름은 Ink_0으로 지정합니다. 이 잉크 그리기 개체가 없으면 복사할 수 없으므로 필수적입니다. 

 

화면 바깥에 원하는 두께와 색상으로 직선 혹은 구불구불한 선으로 그려줍니다. 단색이나 화려한 무지개나 은하수색상도 가능합니다. 시작점과 끝점의 높이가 같게 만들어 주는 것이 좋습니다.

 

그리고 애니메이션에 '재생' 효과를 적용하고 시작:은 '이전 효과 다음에'로 그리고 재생시간을 0.25초~1초 등으로 설정합니다. 이 잉크선을 복사해서 자유형 도형의 node(점)을 따라서 각도와 크기를 조절해줄 예정입니다.

 

 

3.  Alt-F8을 누르고 A1_Selection2Ink 매크로를 실행합니다.

 

4. 아래와 같이 Ink_0 이라는 기본 잉크 도형이 미리 그려놓은 Freeform 도형의 노드(점)을 따라서 여러 획으로 생성되었습니다. (VBA로 Ink모양을 추가할 때 InkML 이라는 InkXML 형식으로 잉크를 추가(Shapes.AddInkFromXML)할 수 있는 것 같은데 자세한 InkML 문법이 알려져 있지 않아 일단은 이렇게 기존 잉크를 복사해서 조절하는 방식으로 해결해보았습니다.)

 

 

은하수 색깔 잉크를 사용한 결과:

 

잉크의 두께를 조절하여 필압이 있는 것처럼 표현할 수도 있습니다.

 

 

기본 잉크를 구불구불한 선으로 만들면 아래와 같은 효과도 가능합니다.

실제 재생화면:

아주 복잡한 선도 잉크 그리기 애니메이션을 적용할 수 있습니다.

 

 

재생화면

 

 

이 방법을 한글이나 영어 글씨 선에 적용하여 마치 글씨를 쓰는 것처럼 글자 획을 따라서 잉크 그리기가 재생되도록 할 수 있습니다.

 

먼저 폰트를 하나의 선으로 긋는 것처럼 단선 path로 만들어 줘야 합니다. 그 방법은 아래 링크를 참고하세요.

https://konahn.tistory.com/entry/Font2Path

 

일러스트레이터로 폰트를 선(Path)으로 바꾸기

글자를 도형으로 만드는 것은 파워포인트에서 텍스트 상자에서 빈 도형(텍스트상자)를 빼기 하면 됩니다. 일러스트레이터에서도 Image Trace를 이용하면 비트맵 그림을 도형으로 변환할 수 있습니

konahn.tistory.com

 

일러스트레이터에서 Image Trace(Line Art옵션)을 이용해서 선으로 바꾼 다음

해당 path를 복사하거나 SVG, EMF 등으로 저장해서 파워포인트에 그림으로 붙여 넣거나 불러온 다음

다시 우클릭해서 '그림 편집'을 누르고 오피스 도형으로 변환하고 그룹을 해제합니다.

 

그룹 해제 후 AutoShape 도형은 삭제해도 됩니다.

 

그 다음 모든 Freeform 도형들을 선택하고

Alt-F8을 누르고 다시 Freemform2Ink 매크로를 실행해서 선을 잉크로 변환합니다.

 

곡선을 제대로 표현하지 못하는 점이 아쉽습니다.

곡선부분을 더 세밀한 직선으로 표현한다면 좀 더 자연스럽겠습니다.

 

아래의 경우 Module2의 DrawRegPolygon 매크로를 이용해서 원(실제로는 32각형)을 자유형으로 넣고 나서 다시 잉크로 변환해보았습니다. 동그라미가 훨씬 자연스럽네요.

 

그리고 간혹 획의 방향이 오른쪽에서 시작하는 경우

일러스트레이터에서 해당 Path의 순서를 Reverse 해줘야 합니다.

아니면 파워포인트에서 간단히 도형방향을 좌우회전 시켜줘도 됩니다.

 

 

곡선 부분과 잉크 그리기 기능이 최신 버전에서만 지원된다는 점이 단점입니다.

 

 

이런 단점이 있지만

파워포인트에서 직접 그리는 듯한 애니메이션 효과를 구현할 수 있다는 점에서 의미가 있는 기능이라고 생각됩니다.

 

아울러서 오피스에서 지원되는 InkML 에 대한 더 자세한 예시와 구문 Syntax 문서가 공개, 지원되기를 바랍니다.

 

>> 재생 영상

 

 

>> 옵션 안내

Const ClearInk As Boolean = True        '기존 잉크삭제 여부

Const AdjustSpeed As Boolean = True     '잉크 애니메이션 속도를 길이에 맞게 조절
True이면 아래 기준 속도를 기준으로 길이가 길면 재생시간을 늘리지만
False로 두면 잉크 그리기 속도를 변경하지 않습니다.

Const DefaultDuration As Single = 0.5   '기본 잉크 애니메이션 시간(속도)

코드상에 eft.Timing.Duration = DefaultDuration * shp.Width / 300 이 부분에서 300을 더 낮은 숫자로 바꾸면 애니메이션 속도가 낮아지고 더 높은 숫자로 하면 애니메이션이 더 빨라집니다.

 

>> 매크로 기능

    A1_Freeform2Ink : 자유형 도형을 따라 잉크 그리기를 생성

    A2_RemoveInk: 현재 슬라이드의 모든 잉크 삭제 

    A3_DrawRegularPolygon: 원하는 각의 정다각형 생성(현재는 정32각형)

 

 

>> 핵심 코드 및 문제해결

  • 가로 직선 잉크를 Freeform의 각 노드의 각도만큼 회전시키는 부분: node1 점과 node2 점의 각도를 삼각함수로 계산
  • 회전하게 되면 기존 Left, Top 위치는 그대로인데 각도만 회전하여 보이는 Left, Top위치가 달라져서 이전 잉크선과 연결되지 않음.
  • 회전으로 인해 이동한 만큼 Left, Top 위치를 보정해줘야 함 >> 삼각함수로 계산
  • 잉크가 많아지면 약간 느려짐

 

>> VBA 코드

더보기
Option Explicit

Const Arad As Single = 57.2958
Const PI = 3.14159265358979

Const ClearInk As Boolean = True        '기존 잉크삭제 여부
Const AdjustSpeed As Boolean = True     '잉크 애니메이션 속도를 길이에 맞게 조절
Const DefaultDuration As Single = 0.5   '기본 잉크 애니메이션 시간(속도)

Sub Selection2Ink()

    Dim oShp As Shape
    Dim oRng As ShapeRange
    Dim oSld As Slide

    On Error Resume Next
    Set oSld = ActiveWindow.View.Slide
    If oSld Is Nothing Then MsgBox "No slide selected.": Exit Sub
    Set oRng = ActiveWindow.Selection.ShapeRange
    If oRng Is Nothing Then
         Set oShp = FindShape("Freeform 1")
         If oShp Is Nothing Then MsgBox "No 'Freeform' shape": Exit Sub
         oShp.Select
         Set oRng = ActiveWindow.Selection.ShapeRange
    End If
    If oRng.Count = 0 Then MsgBox "Select one or more 'Freeform' shape": Exit Sub
    On Error GoTo 0

    If ClearInk Then RemoveInk oSld
    
    For Each oShp In oRng
        If oShp.Type = msoFreeform Then If Freeform2Ink(oShp) = -1 Then Exit For
    Next oShp
    
    If AdjustSpeed Then Call AdjustInkSpeed(oSld)
    
End Sub

Function Freeform2Ink(shp As Shape) As Integer

    Dim ink As Shape, inkd As Shape
    Dim sld As Slide
    Dim n1 As ShapeNode, n2 As ShapeNode
    Dim x1!, y1!, x2!, y2!, w!, r!, x!, y!, Rad!
    Dim i As Integer

    If shp.Type <> msoFreeform Then MsgBox "The selected shape is not a Freeform": Exit Function
    
    Set sld = shp.Parent
    Set ink = FindShape("Ink_0")
    If ink Is Nothing Then MsgBox "The default ink shape(Ink_0) not found": Freeform2Ink = -1: Exit Function
        
    For i = 1 To shp.Nodes.Count - 1
        
        'duplicate the default ink
        Set inkd = ink.Duplicate(1)
        inkd.Name = "Ink_" & shp.ZOrderPosition & "_" & i
        DoEvents
        
        'get each node
        Set n1 = shp.Nodes(i)
        x1 = n1.Points(1, 1)
        y1 = n1.Points(1, 2)
        Set n2 = shp.Nodes(i + 1)
        x2 = n2.Points(1, 1)
        y2 = n2.Points(1, 2)

        'adjust the location, width and rotation of the copied ink
        w = Sqr((x2 - x1) ^ 2 + (y2 - y1) ^ 2)
        inkd.Width = w
        
        'get the rotation angle
        If x2 - x1 = 0 And y2 >= y1 Then
            r = 90
        ElseIf x2 - x1 = 0 And y2 < y1 Then
            r = 270
        Else
            r = Atn((y2 - y1) / (x2 - x1)) * Arad
            If x2 < x1 Then r = 180 + r
        End If
        inkd.Left = x1
        inkd.Top = y1
        inkd.Rotation = r
            
        Rad = (PI / 180) * r
        y = Sin(Rad) * w / 2
        x = w / 2 - Cos(Rad) * w / 2
        inkd.Left = x1 - x
        inkd.Top = y1 + y
         Debug.Print i; ; x1, y1, x2, y2, w, r, inkd.Rotation, x, y
        
    Next i
    
    Freeform2Ink = 1
    
End Function

'Ink 의 길이에 따라서 애니메이션 길이 조절
Function AdjustInkSpeed(sld As Slide)
    Dim shp As Shape
    Dim eft As Effect
    
    For Each shp In sld.Shapes
        If shp.Type = msoInkComment And shp.Name Like "Ink_*" Then
            
            Set eft = sld.TimeLine.MainSequence.FindFirstAnimationFor(shp)
            If Not eft Is Nothing Then
                eft.Timing.Duration = DefaultDuration * shp.Width / 300
            End If
        
        End If
    Next shp
    
End Function

'remove all of the old ink shapes
Function RemoveInk(oSld As Slide)
    
    Dim i As Long
   
    For i = oSld.Shapes.Count To 1 Step -1
        If oSld.Shapes(i).Name Like "Ink_*" And oSld.Shapes(i).Name <> "Ink_0" Then _
            oSld.Shapes(i).Delete
    Next i
 
End Function

'find and return the shape with the given name
Function FindShape(shpName As String) As Shape

    Dim oSld As Slide
    Dim oShp As Shape
    
    Set oSld = ActiveWindow.View.Slide
    For Each oShp In oSld.Shapes
        If oShp.Name Like shpName Then
            Set FindShape = oShp
            Exit For
        End If
    Next oShp
    
End Function

 

>> 샘플 포함 VBA 파일

Freefrom2Ink1.pptm
0.39MB

 

 

>> 관련: 지식인