[H3 2012] 하이브리드앱 제작 사례 공유 - 푸딩얼굴인식 3.0

5,615 views

Published on

H3 2012 발표자료
하이브리드앱 제작 사례 공유 - 푸딩얼굴인식 3.0
-KTH 박종순

0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,615
On SlideShare
0
From Embeds
0
Number of Embeds
758
Actions
Shares
0
Downloads
101
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

[H3 2012] 하이브리드앱 제작 사례 공유 - 푸딩얼굴인식 3.0

  1. 1. 하이브리드 앱 제작 사례 공유 푸딩얼굴인식 3.0 앱스프레소랩 | 박종순 112년 10월 29일 월요일
  2. 2. Agenda 1. 하이브리드 앱과 프레임워크들 2. 단일페이지 인터페이스 3. 푸딩 얼굴인식 3.0 기술요소 Javascript Library Appspresso Built-in API Custom Plugins 4. 실전 앱 제작 테크닉 “웹 개발”스러운 “앱 개발” - 앱스프레소 On The Fly Fast button click iScroll 터치 이벤트 처리를 위한 레퍼 button 이벤트를 담당하는 하나의 이벤트 delegate 초기 앱 로딩 속도 개선 ... 212년 10월 29일 월요일
  3. 3. 하이브리드 앱과 프레임워크들 하이브리드 앱 프레임워크 Javascript Framework 312년 10월 29일 월요일
  4. 4. 하이브리드 앱과 프레임워크들 하이브리드 앱 프레임워크 PhoneGap, Appcelerator, Appspresso 플랫폼(iOS/Android/Etc.) 별 앱 빌드기능 제공 카메라 등 장치 접근을 위한 Device API 제공 412년 10월 29일 월요일
  5. 5. 하이브리드 앱과 프레임워크들 Javascript Framework jQueryMobile, Sencha Touch, JQTocuh, Jo 모바일 웹브라우저용 웹앱 제작을 위한 프레임워크 순수 웹 기반 (카메라 등 장치접근 불가) 512년 10월 29일 월요일
  6. 6. 단일 페이지 인터페이스 단일 페이지 인터페이스 (SPI: Single page interface) show/hide 하나의 HTML파일로 페이지 구성 612년 10월 29일 월요일
  7. 7. 푸딩 얼굴인식 3.0 기술요소 Javascript Library 앱스프레소 내장 API 앱스프레소 커스텀 플러그인 712년 10월 29일 월요일
  8. 8. 푸딩 얼굴인식 3.0 기술요소 Javascript Library Appspresso jQuery 1.6 KitchenSink 소스코드 공개 xx - 자체 제작 페이지 라이브러리 기존 플랫폼: 퍼포먼스 이슈, 커스터마이징 어려움 iScroll4 jpeg encoder Android Canvas를 이미지 파일로 저장하기 위함 oauth.js, sha1.js Facebook, Twitter OAuth 인증용 812년 10월 29일 월요일
  9. 9. 푸딩 얼굴인식 3.0 기술요소 Built-in Plugin filesystem - 히스토리 이미지, json파일저장 등 device status - 네트워크 상태 체크 등 ax.ext.ios - iOS 고유 네이티브 API ax.ext.android - Android 고유 네이티브 API ax.ext.ga - Google Analytics API ax.ext.media - 화면캡쳐 API ax.ext.net - cross domain 우회용 네트워크 API ax.ext.ui - 네이티브 다이얼로그 API 912년 10월 29일 월요일
  10. 10. 푸딩 얼굴인식 3.0 기술요소 Custom Plugin iOS / Android Camera Push notification Admob Media Share - 카카오톡 등 공유 etc... 1012년 10월 29일 월요일
  11. 11. 실전 앱 제작 테크닉 실전 앱 제작 테크닉 1. 하이브리드앱 주의사항 2. “웹 개발”스러운 “앱 개발” - On The Fly 3. Fast button click 4. iScroll 터치 이벤트 처리를 위한 레퍼 5. 버튼 이벤트는 한곳에 모아 처리 6. 초기 앱 구동 속도 개선 7. 페이지 전환 효과 8. DEMO 9. CSS 개발자 협업 10.다국어 처리 11.파일시스템 레퍼 1112년 10월 29일 월요일
  12. 12. 실전 앱 제작 테크닉 하이브리드 앱 주의사항 1212년 10월 29일 월요일
  13. 13. 12년 10월 29일 월요일
  14. 14. 12년 10월 29일 월요일
  15. 15. 하이브리드 앱 주의사항 그래서 어떻게?? 가능한 모든 리소스는 앱에 포함 오프라인 대응 꼭 필요한 경우에만 웹 리소스 접근 네이티브 앱 UI/UX 구현 1512년 10월 29일 월요일
  16. 16. 실전 앱 제작 테크닉 “웹 개발”스러운 “앱 개발” 앱스프레소 On The Fly 1612년 10월 29일 월요일
  17. 17. “웹 개발”스러운 “앱 개발” - On The Fly 앱 개발 사이클 개발자 설치 및 컴파일 확인 코딩 1712년 10월 29일 월요일
  18. 18. “웹 개발”스러운 “앱 개발” - On The Fly 왜그럴까요?? 코드 한줄을 수정해도 컴파일 필요 웹 개발에 익숙한 개발자들은 적응안됨 참을 수 없는 컴파일 과정의 답답함 코드수정 > 새로고침 되게 해주세요!!! 1812년 10월 29일 월요일
  19. 19. “웹 개발”스러운 “앱 개발” - On The Fly On The Fly 앱 개발 사이클 리플래쉬 확인 코딩 1912년 10월 29일 월요일
  20. 20. “웹 개발”스러운 “앱 개발” - On The Fly http://appspresso.com 2012년 10월 29일 월요일
  21. 21. 실전 앱 제작 테크닉 Fast button click 터치 반응성 향상 기법 2112년 10월 29일 월요일
  22. 22. 12년 10월 29일 월요일
  23. 23. Fast button click - 터치 반응성 향상 기법 왜그럴까요?? Click event VS Touch event 브라우저는 터치이벤트인지를 판단할 시간이 필요 약 300ms 의 delay time https://developers.google.com/mobile/articles/fast_buttons http://cubiq.org/remove-onclick-delay-on-webkit-for-iphone 2312년 10월 29일 월요일
  24. 24. Fast button click - 터치 반응성 향상 기법 이렇게 해결했습니다 touchstart 사용 var  touchEvent  =  ‘touchstart’; //  touch  event를  지원하지  않는  브라우저에서는  mousedown을  이용 if  (typeof  document.body.ontouchstart  ===  undefined  )  {          touchEvent  =  ‘mousedown’; } document.getElementById(‘someElement’)      .addEventListener(touchEvent,  function(e){        //  do  something },  false); 2412년 10월 29일 월요일
  25. 25. 실전 앱 제작 테크닉 iScroll 터치 이벤트 처리를 위한 레퍼 2512년 10월 29일 월요일
  26. 26. iScroll 터치 이벤트 처리를 위한 레퍼 iScroll 헤더고정 바디영역 스크롤 지원 회전목마(Carousel) 지원 iOS/Android 모두 지원 크로스플랫폼 스크롤 library 중 가장 빠른 속도 터치이벤트 처리의 어려움 플랫폼에 따른 옵션변경 필요 2612년 10월 29일 월요일
  27. 27. iScroll 터치 이벤트 처리를 위한 레퍼 이렇게 해결했습니다 touchTime을 계산하여 300ms 미만인 경우 클릭을 위한 터치이벤트로 간주 iScroll 직접수정 대신 wrapper 모듈 작성 - xx.scroll 개발자는 new iScroll(args) 대신 xx.scroll.addScroll(args) 사용 클릭을 위한 터치이벤트에 대해서만 onTouchEnd 콜백 호출 플랫폼 별 옵션 분기처리 자동화 2712년 10월 29일 월요일
  28. 28. iScroll 터치 이벤트 처리를 위한 레퍼 touchTime 계산 var  touchTime  =  0, var  touchTime  =  0,        touchStart  =  0,        touchStart  =  0,        isScrolling  =  false;        isScrolling  =  false; document.addEventListener(DOMContentLoaded,  function(){        var  body  =  document.body; document.addEventListener(DOMContentLoaded,  function(){        body.addEventListener(‘touchstart’,  function(e){        var  body  =  document.body;                touchStart  =  new  Date().getTime();        },  false);        body.addEventListener(‘touchmove’,  function(e){        body.addEventListener(‘touchstart’,  function(e){                isScrolling  =  true; var  myScroll  = new iScroll(‘scrollWrapper’, {        },  false);                touchStart  =  new  Date().getTime();        body.addEventListener(‘touchend’,  function(e){        },  false);        ...,                isScrolling  =  false;        },  false);        onBeforeScrollEnd: function(){ });        body.addEventListener(‘touchmove’,  function(e){ var  myScroll  = new iScroll(‘scrollWrapper’, { Date().getTime()) - touchStart; touchTime = (new                isScrolling  =  true;        ..., },onBeforeScrollEnd: function(){                },  false); = (new Date().getTime()) - touchStart; touchTime onTouchEnd: onTouchEnd, }, onTouchEnd: onTouchEnd,        ...        ...        body.addEventListener(‘touchend’,  function(e){ }); });                isScrolling  =  false; ...        },  false); }); 2812년 10월 29일 월요일
  29. 29. iScroll 터치 이벤트 처리를 위한 레퍼 클릭을 위한 터치이벤트 판단 function  onTouchEnd(e){        var  args  =  this.args,                target  =  e.target,                eventPage,                i  =  10;        if  (isScrolling)  {                isScrolling  =  false;        }  else  {                while  (i-­‐-­‐)  {                        if($(target).hasClass(page))  { 300ms                                eventPage  =  $(target).attr(id);                                break; 이상인 경우만                        }                        target  =  target.parentNode; 버튼 이벤트                }                if  (!xx.page[eventPage]  ||  xx.page[eventPage].info.isShown)  {                        if(touchTime  <  300  &&  touchTime  >  1)  {                                if  (args.onTouchEnd)  {  args.onTouchEnd(e);  }                        }                }        } } 2912년 10월 29일 월요일
  30. 30. iScroll 터치 이벤트 처리를 위한 레퍼 푸딩얼굴인식 3.0 사용 예 var  onOptionTouchEnd  =  function(e)  {        //  클릭이라  판단된  경우에만  호출됨        //  do  something }; if(typeof  xx.scroll.wrapperSetting  ===  undefined){        var  scrollOption  =  {                  wrapperId:  wrapperSetting,                scrollbarClass:  noScroll,                onTouchEnd:  onOptionTouchEnd        };            xx.scroll.addScroll(scrollOption); } 3012년 10월 29일 월요일
  31. 31. 실전 앱 제작 테크닉 버튼 이벤트는 한곳에 모아 처리 3112년 10월 29일 월요일
  32. 32. 버튼 이벤트는 한곳에 모아 처리 일반적인 이벤트 처리 document.getElementById(‘someElement’)      .addEventListener(‘touchstart’,  function(e){        //  do  something },  false); $(‘#someElement’).bind(‘click’,  function(e){        //  do  something },  false); <div  onclick=‘alert(“aa”);’>BUTTON</div> 3212년 10월 29일 월요일
  33. 33. 버튼 이벤트는 한곳에 모아 처리 버튼 HTML <div class="header"> <button data-role="button" title="btnSettings" class="back"> <img src="image/icon_option.png" alt="setting" /> <div class="imgfix">&nbsp;</div> <span class="bg"></span> <img class="new hide" src="image/main_btn_new.png" alt="new" /> </button> <div class="title"> <h1><img id="mainTitle" src="image/beacon.png" alt="얼굴인식"/></h1> <div class="imgfix">&nbsp;</div> </div> <button data-role="button" title="btnMy" class="login"> <img src="image/icon_login.png" alt="my" /> <div class="imgfix">&nbsp;</div> <span class="bg"></span> </button> </div> 3312년 10월 29일 월요일
  34. 34. 버튼 이벤트는 한곳에 모아 처리 하나의 이벤트 delegate document.body.addEventListener(touchstart,  function(e)  { setTimeout(function()  { document.body.addEventListener(touchstart,  function(e)  {        var  target  =  e.target,      //  버튼  누름효과  제거        var  target  =  e.target,                btnName,
  35. 35.  eventPage,
  36. 36.  i  =  10;                btnName,
  37. 37.  eventPage,
  38. 38.  i  =  10;      $(target).removeClass(pressed);        while(i-­‐-­‐)  {                if($(target).attr(data-­‐role)  ===  button)  {  i  =  10;
  39. 39.  break;
  40. 40.  }
  41. 41.  
  42. 42.  
  43. 43.  
  44. 44.        if  (target.getAttribute(data-­‐role)  ===  button)  {                target  =  target.parentNode;        }
  45. 45.  
  46. 46.  
  47. 47.  
  48. 48.  //  실제  버튼  element  찾기      while  (i-­‐-­‐)  {    //  이벤트가  발생한  페이지  찾기        while(i-­‐-­‐)  {        if  (target.getAttribute(data-­‐role)  ===  button)  {              if($(target).hasClass(page))  {                //  버튼  이름  가져오기                                if($(target).attr(data-­‐role)  ===  button)  {                btnName  =  $(target).attr(title);                $(target).addClass(pressed);                      eventPage  =  $(target).attr(id);
  49. 49.  break;                        i  =  10;
  50. 50.                  btnName  =  $(target).attr(title);                setTimeout(function()  {              }
  51. 51.  
  52. 52.  
  53. 53.  
  54. 54.  
  55. 55.  
  56. 56.  
  57. 57.  break;
  58. 58.  
  59. 59.  
  60. 60.  
  61. 61.  
  62. 62.  
  63. 63.  
  64. 64.  
  65. 65.  
  66. 66.  
  67. 67.  
  68. 68.  
  69. 69.  
  70. 70.  
  71. 71.  
  72. 72.  
  73. 73.  
  74. 74.  
  75. 75.                          $(target).removeClass(pressed);              target  =  target.parentNode;                //  버튼  누름효과를  위한  pressed  class추가                        while  (i-­‐-­‐)  {
  76. 76.  
  77. 77.  
  78. 78.  
  79. 79.  
  80. 80.  
  81. 81.  
  82. 82.  
  83. 83.  
  84. 84.  
  85. 85.  
  86. 86.  
  87. 87.  
  88. 88.  
  89. 89.                                  if($(target).hasClass(page))  {
  90. 90.  
  91. 91.  }      }                                        eventPage  =  $(target).attr(id);
  92. 92.  break;                $(target).addClass(pressed);                target  =  target.parentNode;                                }      if  (_DEBUG)  {          }                        }                                target  =  target.parentNode;          console.log(touch  action:,  eventPage,  btnName);                          if  (_DEBUG)  {  console.log(touch  action:,  eventPage,  btnName);  }      }                        onButtonTouched(btnName,  eventPage);                },  200);      onButtonTouched(btnName,  eventPage);                e.stopPropagation(); },  200);                e.preventDefault();        } },  false); 3412년 10월 29일 월요일
  93. 93. 버튼 이벤트는 한곳에 모아 처리 onButtonTouched - 1 //  중복  터치이벤트  방지를  위한  변수 if  (_btnGlobalTouchActionFlag  ===  true)  { var  _btnGlobalTouchActionFlag  =  false, var  _btnGlobalTouchActionFlag  =  false,        _btnGlobalTouchActionTimer  =  undefined;        if  (_DEBUG)  {          _btnGlobalTouchActionTimer  =  undefined; function  onButtonTouched(btnName,  eventPage)  {        if  (_btnGlobalTouchActionFlag  ===  true)  {                console.log(두번  터치된  경우입니다!!!);                  if  (_DEBUG)  {  console.log(두번  터치된  경우입니다!!!,  btnName,  eventPage);  } //  “버튼이름”  과  이벤트가  발생한  “페이지이름”을  전달  받음        }                                  if  (_btnGlobalTouchActionTimer  !==  undefined)  {                        g.clearTimeout(_btnGlobalTouchActionTimer); function  onButtonTouched(btnName,  eventPage)  {        if  (_btnGlobalTouchActionTimer  !==  undefined)  {                }      ...                _btnGlobalTouchActionTimer  =  setTimeout(function(){                g.clearTimeout(_btnGlobalTouchActionTimer);                        _btnGlobalTouchActionFlag  =  false;                        _btnGlobalTouchActionTimer  =  undefined;        }                },  1000);  case  btnSettings:        _btnGlobalTouchActionTimer  =  setTimeout(function(){                return;                //  이건  중복  터치가  자주  일어  나므로  중복  터치  방지        }                _btnGlobalTouchActionFlag  =  false;                _btnGlobalTouchActionFlag  =  true;        switch(btnName)  {      //  basic  button        case  btnMy:                _btnGlobalTouchActionTimer  =  undefined;                xx.page.pageMy.show();                xx.page.pageSetting.show();                break;        },  1000);        case  btnSettings:                break;                //  이건  중복  터치가  자주  일어  나므로  중복  터치  방지                _btnGlobalTouchActionFlag  =  true;                xx.page.pageSetting.show();
  94. 94.  
  95. 95.  
  96. 96.  
  97. 97.  
  98. 98.  
  99. 99.  
  100. 100.  
  101. 101.  //  플래그가  켜진  경우  이벤트  처리안하고  return                break;        case  btnBack:        return;        case  btnClose:                xx.page.back();                break; }        }
  102. 102.  
  103. 103.  
  104. 104.  
  105. 105.  
  106. 106.  
  107. 107.  
  108. 108.  
  109. 109.  ... 3512년 10월 29일 월요일
  110. 110. 버튼 이벤트는 한곳에 모아 처리 onButtonTouched - 2        ...  switch  (eventPage)  {  //  이벤트  페이지에  따라  분기  처리        switch  (eventPage)  {        case  pageMain:        case  pageMain:                switch  (btnName)  {              switch  (btnName)  {  //  버튼  이름에  따라  분기  처리                          case  btnFind:                                xx.page.pageFind.show();                        case  btnFind:                                break;                        case  btnBattle:                                xx.page.pageFind.show();                                xx.page.pageBattle.show();                                break;                                break;                }                        case  btnBattle:                break; //  중복  이벤트방지  플래그가  켜진  경우  1추  후  플래그  해지        case  ...:                                xx.page.pageBattle.show(); if  (_btnGlobalTouchActionFlag  ===  true)  {        }                                break;        _btnGlobalTouchActionTimer  =  setTimeout(function(){        if  (_btnGlobalTouchActionFlag  ===  true)  {                }                _btnGlobalTouchActionFlag  =  false;                _btnGlobalTouchActionTimer  =  setTimeout(function(){                break;                        _btnGlobalTouchActionFlag  =  false;                _btnGlobalTouchActionTimer  =  undefined;                        _btnGlobalTouchActionTimer  =  undefined;        case  pageBattle:                },  1000);        },  1000);        } }                //  do  something }                break; 3612년 10월 29일 월요일
  111. 111. 버튼 이벤트는 한곳에 모아 처리 효과 하나의 이벤트 리스너 정의 앱 전역에 걸친 일관된 이벤트 처리 CSS 개발과 무관한 버튼 액션 처리 버튼누름 효과 처리 자동화 이벤트 코드를 한곳에 모음으로서 유지보수 용이 3712년 10월 29일 월요일
  112. 112. 실전 앱 제작 테크닉 초기 앱 구동 속도 개선 3812년 10월 29일 월요일
  113. 113. 초기 앱 구동 속도 개선 하이브리드 앱은 느려요~ 단일페이지 인터페이스로 구성된 앱 페이지 리소스는 앱 구동시에 로딩? jQueryMobile의 멀티페이지 템플릿 리소스의 lazy loading이 답이다! 3912년 10월 29일 월요일
  114. 114. 초기 앱 구동 속도 개선 싱글 페이지 템플릿 !-- main page -- div id=pageMain class=page style=display: none; div class=header ... img class=new hide src=image/main_btn_new.png alt=new / ... img class=main_event_ball1 src=locales/ko/image/main_event1.png/ img class=hide main_event_ball2 src=locales/ko/image/main_event2.png/ img class=hide main_event_ball1 src=locales/ko/image/main_event1.png/ 메인 페이지 img class=hide main_event_ball2 src=locales/ko/image/main_event2.png/ div class=imgfixnbsp;/div ... /div div class=body ... img class=type1 o1 src=locales/ko/image/main_frame03.png/ img class=type1 o2 src=locales/ko/image/main_frame04.png/ ... /div !-- page pageBattleSearch -- /div div id=pageBattleSearch class=page hide ui ... !-- page pageFind -- img src=image/find_icon_guide.png / div id=pageFind class=page hide ui ... img src=image/find_guide1.png alt=선글라스NO / 서브2 img src=image/battle_guide1.png / 서브1 ... img src=image/battle_guide_icon.png / img src=image/find_guide2.png alt=모자NO / img src=locales/ko/image/battle_guide2.png/ ... img src=image/battle_guide_icon.png / img src=image/find_guide3.png alt=옆모습NO / img src=image/battle_guide3.png / /div ... ... /div 4012년 10월 29일 월요일
  115. 115. 초기 앱 구동 속도 개선 이렇게 해결했습니다 앱 실행시 불필요한 리소스 Lazy Loading image, javascript, html 은 모두 Lazy Loading (단, CSS는 앱 시작시 full loading) 멀티페이지 템플릿, 페이지 모듈 JS 분리 Lazy Loading을 담당하는 xx.page 라이브러리 (개발자와 사용자는 Lazy Loading이 되는지도 몰라요) 4112년 10월 29일 월요일
  116. 116. 초기 앱 구동 속도 개선 멀티페이지 템플릿 !-- main page -- !-- page pageBattle -- div id=pageMain class=page style=display: none; div class=header div id=pageBattle class=page hide ui/div ... img class=new hide src=image/main_btn_new.png alt=new / ... HTML img class=main_event_ball1 src=locales/ko/image/main_event1.png/ Javascript !-- page pageBattle -- img class=hide main_event_ball2 src=locales/ko/image/main_event2.png/ img class=hide main_event_ball1 src=locales/ko/image/main_event1.png/ 메인 페이지 img class=hide main_event_ball2 src=locales/ko/image/main_event2.png/ div id=pageBattleResult ... div class=imgfixnbsp;/div class=page hide ui/div /div div class=body ... !-- page whois (finding) -- img class=type1 o1 src=locales/ko/image/main_frame03.png/ img class=type1 o2 src=locales/ko/image/main_frame04.png/ div id=pageFinding class=page hide/div /div ... /div !-- page pageBattle -- div id=pageBattle class=page hide ui/div !-- page pageFind -- !-- page whois result -- !-- page pageBattle -- div id=pageFind class=page hide ui/div div id=pageBattleResult class=page hide ui/div div id=pageFound class=page pageBattleSearch -- !-- page whois (finding) -- div id=pageFinding class=page hide/div hide ui/div !-- page ... whois result -- !-- page div id=pageBattleSearch class=page hide ui/div div id=pageFound class=page hide ui/div !-- page pageBattleSearchStar -- div id=pageBattleSearchStar class=page hide ui/div 4212년 10월 29일 월요일
  117. 117. 초기 앱 구동 속도 개선 HTML lazy loading if  (this.innerHTML  ===  )  {        ...          var  targetHTML  =  arg.id  +  .html?  +  (new  Date().getTime());        if  (arg.useLocale  ===  true)  {                targetHTML  =  locales/  +  _lang  +  /  +  targetHTML;        }              //  내용이  없는  경우  ajax를  이용한  lazy  loading          $.ajax({                    url:  targetHTML,                    context:  body                }).done(function(data)  {                        $(self).html(data).after(function(){                                loadContentCallback();                        });                                });          ...   } 4312년 10월 29일 월요일
  118. 118. 초기 앱 구동 속도 개선 Javascript lazy loading function  addScript(url,  callback)  {        if  (_DEBUG)  {  console.log(addScript,  url);  }        if  (typeof  lazyScriptLoading[url]  ===  undefined)  {
  119. 119.  
  120. 120.  
  121. 121.  
  122. 122.  
  123. 123.  
  124. 124.  
  125. 125.  
  126. 126.  
  127. 127.  
  128. 128.        //  bookmarklet  기법을  활용한  스크립트  lazy  loading                (function(e)  {                        e.onload  =  callback;                        e.setAttribute(src,  url);                        document.getElementsByTagName(body)[0].appendChild(e);                }(document.createElement(script))); !-- page pageBattle --                lazyScriptLoading[url]  =  true; div id=pageBattle class=page hide ui/div        }  else  { !-- page pageBattle --                if  (typeof  callback  ===  function)  { class=page hide ui/div div id=pageBattleResult                        callback(); !-- page pageBattleSearch -- div id=pageBattleSearch class=page hide ui/div                } !-- page pageBattleSearchStar --        } div id=pageBattleSearchStar class=page hide ui/div } 4412년 10월 29일 월요일
  129. 129. 초기 앱 구동 속도 개선 푸딩얼굴인식 3.0 사용 예 - 1 xx.page.add({ id: pageMy, onPageBeforeLoadForInit: function(){ var self = this; app.common.addScript(js/page_my.js, function(){ self.info.onPageLoad = function(){ app.pageMy.showScroll(); }; }); }, !-- page pageBattle -- div id=pageBattle class=page hide ui/div onPageHide: function() { !-- page pageBattle -- app.pageMy.resetStatus(); id=pageBattleResult class=page hide ui/div div }, !-- page pageBattleSearch -- div id=pageBattleSearch class=page hide ui/div useLocale: true !-- page pageBattleSearchStar -- div id=pageBattleSearchStar class=page hide ui/div }); 4512년 10월 29일 월요일
  130. 130. 초기 앱 구동 속도 개선 푸딩얼굴인식 3.0 사용 예 - 2 xx.page.add({ id: pageSetting, onPageBeforeLoadForInit: function(){ var self = this; app.common.addScript(js/page_setting.js, function(){ self.info.onPageLoad = function(){ app.pageSetting.updateUI(); }; }); }, !-- page pageBattle -- div id=pageBattle class=page hide ui/div onPageBeforeHide: function(){ pageBattle -- !-- page app.common.removeWebView(); div id=pageBattleResult class=page hide ui/div }, !-- page pageBattleSearch -- div id=pageBattleSearch class=page hide ui/div type: vertical !-- page pageBattleSearchStar -- div id=pageBattleSearchStar class=page hide ui/div }); 4612년 10월 29일 월요일
  131. 131. 초기 앱 구동 속도 개선 효과 네이티브앱 수준의 앱 시작 속도 앱 메모리 사용 최소화 멀티페이지 템플릿을 활용한 다국어 처리 용이 CSS 개발자와 협업 시 코드 충돌 최소화 4712년 10월 29일 월요일
  132. 132. 실전 앱 제작 테크닉 페이지 전환 효과 4812년 10월 29일 월요일
  133. 133. 페이지 전환 효과 HTML !-- page pageBattle -- div id=pageBattle class=page ui.../div !-- page pageBattle -- div id=pageBattleResult class=page ui.../div !-- page whois (finding) -- div id=pageFinding class=page.../div !-- page whois result -- div id=pageFound class=page ui.../div 4912년 10월 29일 월요일
  134. 134. 페이지 전환 효과 CSS .page{ width: 100%; height: 100%; left: 0; top: 0; position: absolute; overflow: hidden; opacity: 0; -webkit-transition: all 0.3s ease-out; } 5012년 10월 29일 월요일
  135. 135. 페이지 전환 효과 Javascript -webkit-transition: all 0.3s ease-out; // 배틀페이지 보이기 $(#pageBattle).css({opacity: 1}); // 배틀페이지 슬라이드 다운 $(#pageBattle).css({top: window.innerHeight}); // 배틀페이지 슬라이드 업 $(#pageBattle).css({top: 0}); 5112년 10월 29일 월요일
  136. 136. 페이지 전환 효과 CSS3 Transforms http://www.w3.org/TR/css3-transforms/ http://www.the-art-of-web.com/css/css- animation/ http://www.the-art-of-web.com/css/ timing-function/ 5212년 10월 29일 월요일
  137. 137. 실전 앱 제작 테크닉 DEMO 5312년 10월 29일 월요일
  138. 138. 실전 앱 제작 테크닉 CSS 개발자와 협업 5412년 10월 29일 월요일
  139. 139. CSS 개발자와 협업 data-role=”button” div data-role=button title=btnBattle img id=main_btn_frame3 class=type1 o1 src=locales/ko/image/main_frame03.png alt=닮은꼴 배틀 / div class=imgfixnbsp;/div div class=tit t1/div img id=main_btn_frame3_desc class=battle-msg msg-left src=locales/ko/image/main_battle_msg2.png alt=누가 더 연예인을 닮았을까? / /div div data-role=button title=btnFind img id=main_btn_frame4 class=type1 o2 src=locales/ko/image/main_frame04.png alt=닮은꼴연예인찾기 / div class=imgfixnbsp;/div div class=tit t2/div /div 5512년 10월 29일 월요일
  140. 140. CSS 개발자와 협업 효과 data-role=”button” 을 이용하므로 하위 마크업 과 무관한 버튼영역 처리 멀티페이지 템플릿 사용을 통한 CSS 개발자와 협업 시 코드 충돌 최소화 5612년 10월 29일 월요일
  141. 141. 실전 앱 제작 테크닉 다국어 처리 5712년 10월 29일 월요일
  142. 142. 다국어 처리 다국어 처리 W3C Widget 1.0 Spec http://www.w3.org/TR/widgets/ folder-based localization 5812년 10월 29일 월요일
  143. 143. 다국어 처리 folder-based localization 5912년 10월 29일 월요일
  144. 144. 실전 앱 제작 테크닉 파일시스템 레퍼 6012년 10월 29일 월요일
  145. 145. 파일시스템 레퍼 파일시스템 레퍼 - 1 function  writeFile(path,  text,  isBase64,  scb,  ecb)  {        if  (!ax.util.isValidPath(path))  {                ecb(new  Error(invalid  file  path:  +  path));                return;        }        var  pos  =  path.lastIndexOf(/),                folder  =  path.substring(0,  pos),                filename  =  path.substring(pos  +  1,  path.length);        if  (_DEBUG)  {  console.log(_module_name,  writeFile,  folder,  filename);  }        var  writeStream  =  function(stream){                if  (isBase64)  {                        stream.writeBase64(text.toString());                }  else  {                        if  (_DEBUG)  {  console.log(_module_name,  write  text:,  text);  }                        stream.write(text.toString());                }                stream.close();                if  (scb)  {  scb();  }        };        ... } 6112년 10월 29일 월요일
  146. 146. 파일시스템 레퍼 파일시스템 레퍼 - 2 function  writeFile(path,  text,  isBase64,  scb,  ecb)  {        ...        deviceapis.filesystem.resolve(                function(dir){                        dir.listFiles(function(files){                                var  i=0,  len  =  files.length,  f;                                for(i=0;  ilen;  i++)  {                                        f  =  files[i];                                        if  (f.name  ===  filename)  {                                                f.openStream(writeStream,  ecb,  w,  utf-­‐8);                                                return;                                        }                                }                                var  newFile  =  dir.createFile(filename);                                newFile.openStream(writeStream,  ecb,  w,  utf-­‐8);                        },  ecb);                },  ecb,  folder,    rw        ); } 6212년 10월 29일 월요일
  147. 147. 파일시스템 레퍼 효과 개발시 손쉬운 FileSystem 접근 xx.fexplorer 모듈을 활용한 파일시스템 브라우징 debug 시에만 파일 브라우저 이용 6312년 10월 29일 월요일
  148. 148. QA QA 6412년 10월 29일 월요일
  149. 149. 참조 참조 http://phonegap.com http://www.appcelerator.com http://appspresso.com http://jquerymobile.com http://www.sencha.com http://jqtouch.com http://joapp.com http://enable-cors.org http://msdn.microsoft.com/ko-kr/magazine/cc507641.aspx http://iolothebard.tistory.com/496 http://appspresso.com/api/extension/symbols/ax.ext.net.CurlOpts.html http://appspresso.com/ko/api-reference-ko http://appspresso.com/ko/archives/4098 https://developers.google.com/mobile/articles/fast_buttons http://cubiq.org/remove-onclick-delay-on-webkit-for-iphone http://h3.paran.com/2011/session/hybrid-app-architecture-and-development-method.html http://www.w3.org/TR/widgets/ http://www.bytestrom.eu/blog/2009/1120a_jpeg_encoder_for_javascript 6512년 10월 29일 월요일
  150. 150. 감사합니다. 개발실 / 앱스프레소팀 과장 / 박종순 althjs@kthcorp.com @althjs 6612년 10월 29일 월요일

×