svg로 팔다리를 그리고 합쳐보자!

Kozel·2023년 8월 9일
1
post-thumbnail
post-custom-banner

조금.. 은 지난 일이지만 드디어 svg만을 활용하여 그리니를 완성하였다.

우선 저번 글에서는 '그리니'의 소스가 없어서 직접 본따서 그렸다고 하였는데, 찾아보니 있었다!

사내 서비스 중 디자인을 제공해주는 곳을 찾아내서 그리니 소스도 어렵지 않게 받을 수 있었다.

그런데 그 소스도 이모티콘에 대한 소스만 존재하였기 때문에 그나마 표현이 덜한 이모티콘을 선택하고 각도를 조절하여 기본적인 모습을 하게 만들었다.

이제 이 그리니를 분해하면..

다음과 같이 나온다.

저번보다는 확실히 큰 뭉텅이 별로 나뉘 모습이 보이고, 퀄리티 또한 비교할 수 없을 정도로 높아졌다.

바로 아래가 저번에 기획했던 모습..

기억은 미화된다고 하지만, 이걸 만들었던 기억은 부끄럽다.
3일 정도 굶은 것 같은 그리니보고 만족했으니.. 큰 일 날뻔 했다.

아무튼, 그리니의 완성까지.. 과정을 살펴보자.


뭔가 어릴적 추억이 떠오르던 과정이었다.

딱 진짜 이런 느낌..

이젠 진짜 어떤 식으로 진행했는지 살펴보자.

1. 각각의 요소 나누기

분해한 도면을 보면 알겠지만, 원래는 좌우 상관없이 모든 요소를 그리려고 했다.

눈동자를 그리고, 흰자를 그릴 때 쯤이었나.. 좌우가 거의 차이가 없다는 것을 알았다..!

그 때 부터는 모양이 아예 다른 좌우 다리를 제외하고는 짝이 있는 요소는 하나만 그렸다.

구분하면 다음과 같다.

  1. 동공
  2. 눈 흰자
  3. 날개
  4. 버튼(모자 정수리에 있는 작은 구형 요소)
  5. 밴드
  6. 모자
  7. 왼쪽 다리
  8. 오른쪽 다리
  9. 신발

이렇게만 봐도 많다.. 보기만 해도 머리가 아팠지만 별수있나 해야지.

2. 각각의 요소 그리기

저번 글에서도 보면 알겠지만 svg의 다양한 태그 중 path 태그만 사용했다. 사실 ellipse태그도 하나 사용했다.

어쨌건 이유는 다양한 곡선을 표현하기에 적당하기 때문에.

그래서 코드를 보면 다 이런식이다.

<path d="M(시작 점) C(컨트롤1) (컨트롤2) (중간 점) C(컨트롤3) ... (컨트롤n) (끝 점)z"/>

중간 점들을 기준으로 컨트롤 포인트를 옮겨 가며 적당한 곡선을 찾아 0.1단위까지 숫자를 바꿔가며 그려나갔다.

한마디로 노가다 그 이상도 그 이하도 아니었다는 말..

실제로 어떻게 그려 나갔는지 살펴보자.

1. 동공

  • stroke-linejoin은 선이 꺾이는 부분을 곡선으로 표현할 것인지, 직선으로 표현할 것인지 정하는 속성이다.

2. 눈 흰자

역대급으로 쉬웠던 요소.. 사실 쉽다고 느낀 것은 흰자 단 하나뿐이다.

3. 날개

언뜻보면 천사의 날개같지만 그려보면 악마의 날개다.
아마 속성 값이 가장 길었던 것으로 기억한다..

왜 이 요소는 path 태그가 3개지? 하실텐데, 중간에 날개 깃 라인 2개가 추가로 삐져나와있기 때문에 따로 그려줬다.

4. 버튼

이정도야 뭐.. 귀여운 수준

5. 밴드

6. 모자

7. 왼쪽 다리

8. 오른쪽 다리

9. 신발

이렇게 까지 해준다면..!

80프로는 했다고 볼 수 있다.

3. 재사용성 고려 및 분리

막상 만들고 나니 짝이 있는 요소같은 경우는 코드를 두번 붙여쓰는 것보다 두번 불러오는 것이 이득일 것 같다는 생각이 들었다.

그래서 원래 greeny.html에 몰려있던 코드를 전부 찢어보았다.

구조를 말로 설명하자면

index.html -> greeny.html -> components 밑 요소들..

이 되겠다.

그리고 해당 요소를 greeny.html에 다음과 같이 불러모았다.

	<div id="greeny">
        <!-- 오른쪽 날개 -->
        <div id="right_wing"></div>

        <!-- 동공 -->
        <div id="group_pupil">
            <div id="left_pupil"></div>
            <div id="right_pupil"></div>
        </div>

        <!-- 눈 흰자 -->
        <div id="group_eye">
            <div id="left_eye"></div>
            <div id="right_eye"></div>
        </div>

        <!-- 버튼 -->
        <div id="topButton"></div>

        <!-- 밴드 -->
        <div id="band"></div>

        <!-- 모자 -->
        <div id="hat"></div>

        <!-- 왼쪽 날개 -->
        <div id="left_wing"></div>

        <!-- 오른쪽 다리, 신발 -->
        <div id="rightLeg"></div>
        <div id="right_shoes"></div>

        <!-- 왼쪽 다리, 신발 -->
        <div id="leftLeg"></div>
        <div id="left_shoes"></div>
    </div>

이렇게 봐도 복잡한데.. 분리하지 않았으면 어땠을까? 코드 가독성이 확 떨어졌을 것이다.

