기본 콘텐츠로 건너뛰기

SVG의 path tag 에 대해 araboja

시작은 SVG에서 호(弧:arc)를 그리는 것에서 비롯하였다.
SVG는 정비율 원인 circle 과 ellipse는 있는데 arc 가 따로 있는 건 아니다.
pie graph 류를 그릴 땐 꼭 필요한데 path 말곤 뾰족한 수가 없어 보인다.

뭐 이렇게 된거 path 에 대해 전부 다 알아보도록 하자.

path는 "명령 숫자 숫자 ..."의 조합인데 각각 의도에 맞는 명령(M,L,H,V,Z,C,S,Q,T,A)와 거기에 맞는 인자들을 잘 넣어서 한방에 그릴 수 있게 한다.
참고로, 각각의 커맨드를 소문자로 쓰면 상대 좌표계로 바뀐다. 인자가 없는 Z의 경우는 어느쪽이던 똑같다.
그냥 생각해봐도 일일이 line 으로 모든 걸 다 그리는 건 비효율적이긴 하다.
어짜피 이런 건 아는 것 보다 "하는" 것이 중요하니까 한번 직접 크롬 개발 환경이라도 열고 해보는 게 좋다.


  1. 이동 명령 (M)
  2. 직선 명령 (L, H, V)
    1. L x y - 현재 점에서 x,y 까지 직선을 긋는다.
    2. H x - 현재 점에서 x 위치까지 가로로 직선을 긋는다.
    3. V y - 현재 점에서 y 위치까지 세로로 직선을 긋는다.
  3. 폐쇄 명령 (Z) - 맨 처음 점으로 되돌아가게끔 직선을 그어 닫힌 면을 만든다.
    인자 없는 것이 특징.
  4. 곡선명령 (C,S,Q,T)
    1. C x1 y1, x2 y2, x y - 현재 점에서 x,y 까지 직선을 그은 것을 Bezier 곡선을 만든다. 현재 점에서 x1,y1만큼, x,y 에서 x2,y2 만큼 핸들을 사용한다.
      c 즉 상대좌표일 때 주의할 점은 x2 y2는 x,y 기준이 아니라 현재 점 기준.
    2. S x2, y2, x y - 이전의 핸들을 연장한다. 아래의 경우를 비교해보자. 둘은 완전히 같은 형태의 곡선을 그리지만 S를 쓰는 쪽이 인자가 하나 적다.
      <path d="M100 500 C 150 400, 200 500, 200 500 C 250 600, 300 500, 300 500"/>
      <path d="M100 600 C 150 500, 200 600, 200 600 S 250 700, 300 600"/>
    3. Q x1 y1, x y - C와는 다른 타입(Quadratic curve)이다. 곡선이 x1,y1 점을 지나는 점을 유의하여 보자.
      <path d="M50 600 Q 100 500, 150 600 Q 200 700 250 600"/>
    4. T x y - S와 마찬가지로 연장하는 커맨드. Q의 x1 y1을 생략하였다.
      <path d="M50 600 Q 100 500, 150 600 Q 200 700 250 600"/>
      <path d="M50 700 Q 100 600, 150 700 T 250 700"/>
      둘은 완전히 같은 곡선
  5. Arc 호
    A rx ry x-axis-rotation large-arc-flag sweep-flag x y
    이거 이야기 하려고 밑밥을 너무 깔았다. C,S,Q,T에 대해선 너무 대충 이야기 한 감이 좀 있는데 사실 나도 잘 모른다. 그어보다 보니 감각적으로 알게된 것은 있는데 정확하게는 수학을 건들지 않고 이야기할 수 없을 것 같다.

    여튼 A를 자세히 보아야한다. 이건 Bezier Curve 가 아니다.
    1. rx, ry, x, y
      중요한 부분은 rx ry 와 x y는 ellipse 와 완전히 같다.
      rx ry는 분명하다. 가로측 반지름과 세로측 반지름.
      x y가 조금 이상하다 싶은데
      <path d="M 250 100 A 50 50 0 0 0 350 100"></path>
      실제로 그려보면 이런 형태가 된다.
      이전 점인 250,100 에서 출발하여 rx, ry만큼 크기인 호를 350,100까지 그린다.
    2. sweep-flag
      여기서 주목해야할 점은 sweep-flag 인데 0 일 경우 반시계 방향 1일 경우 시계 방향으로 그린다.
      즉,
      <path d="M 250 100 A 50 50 0 0 0 350 100"></path>
      <path d="M 250 100 A 50 50 0 0 1 350 100"></path>
      이럴 경우
      <ellipse rx="50" ry="50" cx="300" cy="100" />
      와 완전히 같다.
      원의 중심인 cx, cy 대신 실제 선이 지나가는 위치인 x y를 사용한 점을 주목하자.
    3. large-arc-flag
      또 다른 flag 인 large-arc-flag 도 보자.
      만일 호의 일부를 그리기 위해
      <path d="M 400 100 A 50 50 0 0 0 450 150"></path>
      이런 식으로 한다면 어떨까? 400,100 으로부터 50, 50 만큼 떨어진 450, 150 까지 그리는 것이므로 1/4 호를 그릴 수 있다.
      large-arc-flag 를 1로 설정하면 반대 방향으로 크게 돌아 그리는 것을 볼 수 있다.
      마치 팔이 길어서 오른손으로 왼쪽 목을 돌려치는 박진영씨 같은 형국이라고 보면 되겠다.

      ...라고 본인은 부인하시긴 하지만 (죄송)
      두 개의 호의 sweepflag 와 large-arc-flag 가 각각 다르기만 하면(0,0 1,1 혹은 0,1 1,0 등) 완전한 원이된다.
    4. x-axis-rotation
      이것도 참 미묘하다.
      타원일 경우 x축을 기준으로 n만큼 회전(단위는 degree:각도)한다.
      rotate가 있는데 이걸 쓸 필요가 있나 싶긴 하다.
    5. 사실 다 필요없고 이거 한번 보는게 낫다.
      http://codepen.io/lingtalfi/full/yaLWJG/
      x-axis-rotation 이 제대로 작동하는 것을 보기 위해 Radius X와 Radius Y를 다르게 설정하는 것을 추천.
