반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형
Other methods and properties


$.mobile.changePage () 이외에 jQuery Mobile은 추가적인 메소드와 프로퍼티들을 제공합니다. 이것도 $.mobile object에  set 됩니다.


Methods defined on the $.mobile object


Method / Property

Signification

showPageLoadingMsg ()

Method to display a waiting message indicating a page is loading. The message is defined in $.mobile.loadingMessage string ("loading" by default).

hidePageLoadingMsg ()

Method to hide the waiting message previously shown by showPageLoadingMsg ().

activePage

Property representing the jQuery class object for the window currently displayed on the screen.

firstPage

Property representing the jQuery class object corresponding to the first window described in the HTML page (which will normally be displayed first).

pageContainer

Property representing the jQuery class object corresponding to the element in which the windows are inserted. By default the parent element of the first window, corresponding generally to the <body> element. Note that jQuery Mobile assigns the ui-mobile-viewport CSS class to this element.
The value of this property can be changed only during processing of the $ (document).ready () event or after it. New displayed windows will then be inserted in this element.


현재 active window의 HTML content 를 알기 위해 $.mobile.activePage property 를 사용합니다. 우리는 alert 안에 이 content를 display 하는 window에 link를 insert 합니다.


View HTML content of the active window


<!DOCTYPE html>

<html> 

<head> 

  <meta name=viewport content="user-scalable=no,width=device-width" />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=home>

  <div data-role=header>

    <h1>Home</h1>

  </div>


  <div data-role=content>

    <p> Window content </p>  

    <a href=# id=link1> View the contents of the active window </a>

  </div>

</div>


</body>

</html>


<script>


$("#link1").bind ("click", function (event)

{

  alert ($.mobile.activePage.html ());

});




tistory412_01.html





반응형


반응형

Parallax Simplified

Posted on . Written by

I

이번주 화요일의 튜토리얼은 코로나 Ambassador 인 Brent Sorrentino 씨가 해 주셨습니다. parallax scrolling 과 여러분 앱에 customizable touch-and darg parallax view 를 구현하는 데모 프로젝트에 대해 다룹니다.


We Live in a Parallax World



Parallax 는 천문학, photography,광학 에서 다루는 개념인데요 좀 의미가 광범위 합니다.  모바일 게임 개발자의 경우 2-dimensional scrolling simulation 에 대해 작업할 경우 parallax는 카메라와 움직이는 객체 사이의 거리감 (sense of “distance”) 을 제공하게 되죠.  이 메소드는 16 비트 닌텐도 시절부터 사용되어져 왔습니다. 그리고 요즘 인기있는 Angry Birds 와 Squids 등에서도 사용되고 있죠.


코로나의 display groups를 활용하면 차례로 겹쳐진 layer 들로 parallax scrolling을 간단하게 구현할 수 있습니다. 이론적으로는 그런데 실제 많은 개발자들이 실제 이것을 코딩하려고 하면 많이 헛갈려 하시죠. 오늘의 튜토리얼과 데모 프로젝트는 이 부분에 촛점이 맞춰져 있습니다.




1. Getting Started


처음으로 우리가 할 작업은 우리의 parallax "layers" 들을 display groups 로 configure 하는 겁니다. main.lua 파일에 아래 코드를 복사해 넣으세요.


--First, declare a local reference variable for the stage.
local stage = display.currentStage

--Declare your parallax layers in back-to-front order and specify their distance ratio.
--This "distanceRatio" sets the layer's scrolling speed in relation to the foreground (1.0) layer.
local back00 = display.newGroup() ; back00.distanceRatio = 0.2
local back01 = display.newGroup() ; back01.distanceRatio = 0.4
local back02 = display.newGroup() ; back02.distanceRatio = 0.6
local back03 = display.newGroup() ; back03.distanceRatio = 0.8
local foreground = display.newGroup() ; foreground.distanceRatio = 1.0

--IMPORTANT NOTE 1: You MUST have one layer set to 1.0 ratio, even if it won't contain any objects.
--IMPORTANT NOTE 2: Attach a reference variable named "refGroup" to the stage table and set its
--value to the 1.0 layer from above. This group will be used as the core reference group in
--relation to screen touch-and-drag.
stage.refGroup = foreground


  

각 parallax layer 는 “distanceRatio” parameter를 정해 줍니다. 이것은 아주 중요한 부분입니다. 우리는 이것을 foreground 의 1:1 scrolling 과 연결해서 각 레이어별로 스크롤링 스피드를 주는부분에서 사용할 겁니다.  만약 특정 layer 가 parallax scrolling에서 제외되어야 한다면 간단하게 이 파라미터를 undeclare 하면 됩니다.  예를 들어 이 display group setup의 hierarchy 중에 한개 나 두개의 layer 를 scroll 하고 싶지 않다면 , 예를 들어 UI/button/widget layer 같은 경우가 될 수 있겠죠, 이럴 경우 이 distanceRatio 값을 넣지 않으면 됩니다. 이 “distanceRatio” parameter 가 있는 layer 만 parallax scrolling 이 될 테니까요.


