분류 전체보기
- android studio 2.0 android monitor 버그.. 2016.04.27
- 사용자 스레드에서도 Handler(UI쓰레드) 생성할 수 있다. 2016.04.26
- 안드로이드 RecyclerView 스크롤 감지 2016.04.26
- 네트워크 상태 체크 하기 2016.04.26 1
- UI Thread 사용법 2016.04.24
- ListView를 대체할 새로운 컴포넌트 Recyclerview 2016.04.24
- [C/C++] SortLib 2014.11.17
- SVG란-2 2013.07.13
- SVC란-1 2013.07.13
- QT debugging tool 설정 안되어 있을때, 2013.07.13
android studio 2.0 android monitor 버그..
사용자 스레드에서도 Handler(UI쓰레드) 생성할 수 있다.
사용자 스레드를 만들고 그 안에서 UI변경 하려고 하면 다음과 오류가 뜬다.
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
쉽게 말해 안드로이드는 UI를 메인스레드에서 관리하는데 지금 니가 만든 사용자 스레드에서 UI를 건들고 있다. 이건 위험하다. 이런 얘기다.
그래서 사용자 스레드에서 바로 하지 않고 Handler 를 사용해서 UI 건드니깐 또 이런 오류가 뜬다.
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Handler는 MainThread를 사용하는거 아니였나?? ㅡ,,ㅡ?
android.os.Handler handler = new android.os.Handler(Looper.getMainLooper());
위와 같이 만들어주면 이제 오류 메세지를 피할 수 있다.
Handler는 Looper를 통해 스레드의 MessageQueue에 메세지를 전달 하는 역활을 하는데, 우리가 만든 사용자 스레드에는 Looper와 MessageQueue가 없다.
그래서 오류 메세지를 나왔던 것이고, 위와 같이 Looper.getMainLooper() 함수를 통해 MainThread의 Looper를 받아서 만들면 오류를 피할 수 있는 것 이다.
안드로이드 RecyclerView 스크롤 감지
onScrollStateChanged함수는 기존에 onScroll 함수가 스크롤 할 때마다 호출되어 반응성이 좋게 코드를 만들 수도 있겠지만, 빈번한 호출로 어플이 버벅일수도 있었다. 그러한 점을 고쳐 newState로 들어오는 스크롤 상태변수는 상태가 변할 때 마다 딱 1번만 호출되어 값을 넘겨준다.
SCROLL_STATE_SETTLING
상태는 위든 아래든 스크롤이 끝까지 갔음을 의미한다.
SCROLL_STATE_IDLE
상태는 현재 스크롤을 하지 않는 상태, SCROLL_STATE_DRAGGING
스크롤을 하고 있는 상태이다.
onScrolled함수의 dx, dy 변수는 각자 수직 수평으로 스크롤이 얼마나 되었는지 그 양을 뜻한다. 스크롤 위치가 아니다, 절대.
dy가 음수 값이면 현재 위치를 0 기준 잡고 위로 스크롤 했다는 뜻이고, dy가 양수면 아래로 스크롤 했다는 뜻이다.
'android' 카테고리의 다른 글
네트워크 상태 체크 하기 (1) | 2016.04.26 |
---|---|
UI Thread 사용법 (0) | 2016.04.24 |
ListView를 대체할 새로운 컴포넌트 Recyclerview (0) | 2016.04.24 |
네트워크 상태 체크 하기
Android를 개발하다 보면, 네트워크 통신 전에 꼭 해야 할 것이 있는데 이것이 바로 현재 단말기가 mobile network or Wifi에 연결되어 있는지 확인 후, 통신을 시도하게 된다.
오랜만에 코딩 하고 있는지라, api 23 부터 기존 아래의 코드는 deprecated 되었다.
1: ConnectivityManager manager = (ConnectivityManager) MyApplication.mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
2: NetworkInfo mobile = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
3: NetworkInfo wifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
4:
5: if (mobile.isConnected() || wifi.isConnected()) {
6:
7:
8: } else {
9: // WIFI, 3G 어느곳에도 연결되지 않았을때
10:
11: }
새로운 방식은 아래와 같다.
1: ConnectivityManager cm = (ConnectivityManager) MyApplication.mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
2: NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
3: if (activeNetwork != null) {
4:
5: if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI && activeNetwork.isConnectedOrConnecting()) {
6: // wifi 연결중
7:
8: } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE && activeNetwork.isConnectedOrConnecting()) {
9: // 모바일 네트워크 연결중
10:
11: }
12: else
13: {
14: // 네트워크 오프라인 상태.
15: }
16: } else {
17: // 네트워크 null.. 모뎀이 없는 경우??
18: }
흠.. 별로 달라진 것이 없는 것 같지만, 이제 어떤 통신인지 구별도 가능하게 되었다..
MyApplication.mContext는 내가 만든 context를 저장하기 위한 전역 변수 역할을 하는 클래스이다.. 필자는 어디서든 쓸 수 있도록 저렇게 쓴다.
다른 분들은 그 자리에는 자신이 만든 main Activity의 context를 넣자.
'android' 카테고리의 다른 글
안드로이드 RecyclerView 스크롤 감지 (0) | 2016.04.26 |
---|---|
UI Thread 사용법 (0) | 2016.04.24 |
ListView를 대체할 새로운 컴포넌트 Recyclerview (0) | 2016.04.24 |
UI Thread 사용법
안드로이드는 크게 사용자가 만든 쓰레드와 UI를 담당하는 MainThread(UI Thread)가 있는데, Activity내부에서 쓰여진 코드들은 모두
UI쓰레드에서 실행된다.
그래서 쓰레드를 따로 쓰지 않고, 연산이 오래 걸릴 가능성이 있는 network 소켓을 사용한 통신을 한다 던지, file I/O 작업을 하게 되면
오류가 나며, 강제 종료 되게끔 되어있다.
왜 그런 것 일까? 우리가 안드로이드 입장이 되어 보면 당연하다. 만일 UI 쓰레드에서 네트워크 통신을 하면, 통신 하는 동안에는 UI
작업을 못하니깐, 말 그대로 화면이 멈출 것이다.
사용자가 화면을 터치해도 무반응일 것이며, 화면이 먹통이 되어버릴 것이다. 그래서 꼭 이런 작업들은 따로 사용자 스레드를 만들
어서 작업해주어야 한다.
사용법은 아래와 같다.
1: new Thread(new Runnable()
2: {
3: @Override
4: public void run()
5: {
6: //수행 할 작업 코드
7: }
8: }).start();
간단하다. But, 그런데 사용자 스레드 작업 중, UI를 변경(UI스레드에서 작업)하고 싶다면 어떻게 할까?
예를 들면 통신이 실패 해서 사용자에게 “통신이 상태가 좋지 않습니다” 라고 메세지를 띄우고 싶다면?
그럴 경우도 안드로이드는 친절히 방법을 마련해 놓았다.
아래와 같이 사용하면 된다.
1: MainActivity.runOnUiThread(new Runnable()
2: {
3: @Override
4: public void run()
5: {
6: //여기에 UI스레드에서 동작하게 하고 싶은 내용 입력
7: }
8: });
App 내에 자신이 정의한 메인엑티비티.runOnUiThread( )를 사용하면 된다. 제발 소스코드 복사 붙여 넣기 해서, “MainActivity선언이
안되어 있어요..” 라고 말도 안 되는 소리 하지 말자..
'android' 카테고리의 다른 글
안드로이드 RecyclerView 스크롤 감지 (0) | 2016.04.26 |
---|---|
네트워크 상태 체크 하기 (1) | 2016.04.26 |
ListView를 대체할 새로운 컴포넌트 Recyclerview (0) | 2016.04.24 |
ListView를 대체할 새로운 컴포넌트 Recyclerview
기존에 안드로이드 내에서 item목록을 보여주기 위해서는 ListView 컴포넌트를 사용했었다.
문제는 listView가 스크롤(scroll)되면서 getView내에서 계속해서 v.findViewById() 함수를 호출하게 되는데, 이는 불필요한 연산일뿐아니라,
UI성능 저하를 가져온다. 그래서 꼭 필수적으로 쓸 사항은 아니지만, 구글에서는 암묵적으로 ViewHolder 패턴을 쓰라고 권장하고 있는데,
아래와 같다.
1: @Override
2: public View getView(int position, View convertView, ViewGroup parent)
3: {
4: PersonViewHolder viewHolder;
5:
6: // 캐시된 뷰가 없을 경우 새로 생성하고 뷰홀더를 생성한다
7: if(convertView == null)
8: {
9: convertView = mInflater.inflate(mLayout, parent, false);
10:
11: viewHolder = new PersonViewHolder();
12: viewHolder.icon = (ImageView) convertView.findViewById(R.id.iconImage);
13: viewHolder.name = (TextView) convertView.findViewById(R.id.name);
14: viewHolder.address = (TextView) convertView.findViewById(R.id.address);
15: viewHolder.phone = (TextView) convertView.findViewById(R.id.phone);
16:
17: convertView.setTag(viewHolder);
18: }
19: // 캐시된 뷰가 있을 경우 저장된 뷰홀더를 사용한다
20: else
21: {
22: viewHolder = (PersonViewHolder) convertView.getTag();
23: }
24:
25: viewHolder.name.setText(mItemList.get(position).getName());
26: viewHolder.address.setText(mItemList.get(position).getAddress());
27: viewHolder.phone.setText(mItemList.get(position).getPhone());
28:
29: return convertView;
30: }
저렇게 매번 converView를 생성 하는게 아니라, null이 아니면 재사용하는 방법을 사용한다.
하지만, 이제는 Recyclerview를 사용한다면, 저렇게 하지 않아도 된다.
아래는 내가 앱 내에서 게시판 글 목록을 보여주기 위해 만들어본, 게시판 리스트 뷰이다.
1: static private class ArticleListAdapter extends RecyclerView.Adapter<ArticleListAdapter.ArticleItem>
2: {
3: ArrayList<Article> mList = null;
4: public ArticleListAdapter(ArrayList<Article> articles)
5: {
6: mList = articles;
7: }
8:
9: @Override
10: public ArticleItem onCreateViewHolder(ViewGroup parent, int viewType) {
11: //새로운 itemView가 필요시마다 호출된다.
12:
13: LayoutInflater inflater = LayoutInflater.from(MyApplication.mContext);
14:
15: View rootView = inflater.inflate(R.layout.fragment_board_article_row_item,parent,false);
16:
17: return new ArticleItem(rootView);
18: }
19:
20: @Override
21: public void onBindViewHolder(ArticleItem holder, int position) {
22: /* itemView가 ArticleItem holder로 넘어오면 우리는 그냥 받아 쓰면된다.
23: 그것이 화면에서 사라져 재활용되기 위해서 온 view일수도 있고, 새로 만들어진 view일수도있지만
24: 사용자는 그것에 대해 신경쓸필요없다.*/
25: Article article = mList.get(position);
26: holder.setTitle(article.getTitle());
27: switch (article.getType())
28: {
29: case "normal":
30: holder.setType(ArticleItem.ArticleType.NORMAL);
31: break;
32: case "notice":
33: holder.setType(ArticleItem.ArticleType.NOTICE);
34: break;
35: }
36: holder.setDate(article.getDate());
37: holder.setNick(article.getNickName());
38:
39:
40:
41: }
42:
43: @Override
44: public int getItemCount() {
45: return mList.size();
46: }
47:
48: /*
49: * 이전까지 썻던 ViewHolder패턴에서 직접 만들어 쓰던 ViewHolder다.
50: * 이제는 만들어 쓸필요없이, RecyclerView에서 자체적으로 제공해주는것을
51: * 상속해 쓰기만 하면된다.
52: * */
53: static class ArticleItem extends RecyclerView.ViewHolder
54: {
55: enum ArticleType {NOTICE,NORMAL}
56: TextView mTitleView = null;
57: TextView mDateView = null;
58: TextView mNickView = null;
59: TextView mArticleTypeView = null;
60:
61: public ArticleItem(View itemView) {
62: super(itemView);
63: mDateView = (TextView) itemView.findViewById(R.id.articleDate);
64: mTitleView = (TextView) itemView.findViewById(R.id.articleTitle);
65: mArticleTypeView = (TextView) itemView.findViewById(R.id.articleType);
66: mNickView = (TextView) itemView.findViewById(R.id.author);
67: }
68: public void setDate(String date)
69: {
70: mDateView.setText(date);
71: }
72: public void setTitle(String title)
73: {
74: mTitleView.setText(title);
75: }
76: public void setType(ArticleType type)
77: {
78: if(type == ArticleType.NOTICE)
79: {
80: mArticleTypeView.setText("공지");
81: }
82: else
83: {
84: mArticleTypeView.setText("일반");
85: }
86: }
87: public void setNick(String nick)
88: {
89: mNickView.setText(nick);
90: }
91: }
92: }
'android' 카테고리의 다른 글
안드로이드 RecyclerView 스크롤 감지 (0) | 2016.04.26 |
---|---|
네트워크 상태 체크 하기 (1) | 2016.04.26 |
UI Thread 사용법 (0) | 2016.04.24 |
[C/C++] SortLib
SortLib.h
#include <iostream>
namespace SortLib
{
void insert_sort_by_binary(void* base, int num, size_t size, int(*compar)(const void*, const void*));
void qsort_by_recursive(void* base, int num, size_t size, int(*compar)(const void*, const void*));
void qsort_by_non_recursive(void* base, int num, size_t size, int(*compar)(const void*, const void*));
void merge_sort_by_recursive(void* base, int num, size_t size, int(*compar)(const void*, const void*));
void merge_sort_by_non_recursive(void* base, int num, size_t size, int(*compar)(const void*, const void*));
void natural_merge_sort(void* base, int num, size_t size, int(*compar)(const void*, const void*));
void heap_sort(void* base, int num, size_t size, int(*compar)(const void*, const void*));
void buble_sort(void* base, int num, size_t size, int(*compar)(const void*, const void*));
void selection_sort(void* base, int num, size_t size, int(*compar)(const void*, const void*));
}
SVG란-2
Path
지난시간에는 SVG에서 사용할 수 있는 기본적인 도형들을 살펴보았다. 하지만 정형화된 도형을 쓰는 경우보단 정형화되지 않은 도형을 만들어서 써야 할 경우가 많다. 이때 사용할 수 있는 것은 path 이다. 사실 path 하나만으로도 지난시간에 살펴본 모든 도형들을 대체가 가능하다.
M 과 L
path 는 그 이름에서 알 수 있듯이 몇개의 좌표를 지정하고 그 좌표를 지나가도록 하여 도형을 그리는 element 이다. 아래의 예제를 보자.
<path stroke="#000000" d="M 50 50 L 100 50 100 100 M 150 150 L 200 150 150 200" />
d 속성에 그리고자 하는 위치의 좌표값을 설정하면 된다. 좌표는 “M x y” 혹은 “L x y”로 표현이 되는데 여기서 M 은 Move를 L 은 Line을 의미한다. 즉 M 으로 시작하는 좌표로는 눈에 보이는 선을 그리지 않고 L 로 이동하는 좌표일때 선을 그리게 된다. 마치 종이에 그림을 그릴때 펜을 종이 닿은 상태에서 이동하느냐 뗀 상태에서 이동하느냐의 차이와 같다. 그래서 위의 예제에서는 하나의 path element 를 이용해 서로 닿지 않는 두개의 삼각형을 그릴 수 있었다.
fill(채우기)
<path d="M 50,100 150,200 50,150"/> <path d="M 100 50 L 200 150 100 100" fill="none" stroke="black"/>
위의 예제에서 첫번째 path 에는 fill 속성이 없음에도 자동으로 검은색으로 채워졌다는 걸 볼 수 있다. 반면 fill속성을 주지 않고 stroke 만 속성만 준 두번째 path 는 선만 두개 그어졌을뿐 자동으로 close되지 않았음을 볼 수 있다. 그리고 , (comma) 를 삽입하던 삽입하지 않던 좌표에는 문제가 없음을 유의하자.
만약 두번째 path 와 같은 상황에서 도형을 완전히 close 시키고 싶다면? d 속성 마지막 값에 "z"를 추가하면 된다. open: <path d="M 100,50 200,150 100,100" fill="none" stroke="black"/> closed: <path d="M 100,50 200,150 100,100 z" fill="none" stroke="black"/> |
fill-rule
만약 채움이 있는 두개의 도형이 겹쳐지면 어떻게 될까? fill-rule 을 이용해서 겹쳐질때의 채움상태를 결정할 수 있다. 아래의 예제는 여러개의 삼각형으로 이루어져있는 것처럼 보이지만 사실은 두개의 삼각형을 겹쳐놓았을 뿐이다. 겹쳐지는 영역을 어떻게 채울 것인지에 대해 결정하는 속성이 fill-rule 이다. "evenodd" , 와 "noezero" 가 있다.
<path fill="orange" d="M 10,215 210,215 110, 42 z M 10,100 210,100 110,273 z" stroke="purple" stroke-width="3" fill-rule="evenodd"/>
Q 와 C
L 과 M 으로는 직선밖에 표현할 수가 없다. 곡선이나 타원을 표현하려면? Q 와 C 를 이용해 곡선을 나타낼 수 있다. Q} }와 {{C 는 Bézier curves를 그 기초로 하고 있다.
Bézier curves 베지에 곡선은(Bezier curve) n개의 점을 통해 곡선을 그리는 식이다. 폰트나 그래픽툴 등에서 부드러운 곡선을 생성하는데 이용되고 있다. cubic bezier curve 는 네개의 점(p0,p1,p2,p3)을 통해 3차 곡선을 만들며 Quadratic Bézier curves는 세개의 점을 통해 곡선을 만들어낸다. .... |
아래의 예제는 같은 좌표값을 이용해 직선과 곡선을 그린 예제이다.
<path d="M 100 200 Q 200,400 300,200" fill="none" stroke="blue" /> <path d="M 100 200 Q 300,400 300,200" fill="none" stroke="yellow" /> <path d="M 100 200 Q 100,400 300,200" fill="none" stroke="black" /> <path d="M 100 200 L 200,400 300,200" fill="none" stroke="red"/>
Quadratic curve는 세개의 인자가 필요하다. 시작점과 끝점 그리고 중간점이다. 중간점의 위치에 따라 곡선의 모양이 달라진다.(다소 혼란스러워보이지만) 위의 예제에서 나타는 세개의 곡선은 중간점만 다르고 이에 따라 변곡점의 위치도 달라짐을 볼 수 있다.
transformations
지금까지는 도형을 어떻게 그리는지에 대해서 알아보았다. 이제는 그려진 도형들을 변형시켜보도록 하자.
translation
가장 기본적인 transformation은 그려진 도형을 이동시키는 translation 이다. transform 속성을 이이용해서 이동시킬 수 있다.
<path fill="#bbb" fill-rule="evenodd" d="M 70,140 150,0 200,100 40,100 100,0 170,140 z"/> <path fill="#bbb" fill-rule="evenodd" transform="translate(200,0)" d="M 70,140 150,0 200,100 40,100 100,0 170,140 z"/>
위의 코드는 같은 좌표값을 사용하여 똑같은 모양의 도형을 두쌍 그린 후 하나를 다른 위치로 옮긴것이다. 만약translation 을 쓰지 않고 같은 효과를 내려고 한다면 이동후의 좌표값을 일일히 계산해서 도형을 따로 그려줘야 할 것이다.
rotation
이런 그대로 회전을 시키는 transformation이다.
아래의 예제는 두개의 타원을 그린 후 하나의 타원을 30도 만큼 rotation 시킨 예제이다. rotate(a,b,c) 코드로 회전을 시키는 첫번째 인자는 회전시킬 각도(radian이 아니라 degree)값이며 두번째 세번째 인자는 회전시킬 기준 좌표(x,y)이다. 기준 좌표가 타원의 중심과 같기 때문에 타원의 중심은 변하지 않은 상태로 회전하게 된다.
<ellipse cx="200" cy="200" rx="20" ry="100" opacity=".6" fill="#faa" stroke="#806" stroke-width="4"/> <ellipse cx="200" cy="200" rx="20" ry="100" transform="rotate(30,200,200)" opacity=".6" fill="#faa" stroke="#806" stroke-width="4"/>
만약 rotate시 기준좌표를 바꾼다면? 기준 좌표를 중심으로 돌테니 아래의 예제와 같이 도형의 위치또한 바뀔 것이다.
<ellipse cx="100" cy="100" rx="20" ry="100" opacity=".6" fill="#faa" stroke="#806" stroke-width="4"/> <ellipse cx="100" cy="100" rx="20" ry="100" transform="rotate(45,200,200)" opacity=".6" fill="#faa" stroke="#806" stroke-width="4"/>
scaling
scale 은 단순히 크기를 변화시키는 것이 아니다. 정확히 말하면 각 x,y좌표값들에 scale 값을 곱해준다. 이럴경우 중심의 좌표 역시 상대적으로 이동할 수 밖에 없다. 아래의 예제를 보자.
<ellipse cx="100" cy="50" rx="40" ry="20" fill="grey" stroke="black" stroke-width="12" stroke-dasharray="3,5,2"/> <ellipse cx="100" cy="50" rx="40" ry="20" fill="grey" stroke="black" stroke-width="12" stroke-dasharray="3,5,2" transform="scale(2.5)" />
여기서 주의깊에 보아야 할점은 두 타원의 중심좌표를 포함한 모든 속성값이 같고 scale 값만 다르지만 타원의 위치가 바뀌었다는 것이다. scale값이 제 자리에서 도형을 확대시키는 것이 아니라는 점이다.
'web' 카테고리의 다른 글
SVC란-1 (0) | 2013.07.13 |
---|---|
google map api key 받기 (0) | 2013.07.13 |
JSON (0) | 2013.07.13 |
SVC란-1
SVG란?
SVG(Scalable Vector Graphics)는 XML의 기반의 2차원 그래픽을 표현하기 위한 파일형식이다. SVG는 정적인(static) 이미지(image)뿐만 아니라 애니메이션이나 다양한 그래픽 효과를 위한 마크업과 API로 구성이 되어 있다. 그 이름 그대로 벡터(vector)기반으로 그래픽 데이터를 처리하므로 래스터(raster) 방식에 비해 확대나 축소에 유연하게 대응할 수 있으며 HTML에 섞어서 사용이 가능하므로 JavaScript를 통한 DOM 조작과 CSS로의 styling도 자유롭다.
현재는 1.1이 권고안으로 사용되고 있으며 여러가지 스펙이 추가된 1.2 버전이 재정중에 있다. 전체 스펙은 W3C SVG에서 확인할 수 있다.
지원 브라우져
데스크탑의 주요 브라우져인 FireFox, Chrome, Safari, Opera에서 지원을 하고 있다. MS에서는 SVG에 대응되는 VML(Vector Markup Language)라는 자체 스펙을 만들었으나 IE9부터는 SVG를 지원하기 시작했다.(MS는 W3C SVG워킹그룹에도 가입하였다) IE8이하버전에서는 플러그인 형태(Adobe SVG Viewer)로 SVG를 사용할 수 있다. 모바일 환경에서는 Mobile Safari, Mobile Opera, Fennec(FireFox의 모바일버전)에서 지원한다. 다만 안드로이드의 기본브라우져에서는 성능상의 이슈로 지원하고 있지 않고 있고 다음 버전(2.3 진저브레드 이상)의 안드로이드OS에서 지원할지 여부도 확실치 않다. 이외에 이미지를 SVG형태로 이미지를 export 하는 tool이나 SVG를 생성할 수 있는 많은 툴들이 있다.
XML based
SVG는 XML 베이스이다. 도형·필터·애니메이션이 XML 마크업 요소로 구성이 되며 각각의 조절은 그 속성값을 통해 이루어진다.일반적인 SVG의 형태는 다음과 같다.
<?xml version= "1.0" standalone= "no" ?> |
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > |
<svg width= "100%" height= "100%" version= "1.1" xmlns= "http://www.w3.org/2000/svg" > |
<path id= "mypath" stroke= "black" d= "M 50 50 L 100 100" /> |
<rect id= "myrect" stroke= "black" d= "M 50 50 L 100 100" style= "border:1px solid;" /> |
</svg> |
이와 같이 XML기반이기 때문에 SVG전문툴 뿐만이 아니라 메모장같은 간단한 텍스트편집기로도 파일을 편집할 수 있으며 text기반으로 분석하기도 용이하다.
SVG의 활용
웹폰트
웹에서 타이포그라피는 매우 중요한 요소이다. 웹페이지의 전체의 분위기를 결정지으며 잘 선택된 폰트는 불필요한 이미지나 코드를 줄여주기도 한다. 다양한 타이포그라피를 표현하기 위해 일반적으로 가장 많이 사용되는 방법은 이미지이다. 출력하길 원하는 텍스트를 이미지로 만들어버리는 것이다. 하지만 이와같은 방법은 웹 접근성 측면에서는 바람직하지 못하다. 웹 폰트는 사용자의 PC에 해당폰트가 없더라도 환경에 구애받지 않고 다양한 타이포그라피를 사용할 수 있다는 장점이 있다. 웹폰트로는 MS에서 만든 eot 포맷이 가장 유명하지만 라이선스의 문제로 IE에서만 동작하다는 단점이 있다. SVG로도 웹폰트를 만들 수 있는데 아래의 text는 SVG웹폰트로 styling 된 것이다.
동적 이미지의 생성
Flash같은 별도의 플러그인 없이 웹 상에서 이미지를 생성해야 될 필요가 있을때 SVG는 매우 유용하다. 아래의 이미지는 Daum 맵 서비스에서 면적구하기의 UI를 SVG로 구성한 예이다. 사용자의 마우스 움직임에 따라 면적를 나타내는 이미지가 계속 변하는데 이렇게 동적인 이미지를 SVG로 그릴 수 있다.
아래의 그림은 Google Docs 의 presention 서비스의 한 화면이다. 각종 도형들을 삽입하고 조절할 수 있는데 이런 도형들도 SVG로 생성된다.
resizing이 빈번한 이미지
SVG는 벡터 방식이므로 아래와 같이 이미지의 크기가 커지거나 작아지더라도 어느정도의 퀄리티를 계속 유지한다. [확대하기] 버튼을 한번 눌러보자.
SVG사용하기
SVG의 MIME-type은 image/svg+xml 이고 확장자는 .svg를 권장한다. HTTP헤더의 MIME-type이 정확하지 않을 경우 일부 브라우져에서는 표현이 잘 되지 않는 경우가 있다. 사실 웹상에서는 SVG 파일을 단독으로 쓰기 보다는 HTML페이지 내에서 섞어 쓸 일이 더 많다.
embed, object tag 사용
<div>아래의 그림은 호랑이 입니다.<div> |
<object type= "image/svg+xml" data= "tiger.svg" > |
위의 소스와 같이 embed 태그나 obejct 태그를 이용해 외부의 SVG를 html페이지 내에 포함시킬 수 있다.(embed 는 HTML5의 스펙에 포함되어 있다.) SVG파일별로 import가 쉽고 관리가 용이하다.(wikipedia의 경우 많은 이미지들이 SVG로 그려지고 각 위키 페이지에 import된다.)
img tag 사용
SVG 자체가 이미지의 한 포맷임으로 HTML의 img 태그를 사용할 수 있다. embed, object와의 차이점이 있다면 img 태그로 import시에는 SVG DOM node를 traversing 할 수 없다는 점이다.
<img src= "my_image.svg" width= "400" height= "300" > |
CSS
SVG를 지원하는 브라우져에서는 CSS의 image 관련 속성에 SVG를 사용할 수 있다.
<style type= "text/style" > |
.img { background-image:url(./image.svg); } |
</style> |
동적인 생성
정적인 SVG를 import 하는 경우만큼이나 동적으로 이미지를 생성해야 하는 경우가 많다. 이때에는 HTML element를 생성하듯이 SVG element를 만들면된다. 다만 SVG가 XML베이스이기 때문에 namespace를 명시해주어야 한다.
<script type= "text/javascript" > |
var svgns = "http://www.w3.org/2000/svg" ; |
var elLine = document.createElementNS( "line" , svgns ); |
elLine.setAttribute( "x1" , 100 ); |
elLIne.setAttribute( "x2" , 200 ); |
... |
svgRoot.appendChild( elLine ); |
</script> |
예제
아래와 같은 내용의 파일을 만든 후 브라우져나 SVG 뷰어로 열어보자. 간단한 선이 하나 나올 것이다. 이후부터 나오는 소스코드는 아래의 내용을 바탕으로 할 것이다.
<?xml version= "1.0" standalone= "no" ?> |
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" |
<svg width= "100%" height= "100%" version= "1.1" xmlns= "http://www.w3.org/2000/svg" > |
<!-- 그리기 시작 --> |
<line x1= "50" y1= "50" x2= "100" y2= "100" stroke= "#000" /> |
<!-- 그리기 끝 --> |
</svg> |
기본 단위
좌표 체계
기본 좌표체계는 HTML과 거의 비슷하다. top left를 (0,0)으로 하고 right, bottom방향으로 증가하게 된다.
color code
이역시 HTML과 유사하다.
red
, aquagreen 같은 color name 사용가능- #ff0283 와 같은 6digit과 #000 와 같은 3digit 사용가능
- rbg(100,100,100) 혹은 rgb(100%, 50%, 25%) 와 같은 RGB value로 표현가능
기본 도형
<line>, <rect>, <circle>, <ellipse>, <text>, <image>, <polyline>, <polygon>, <path>, <use> 이다. 하나씩 살펴보도록 하자.
line, rect, circle, ellipse
각각의 이름그대로 선, 직사각형, 원, 타원을 나타낸다.
<line x1= "240" y1= "100" x2= "300" y2= "150" stroke= "#00ff00" stroke-width= "6" /> |
<rect width= "100" height= "150" fill= "#0000ff" stroke-width= "1" stroke= "#000000" /> |
<rect x= "120" y= "10" width= "100" height= "150" fill= "#0000ff" stroke-width= "1" stroke= "#000000" /> |
<circle cx= "300" cy= "50" r= "40" stroke= "black" stroke-width= "2" fill= "red" /> |
<ellipse cx= "300" cy= "200" rx= "220" ry= "30" style= "fill:purple" /> |
<ellipse cx= "300" cy= "220" rx= "190" ry= "20" fill= "lime" /> |
위와 같이 원하는 shape의 element를 선언하고 attribute를 통해 세부적으로 도형을 모양을 조절할 수 있다. 이후에도 살펴보겠지만 fitler나 animation등도 관련된 animation이나 filter element를 선언하고 attribute를 통해 세부적인 내용을 조절하는 방식으로 사용된다. 자세한 속성들은 천천히 살펴보도록하고 지금은 기본적인 몇가지 속성만 알아보자.
- stroke 속성은 선의 색깔을 나타낸다.
- storoke-width 속성은 선의 굵기를 나타낸다. 단위는 pixel이다.
- fill 속성은 채워지는 색깔을 나타낸다.
- 좌표는 element마다 약간씩의 차이는 있지만 x , y attribute로써 표현된다. line element의 경우 선의 시작점과 끝점을 나타내기 위해 x1, y1, x2, y2 두쌍의 좌표 attribute가 존재한다.
- circle, ellipse element에 사용된 cx, cy 속성은 원(타원)의 중심 좌표를 나타낸다. r 속성은 반지름을, rx와 ry 는 타원의 x축,y축 방향으로의 반지름을 나타낸다.
stroke-dasharray attribute
다양한 점선을 표현하기 위한 속성으로 stroke-dasharray 가 있다.
<circle cx= "140" cy= "110" r= "60" stroke= "yellow" stroke-width= "30" fill= "red" stroke-dasharray= "10,20" /> |
<line x1= "280" y1= "10" x2= "350" y2= "200" stroke= "black" stroke-width= "20" stroke-dasharray= "1,5,5,10" /> |
위의 예와 같이 복잡한 모양의 점선을 만들 수가 있는데 stroke-dasharray 의 값은 (선의넓이, 여백, 선의넓이, 여백....)으로 구성이 된다. 세밀한 선과 여백을 표현하려면 stroke-dasharray 의 값을 좀 더 조밀하게 조절해주면 된다.
text
text element 는 글자를 표현하는 요소이다. 다양한 방법으로 응용이 가능하지만 우선 간단하게 어떻게 쓰는지 보도록 하자.
<text x= "20" y= "20" >기본 텍스트</text> |
<text x= "20" y= "70" style= "font-size:50px;stroke:#000;fill:#0f0" >폰트 크기 조절 및 채우기</text> |
<text x= "20" y= "110" style= "font-size:30px;fill:#000;letter-spacing:15px;" rotate= "0,45,90,135,180,225,270,315,360" >ABCDE가나다라</text> |
style 속성을 이용해 letter-spacing 이나 font-size 를 조절하는 위의 예에서 볼 수 있듯이 text element 는 CSS와 거의 흡사한 방법으로 text를 styling할 수 있다(이는다른 SVG의 다른 element들에도 적용된다). 3번째 라인의rotate 속성은 character 하나 마다 얼마나 회전시킬지를 결정하는 속성이다. 단위는 degree이다.rotate="-10,-20,-30,-40, -40" 가 적용되어 있다면 각각의 텍스트는 다음과 같이 회전된다.
위치의 조절
text 가 나타낼 위치역시 x, y 로 조절이 되는데 도형과는 조금 차이가 있다. 아래의 코드와 그림에서와 같이 text와 line이 같은 y position이 같은 값을 가지고 있지만 라인이 text의 일부를 가로지는 걸 볼 수 있다.
<line x1= "20" y1= "50" x2= "300" y2= "50" stroke= "black" /> |
<text x= "20" y= "50" style= "font-size:40px;" >A g p h ㄱ 가 각</text> |
image
HTML의 img 와 같은 기능을 한다. image파일이나 svg파일을 모두 import할 수 있으며 기본 속성값은 rect 와 흡사하다. 다만 외부의 이미지를 link하기 위해서 xlink namespace가 선언되어 있어야 한다. 아래의 코드에서도svg element에 xlink 의 namespcae( xmlns:xlink="http://www.w3.org/1999/xlink )를 선언해주었다.
<svg width= "100%" height= "100%" version= "1.1" |
xmlns= "http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink" > |
<image xlink:href= "./img2.jpg" width= "100" height= "100" x= "0" y= "0" /> |
<image xlink:href= "./img2.jpg" width= "100" height= "100" x= "0" y= "0" /> |
</svg> |
use
앞에서 여러 basic shape들을 이용해 만든 도형들을 여러번 사용해야 할 때가 있다. 같은 모양 같은 색깔의 shape를 하나 더 선언해주는 것보다 use element를 통해 이미 선언된 element를 사용하는 것이 효율적이다. 아래의 예제는<g> element로 묶인 복잡한 도형을 use 를 이용해 재사용하는 예이다. use 사용된 transform 속성은 뒤에 살펴보도록 하겠다.
<svg width= "100%" height= "100%" version= "1.1" |
xmlns= "http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink" > |
<g id= "shape" > |
<rect x= "100" y= "100" width= "100" height= "20" fill= "#000" /> |
<rect x= "100" y= "160" width= "100" height= "20" fill= "#eee" /> |
<ellipse cx= "150" cy= "140" rx= "30" ry= "100" fill= "#777" /> |
</g> |
<use xlink:href= "#shape" transform= "translate(120,0)" /> |
</svg> |
'web' 카테고리의 다른 글
SVG란-2 (0) | 2013.07.13 |
---|---|
google map api key 받기 (0) | 2013.07.13 |
JSON (0) | 2013.07.13 |
QT debugging tool 설정 안되어 있을때,
QT 설치시 visual studio 가 깔려 있다 하더라도, 디버깅을 하기 위해서는 Win SDK가 깔려 있어야한다.
http://www.microsoft.com/en-us/download/confirmation.aspx?id=8279
위 링크를 통해 다운 받고 나면 자동으로 QT creator에서 CDB(console debugger)를 인식한다.