실제로 호를 그리려면 결국 굉장히 암울한데 sin, cos을 이용하여 호의 시작점과 끝점은 미리 알고만 있으면 어떻게든 그릴 수 있긴 하겠다. 그래도 저걸 루프써서 선으로 안긋는게 어딥니다.
사실은 "A 시작각도 끝각도 rx ry cx cy" 였으면 얼마나 좋아 제기랄
http://jsbin.com/rowivid/edit?html,output 같이 하나 열고 연습해보아요.

sin, cos으로 원 그리는 건 다들 알고 계시죠?
r 이 반지름, cx,cy가 중심점일 때 degree 각도 만큼인 곳의 점의 위치는
cos(2*Math.PI*degree/360)*r + cx
sin(2*Math.PI*degree/360)*r + cy
이니까 약분하면
[cos(Math.PI*degree/180)*r + cx , sin(Math.PI*degree/180)*r + cy]
으로 x,y를 구할 수 있다. 호의 x,y는 이걸 사용하면 된다.



중간중간 빵꾸난 지식으로 글 쓰려니 힘들다. 그러니까 여러분도 같이 힘들어요~

이 블로그의 인기 게시물

ESP32 DevBoard 개봉기

오늘 드디어 손에 넣었다. ESP32 DevBoard!
Adafruit 에서 15개 한정 재입고 트윗을 보고 광속 결제.
그리고 1주일의 기다림. 사랑해요 USPS <3
알리를 이용하다보니 1주일 정도는 광속 배송임.
물론 배송비도 무자비함 -_ㅜ
15개 한정판 adafruit 발 dev board
그놈이 틀림없으렸다.
오오 강려크한 포스
ESP32_Core_board_V2라고 적혀있군요.
ESP32 맞구요. 네네. ESP32-D0WDQ6 라고 써있는데 D → Dual-core 0 → No internal flash W → Wi-Fi D → Dual-mode Bluetooth Q → Quad Flat No-leads (QFN) package 6 → 6 mm × 6 mm package body size 라고 함.
길이는 이정도
모듈크기는 이정도
코어는 6mm밖에 안해! 여기에 전기만 넣으면 BLE+WIFI!
밑에 크고 발 8개 달린 놈은 FM25Q32라고 32Mbit 플래시메모리
ESP8266 DevBoard 동생이랑 비교 크고 아름다운 레귤레이터랑 CP2102 USB Driver가 붙어있음.
ESP8266 DevBoard엔 CH340G 인데 확 작아졌네.
머리를 맞대어 보았음.
모듈크기는 아주 약간 ESP32가 더 큰데 워낙에 핀이 많고 촘촘함. ESP8266인 ESP12는 핀 간격이 2.00mm인데 비해
ESP32는 1.27mm 밖에 안함.
딱봐도 비교가 될 정도.
https://www.sparkfun.com/news/2017 크고 아름다운 Pinouts