Additional note: “distanceRatio” parameter 는 여러분이 원하신다면 1.0 보다 클 수도 있습니다.  예를 들어 1.4로 했다면 이 레이어는 foreground 보다 더 빨리 움직일 겁니다.  이건 아마 카메라와 foreground 사이에 연한 안개가 있도록 할 경우에 활용할 수 있겠네요.


2. Setting Scroll Limits


대부분의 시나리오에서 어떤 제한된 공간(세계) 가 있게 되죠. 유저가 어느쪽으로 어디까지 drag 할 수 있는지에 대한 제한 등이 그런 것들인데요. 이런것들은 다음에 나오는 4개의 변수들에 의해 해결할 수 있습니다. 다음에 이것들을 쉽게 사용하도록 하기 위해 stage 의 파라미터들로서 이 4개를 정의해 둡니다.

여러분의 프로젝트에 다음 한 줄을 추가해 주세요.


stage.xMin = -400 ; stage.xMax = 400 ; stage.yMin = -150 ; stage.yMax = 1000
 

이 4개의 파라미터가 간단하게 그 제한된 공간을 나타낼 겁니다. xMin는  대개 음수가 되겠죠. 왼쪽까지 얼마나 멀리 그 공간이 정해질지를 정합니다. xMax는 오른쪽까지의 공간이구요. yMinyMax는 위쪽과 아래쪽으로 스크롤할 수 있는 공간을 나타낼겁니다.

이 숫자들은 모두 픽셀단위를 사용합니다. % 가 아닙니다. 또한 foreground 1:1 레이어는 움직이지 않을 거구요. 이 foreground layer 이외의 layer 들은 이 제한사항들이 적용될 겁니다.


3. Add Layers to a Containing Table


이제 우리는 이 parallax layer 들을 paraGroups라는 이름의 테이블에 포함시킬 겁니다. 그리고 그 테이블은 stage 의 sub-table 이 될 거구요.

아래 코드를 여러분 프로젝트에 복사해 넣으세요.