불러온 요소를 살펴보면 그룹으로 묶인 요소를 볼 수 있는데 해당 요소는 후에 모션을 적용했을 때 높을 확률로 같이 움직일 것 같은 요소이다.
동공과 눈이 왼쪽 오른쪽이 따로 움직일 가능성은.. 카멜레온이 아니라면 0?

같은 이유로 날개나 다리, 신발 같은 경우는 따로 모션을 줄 가능성이 있기 때문에 묶어두지 않았다.

물론 아직 애니메이션을 적용하지 않았기 때문에 후에 또 바뀔지도 모른다.


그런데.. 위 모아놓은 코드에서 위에서 아래로 적어놓은 요소들의 순서의 의미는 뭘까? 바로 다음에 알려주겠다.

4. 요소 합치기

위 코드에서 요소의 순서의 의미는 바로 덮여지는 역순이다.

이게 무슨소리일까.. 싶겠지만 그리니를 보면

그리니를 화면 기준 수직으로 바라보고 분해했을 때

오른쪽 날개 -> 동공 -> 흰자 -> 버튼 -> 밴드 -> 모자 -> 왼쪽 날개 -> 오른쪽 다리 -> 오른쪽 신발 -> 왼쪽 다리 -> 왼쪽 신발

의 역순으로 쌓여있을 거라는 말이다.

결론은 그냥 편하게 읽고 이해하려고 이 순서로 배치했다.


css로 우선 왼쪽 신발 부터 오른쪽 날개 순으로 'z-index' 속성을 1부터 12까지 쭉 지정해주어 화면상 덮이는 순서를 정해줬다.

그리고 id 'greeny' div 태그에는 'position: relative' 속성을, 그 자식 div 태그에는 'position: absolute' 속성을 지정하여 'greeny'태그 안에서 자유롭게 떠다니게? 해주었다.

그리고 각각의 요소에 top, left를 적당히 지정해주고.. 그룹 태그 안 요소에는 margin도 적당히 조절해주면은..

짠!

다음과 같은 그리니가 완성된다.
아주 자세히.... 보면은 미세한 차이가 있긴 하다. 만약 찾으시면.. 음.. 칭찬을..해드리겠다.

그래도 그리니의 귀여운 포인트가 잘 보존된거 같아서 꽤 흡족한 결과물이라고 생각한다.

다음은 css 코드이다.

body {
    display: flex;
    flex-direction: column;
}

#greeny {
    position: relative;
}

#greeny > div {
    position: absolute;
}

#right_wing {
    z-index: 12;
    top: 70px;
    left: 428.5px;
}
#left_wing {
    z-index: 5;
    top: 44px;
    left: 94px;
}

#group_pupil {
    z-index: 11;
    top: 339.5px;
    left: 165px;
    display: flex;
}
#right_pupil {
    margin-left: 10px;
    margin-top: 5px;
}

#group_eye {
    top: 326px;
    left: 165px;
    display: flex;
}
#right_eye {
    z-index: 10;
    margin-left: -30px;
    margin-top: 6px;
}
#left_eye {
    z-index: 9;
}

#topButton {
    z-index: 8;
    top: 193.5px;
    left: 290.5px;
}

#band {
    z-index: 7;
    top: 284px;
    left: 110px;
}

#hat {
    z-index: 6;
    top: 200px;
    left: 45px;
}

#rightLeg {
    z-index: 4;
    top: 517px;
    left: 336px;
}
#right_shoes {
    z-index: 3;
    top: 596px;
    left: 273px;
}

#leftLeg {
    z-index: 2;
    top: 554px;
    left: 242px;
}
#left_shoes {
    z-index: 1;
    top: 589px;
    left: 176px;
}

물론 이것만 봐서는 아무 의미 없다.

파일도 분리되어 있고, 파일을 불러오기 위해 js도 활용하였고.. 아무튼 자세한 코드가 궁금하신 분들은 깃헙 레포를 참고바란다.

5. 다음은?

그리니가 아주 좋게 나와줬으니.. 다음은 역시 모션, 애니메이션이 아닐까.

일단 어떤 애니메이션을, 어떤 트리거에 작동하게 할지 정해야 하기도 하고, transition은 학습했지만 아직 animation은 공부하지 않았기 때문에 당장은 구현이 어려울 것 같다.

animation을 따로 공부하는 이유는 트리거가 없어도 자동적으로 움직이는 모션들(눈 깜빡임, 날개 털기?)을 구현하기 위해서는 필수이기 때문이다.

후에 애니메이션 설계로 돌아올 생각이다.

결론

누군가 나에게 이것이 'FE개발에 도움이 될까요?' 라고 묻는다면,

음 글쎄요?

라고 답할 것이다.

현직에서 이런식으로 캐릭터를 구현할 일도 거의 없다..고 볼 수 있다.
시간도 많이 걸리고(200% 노가다), 제한도 많고.. 대부분 그래픽 툴로 재작된 소스를 통해 구현할 것이다.

그런데 왜 하고 있나?

이런 것도 해보고.. 직접 그래픽도 그려보고.. 하면 내 개발 시각이 좀 더 넓어지지 않을까? 싶은 마음이다.

그리고 아직 반에 반도 안왔다.

모션 설계도 해야하고 적당히 애니메이션 구현도 해야하고 마우스 포인터에 키보드 따라가는 시선까지.. 퍼센트로 따진다면 17% 정도 했다고 본다.

음.. 힘내자!

profile
front-end developer
post-custom-banner

4개의 댓글

comment-user-thumbnail
2023년 8월 9일

좋은 글 감사합니다. 자주 올게요 :)

1개의 답글
comment-user-thumbnail
2023년 8월 11일

구상과 구현까지 도달해가는 과정이 보기좋네요 잘 봤습니다 :)

1개의 답글