ESP8266 보드랑 별로 안달라보인다.
http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers.aspx#mac
에서 CP2102 드라이버를 설치하고
screen 으로 연결해보자.
내 경우엔 tty.SLAB_USBtoUART 로 잡혔다.
어디서 기본 속도가 115200bps 라고 들은 적이 있어서
screen /dev/tty.SLAB_USBtoUART …

즐거운 Online Prototyping Tool 들

jsbin, codepen, jsfiddle 이런 것들은 일단 생략. 너무 유명한 것들이라.

https://launchpad.graphql.com - node.js 기반 graphQL 연습장. 이것만으로도 충분히 훌륭한 백엔드
https://codesandbox.io/ npm 사용이 가능한 클라이언트 사이드 연습장. webpackbin이 너무 문제가 많아서 찾아본 것.

https://scrimba.com 이건 codesandbox+ asciinema(https://asciinema.org/) 같은 느낌인데 키 녹화와 음성 녹화 기능이 추가되었다. 다 좋은데 화살표 키로 빨리감기 뒤로감기 기능이 안되고 익스포트(youtube등)으로 지원이 없는게 아쉽다.

이 둘이 만나면? https://codesandbox.io/s/jvlrl98xw3?from-embed
뭐야 이거 무서워 하지마 ㄷㄷ;  graphql+react-native-web(부왘ㅋㅋ)

https://repl.it/languages 전통을 자랑하는 REPL 도구. 지원 언어 종류가 -_-;;;;;

https://tio.run/# repl.it? 장난함? 얘는 지원 언어가 무려 386종류. J랑 아희도 있다.

https://play.golang.org/ 즐거운 go playground. 소스 포멧팅 넘 좋아.

http://decaffeinate-project.org/repl/ 최고의 coffeescript REPL. 원래 용도는 coffee를 ecma6코드로 바꾸는 것이지만...

https://scaphold.io
https://www.graph.cool/ graphql backend service. scaphold.io는 설치도 필요없는 클라우드. graphcool은 호스팅+클라우드 다있음. 둘 다 막상막하. 푸쉬서버도 되고 뭐 미친득.

https://glitch.com/ gomix에서 결국 glitch로 안착.  node.js

https://www.shadertoy.com 잘하고 싶다! 쉐이다! 오디오도 된다!

http:/…

graphql 연습 /w launchpad

https://launchpad.graphql.com/mw9wkzv99
단순 전체쿼리+조건쿼리+추가

http://graphql.org/graphql-js/passing-arguments/
참고. random ID는 crypto 1.0.1 사용
  type Query {
    Members: [member]
    getMember(id: ID!): member
  }
  type member {
    id: ID!
    text: String
  }
  input memberInput {
    text: String
  }
  type Mutation {
    addMember(member: memberInput): member
  } SQL 정의. facebook 쪽은 스트링에 지지는 거 진짜 좋아하네. *.gql 파일이 있다고 하니 이해해주자.
resolver는 var buffer = [];
const resolvers = {
  Query: {
    Members: (root, args, context) => {
      return buffer;
    },
    getMember: (id)=> {
      return buffer.find(o=>o.id)
    }
  },
  Mutation: {
    addMember(_, {member}) {
      const mm = { ...member, id:randomBytes(10).toString('hex') };
      buffer.push(mm);
      return mm;
    }
  }
}; 평범 평범.
https://dev-blog.apollodata.com/tutorial-graphql-subscriptions-server-side-e51c32dc2951 다음으로 pub/sub 연습.
https://launchpad.graphql.com/xvn94n3ql   type Subscription {
    memberAdded: member
  } member가 added되는 순간을 감시. imp…