stage.paraGroups = {}
for g=1,stage.numChildren do
  if ( stage[g].distanceRatio ) then stage.paraGroups[#stage.paraGroups+1] = stage[g] end
end

  

이 코드를 보면 첫번째로 테이블을 정의합니다. 그리고 display groups 에 대해 stage 의 각 child 숫자 만큼 루프를 돌립니다. 그리고 if 문을 사용해서 “distanceRatio” parameter가 있는 경우에만 테이블에 집어 넣습니다.


4. Populate the World


다음 코드에서는 gradient background를 세팅할 겁니다. 그리고 our world 에 몇개의 샘플 객체들을 추가할 거구요. 이 코드들에 대해서는 일일이 설명하지는 않을께요. 여러분들은 여러분들 나름대로의 parallax world 를 만들실 거니까요. 아래에서 하나의 객체를 각 parallax layer 에 add 하는 것을 보실텐데요. 여러분은 많은 객체들과 이미지들을 추가하셔야 한다는 것만 기억해 두세요.


local cX = display.contentWidth/2 ; local cY = display.contentHeight/2
local bkgrad = graphics.newGradient( {42,17,10}, {0,0,0}, "up" )
local bk = display.newRect( 0,0,cX*2,cY*2 ) ; bk:setFillColor( bkgrad ) ; bk:toBack()

local object00 = display.newRect( back00,cX-16,cY-16,32,32 ) ;
    object00:setFillColor(150,0,50,120)
local object01 = display.newRect( back01,cX-32,cY-32,64,64 ) ;
    object01
:setFillColor(150,20,50,140)
local object02 = display.newRect( back02,cX-48,cY-48,96,96 ) ;
    object02
:setFillColor(150,40,50,160)
local object03 = display.newRect( back03,cX-64,cY-64,128,128 ) ;
    object03
:setFillColor(150,60,50,180)
local foreObject = display.newRect( foreground,cX-80,cY-80,160,160 ) ;
    foreObject
:setFillColor(150,80,50,200)


5. Implementing Touch and Drag

여러분이 움직일 수 없다면 이 scrollable world 는 소용이 없겠죠. 아래 함수는 screen touch 의 "began" 과 "moved" phases 를 사용해서 paraGroups table 안에 있는 모든 그룹들을 스크린 내에서 여러분이 drag 할 수 있도록 만들겁니다.

이 함수와 touch listener 를 여러분 프로젝트에 복사해 넣으세요.


local function touchScreen( event )
  local stageID = event.target
  local refGroup = stageID.refGroup ; local paraGroups = stageID.paraGroups
  local eventX = event.x ; local eventY = event.y

  if ( #paraGroups < 1 ) then return end

  if ( event.phase == "began" ) then

    for i=1,#paraGroups do
      paraGroups[i].offsetX = eventX - refGroup.x
      paraGroups[i].offsetY = eventY - refGroup.y
    end

  elseif ( event.phase == "moved" ) then

    local xDif = eventX - refGroup.offsetX
    local yDif = eventY - refGroup.offsetY

--If you are NOT limiting the boundaries of your world, comment out these 2 lines.
    if ( xDif < stageID.xMin ) then xDif = stageID.xMin
    elseif
( xDif > stageID.xMax ) then xDif = stageID.xMax end
    if ( yDif < stageID.yMin ) then yDif = stageID.yMin
    elseif ( yDif > stageID.yMax ) then yDif = stageID.yMax end

    for i=1,#paraGroups do
      local group = paraGroups[i]
      group.x = xDif * group.distanceRatio
      group.y = yDif * group.distanceRatio
      group = nil
    end
    xDif, yDif = nil,nil

  end

  stageID, refGroup, paraGroups, eventX, eventY = nil,nil,nil,nil,nil
  return true

end

stage:addEventListener( "touch", touchScreen )



이 코드에 대해서도 일일이 설명을 드리지는 않겠습니다. 단지 이 behavior를 summarize 할께요.


began phase에서 우리는 paraGroups table에 대해 루프를 돌립니다. 그리고 the foreground reference group 에 대해 각각 특정 X/Y 값을 세팅합니다. 이것은 core 1:1 group 의 포지션에 근거해서 각 layer들의 위치를 정해주기 위해 필요한 부분 입니다.


moved phase 는 실제 action 이 일어나는 곳입니다. 우선 첫번째로 어디에 유저가 touch 했는가에 따라 관련 group 들을 움직이기 위해 xDifyDif ”delta” values를 정해야 합니다. 그리고 바로 직전의 phase check 으로부터 얼마나 멀리 움직였는지도 정해야 하구요.


그 다음으로는 위의 Step #2 에서 정해 놓은 world boundary 들의 바깥으로 X, Y 포지션이 나갔는지 여부를 체크합니다. 4개 중에 하나라도 밖으로 나가게 되면 xDifyDif value 를 pre-adjust  합니다. 그렇게 함으로서 그 world 밖으로는 절대 나가는 일이 없게 되는거죠. 코드 안에 적어놨듯이 scrolling 의 제한을 주고 싶지 않으면 이 부분을 주석을 달 수도 있습니다. 


마지막으로는 paraGroups table에 루프를 돌리고 각각의 parallax layer의 위치를 조정합니다. 이 때 group 에서 정해 줬던 distanceRatio value에 따라 위치를 조정하게 됩니다. distance ratio 가 1.0 인 foreground group은 정확히 유저의 touch 를 따라서 움직이게 됩니다. 그리고 그 이외에 layer 들은 여러분이 정해 준 distance ratio 에 따라서 약간씩 다르게 움직입니다. 한번 ratio들을 바꾸고 나서 다시 시도해 보세요. 움직임이 다를 겁니다. 여러번 테스트 해 보시고 가장 그럴듯한 ratio 들을 정하셔서 사용하세요.



아주 간단하죠? 이제 몇개의 layer 든지 상관없이 scrolling touch-and-drag parallax world 를 구현할 수 있는 flexible 한 메소드를 구현했습니다. 이제 실전에서는 각각의 ratio 들만 조정해서 사용하시면 됩니다. 아니면 database 나 text file을 이용해서 dynamically 움직임들을 조정 할 수도 있죠.


6. Cleaning Up


마지막으로 layer references들을 clean up 하는 것을 잊지 마세요. 특히 여러분이 Storyboard 나 Director 와 같은 scene manager 를 사용하고 있다면 더 잊지 마셔야 됩니다. 각 scene manager 에서 사용하는 standard cleanup practices 를 사용하는 것 외에 parallax display groups 에 대한 references 를 가지고 있는 paraGroups table 을 clean up 하는 것도 중요합니다. scene 들이 바뀔 때마다 이 작업들이 이루어 지도록 해야 합니다. touch listener도 remove 하는 것 잊지 마시구요. (전체 메소드가 전체 scene 에서 작동하는 global level 이면 필요가 없겠지만요.)



for i=#stage.paraGroups,1,-1 do
  stage.paraGroups[i] = nil
end
stage:removeEventListener( "touch", touchScreen )


Looking Forward!


다음 튜토리얼에서는 이 메소드를 build 하고 dynamic 하게 parallax layer 를 zoom in/out 하는 간편한 zoom feature에 대해 다루겠습니다. 그 때까지 이 데모 project 를 구현하고 수정하고 테스트 해 보시고 질문이나 제안이 있으면 댓글 달아 주세요.



반응형

Dialog windows 사용하기

2012. 10. 17. 08:28 | Posted by 솔웅


반응형
Dialog windows


Display a dialog window


$.mobile.changePage () method는 overlapping windows를 display 하기 위해서 사용 될 수도 있습니다. 이 overlay 윈도우는 그 작업을 위해 data-role="dialog" attribute 를 가지고 있어야 합니다.


Use the $.mobile.changePage () to display a layered window


<!DOCTYPE html>

<html> 

<head> 

  <meta name=viewport content="user-scalable=no,width=device-width" />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=home>

  <div data-role=header>

    <h1>Home</h1>

  </div>


  <div data-role=content>

    <p> Window content 1 </p>  

    <a href=# id=link1> Goto window 2 </a>

  </div>

</div>


<div data-role=dialog id=win2>

  <div data-role=header>

    <h1>Window 2</h1>

  </div>


  <div data-role=content>

    <p> Window content 2 </p>  

  </div>

</div>

</body>

</html>


<script>


$("#link1").bind ("click", function (event)

{

  $.mobile.changePage ($("#win2"), { transition : "pop" });

});


</script>






tistory410_01.html


Close a dialog window


dialog 윈도우를 닫는것은 대개 jQuery Mobile에 의해 추가된 close button 을 클릭해서 닫게 됩니다. 그 외에도 윈도우의 content 안에 버튼을 넣어서 이 closing 메카니즘을 만들어서 사용해도 상관없습니다. 그러려면 button 을 처리하는 어떤 과정이 필요합니다. 윈도우에 연관된 <div>에서 dialog ("close") method를 call 하는 부분을 코딩해야 합니다.


Use a close button in the dialog window


<!DOCTYPE html>

<html> 

<head> 

  <meta name=viewport content="user-scalable=no,width=device-width" />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=home>

  <div data-role=header>

    <h1>Home</h1>

  </div>


  <div data-role=content>

    <p> Window content 1 </p>  

    <a href=# id=link1> Goto window 2 </a>

  </div>

</div>


<div data-role=dialog id=win2>

  <div data-role=header>

    <h1>Window 2</h1>

  </div>


  <div data-role=content>

    <p> Window content 2 </p>  

    <a id=close data-role=button> Close window </a>

  </div>

</div>

</body>

</html>


<script>


$("#link1").bind ("click", function (event)

{

  $.mobile.changePage ($("#win2"), { transition : "pop" });

});


$("#close").bind ("click", function (event)

{

  $("#win2").dialog ("close");

});


</script>






tistory410_02.html


Remove the close button in the dialog window


마지막으로 overlay window의 title bar 안에 jQuery Mobile 에 의해 add 된 close 버튼을 어떻게 remove 하는지에 대해 알아보겠습니다. 이것은 title bar에 있는 <a> element 와 관련이 있습니다. 그리고 selector $(this).find ("div: jqmData (role=header) a")를 통해서 접근될 수 있습니다. (만약 이것이 overlay window 라면요.)


우리는 이 element를 jQUery Mobile에 의해 overlay window 가 transforme 되기 위한 HTML 코드 이후에 접근할 수 있습니다. 이 때 dialogcreate event 와 견결 됩니다. 왜냐하면 overlay window 는 jQuery Mobile standard component dialog에 의해 handle 되기 때문입니다.


So we write:


Remove the close button in the dialog window


<!DOCTYPE html>

<html> 

<head> 

  <meta name=viewport content="user-scalable=no,width=device-width" />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=home>

  <div data-role=header>

    <h1>Home</h1>

  </div>


  <div data-role=content>

    <p> Window content 1 </p>  

    <a href=#win2 id=link1> Goto window 2 </a>

  </div>

</div>


<div data-role=dialog id=win2>

  <div data-role=header>

    <h1>Window 2</h1>

  </div>


  <div data-role=content>

    <p> Window content 2 </p>  

  </div>

</div>

</body>

</html>


<script>


$("#win2").bind ("dialogcreate", function ()

{

  $(this).find ("div:jqmData(role=header) a").hide ();

});


</script>



dialog window 도 (다른 윈도우들과 마찬가지로) pagecreate event를 받습니다.  하지만 이 이벤트는 dialogcreate event 이전에 받게 됩니다. jQuery Mobile 에 의해 HTML 이 transform 된것을 inform 하지 않는 거죠. 그래서 dialogcreate event 를 사용해야 되는 겁니다.




tistory410_03.html



이제 dialog 윈도우는 더 이상 close button 이 없습니다.




반응형