PageRenderTime 26ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/code/_libs/Slider.lua

https://bitbucket.org/AleksanderGrzyb/kernstop-application
Lua | 223 lines | 90 code | 56 blank | 77 comment | 28 complexity | 7a59ff67166192f2ad501bd399137897 MD5 | raw file
  1. --module(..., package.seeall) --ACTIVATE THIS LINE IF USING DIRECTOR; REMOVE IF NOT
  2. local math_abs = math.abs
  3. local cw, ch, ox, oy = display.contentWidth, display.contentHeight, math_abs(display.screenOriginX), math_abs(display.screenOriginY)
  4. --"ox" and "oy" calculate the X/Y 'offset' at different screen proportions, i.e. iPhone vs. Galaxy Tab vs. iPad
  5. ------------------------
  6. --Setup Display Groups
  7. ------------------------
  8. --IF -NOT- USING DIRECTOR
  9. local sliderGroup = display.newGroup()
  10. local dotGroup = display.newGroup()
  11. --IF USING DIRECTOR
  12. --local localGroup = display.newGroup()
  13. --local sliderGroup = display.newGroup() ; localGroup:insert(sliderGroup)
  14. --local dotGroup = display.newGroup() ; localGroup:insert(dotGroup)
  15. ------------------------
  16. --Forward Declarations
  17. ------------------------
  18. local pageDots = {} --"container" table to reference dots (which indicate current slide position, as on iOS)
  19. local slideDist = cw+ox+ox --total left-to-right distance of a slide
  20. local slideIndex = 0
  21. local touchPos = 0
  22. local lastPos = 0
  23. local touchTime = 0
  24. --A 'swipe' is basically just a SHORT (distance) and FAST (time) screen touch. The variable "coreSwipeDist" sets the DISTANCE aspect
  25. --of a swipe. Default in this module is 1/10th the screen width. Adjust if you desire a longer or shorter distance to register as a 'swipe'
  26. --The variable "coreSwipeTime" is the TIME aspect (in milliseconds) which registers as a swipe. If the user's touch is longer than this value,
  27. --this module considers that motion a DRAG/HOLD, not a swipe. Adjust this time value to your desire.
  28. --NOTE!!! After you determine the values that feel right to you, I suggest you replace these variables below (in function "screenMotion")
  29. --with the hard-coded values, so Corona doesn't need to waste effort on upvalue lookups.
  30. local coreSwipeDist = cw/10
  31. local coreSwipeTime = 300
  32. --------------------
  33. local slideTrans = 0 --the tween transition variable; when set to 0, transition is not happening.
  34. local maxSlideIndex = 0 --max number of slides, to be automatically set later.
  35. local resist = 1
  36. ------------------------------
  37. --Update slide position dots
  38. ------------------------------
  39. --If you choose to eliminate the dots, you may remove this entire function, and all references to "pageDots"
  40. local function updateDots( sIndex )
  41. for d=1,#pageDots do
  42. if ( d == sIndex+1 ) then pageDots[d].alpha = 1.0 else pageDots[d].alpha = 0.3 end
  43. end
  44. end
  45. -----------------------------
  46. --Complete slide transition
  47. -----------------------------
  48. --Line 70: Cancels any existing tween transition (probably not necessary because transition is also cancelled on touch "began" phase)
  49. --Line 71: Snaps the slide to its proper ending position (probably not necessary, but a minor fail-safe)
  50. --Line 72: Calls the function to update the slide position dots.
  51. local function transComplete( event )
  52. transition.cancel( slideTrans ) ; slideTrans = 0
  53. local targetX = (slideIndex*-slideDist) ; if ( sliderGroup.x ~= targetX ) then sliderGroup.x = targetX end
  54. updateDots( slideIndex )
  55. end
  56. ----------------------------
  57. --Transition to next slide
  58. ----------------------------
  59. local function slideTween( targetX )
  60. --Overall transition time is 400 milliseconds by default. Adjust if you desire slower or faster slide movement.
  61. local transTime = ( (math_abs(sliderGroup.x-targetX))/slideDist) * 400
  62. if ( slideTrans ~= 0 ) then transition.cancel( slideTrans ) ; slideTrans = 0 end
  63. slideTrans = transition.to( sliderGroup, { x=targetX, time=transTime, transition = easing.outQuad, onComplete=transComplete } )
  64. end
  65. ------------------------------------
  66. --'Go to slide' function, optional
  67. ------------------------------------
  68. --This function can be used to either "snap" or "move" to a specific slide in your stack.
  69. --Usage: FOR SNAP: gotoSlide( [slide], "snap" )
  70. -- FOR MOVE: gotoSlide( [slide], "move" )
  71. --Potential usage for this function: if you save the current slide position somewhere in your code (or in an external text file), you
  72. --can retrieve that value later (i.e. on a future application load) to snap to the same slide that the user was previously viewing.
  73. --Another possible usage: Call this function once using "snap" to go to a specific slide (perhaps a level screen). Then call the function
  74. --again (after an elapsed time) and use "move" to drift to the next slide, indicating that the user has "unlocked" a new level.
  75. local function gotoSlide( targetSlide, method )
  76. if ( slideTrans ~= 0 ) then transition.cancel( slideTrans ) ; slideTrans = 0 end
  77. local si = targetSlide-1 ; slideIndex = si ; local destX = (si*-slideDist)
  78. if ( method == "snap" ) then sliderGroup.x = destX ; updateDots( si )
  79. else slideTween( destX )
  80. end
  81. end
  82. -----------------------------------------------
  83. --Core touch sensor + movement/swipe function
  84. -----------------------------------------------
  85. local function screenMotion( event )
  86. local phase = event.phase ; local eventX = event.x
  87. if ( "began" == phase ) then
  88. if ( slideTrans ~= 0 ) then transition.cancel( slideTrans ) ; slideTrans = 0 end
  89. touchPos = eventX ; lastPos = eventX ; touchTime = event.time
  90. elseif ( "moved" == phase ) then
  91. local dist = eventX-lastPos ; local res = resist
  92. --"resist" is the ratio (percentage) for the end-of-stack spring resistance effect. At either end of your stack of slides, if the
  93. --user tries to slide further, this module "resists" that movement to indicate that there are no more slides, just like iOS! :)
  94. --Default is "0.3" on line 126 ; you may change this, but 0.5 or higher risks the ability to move the slide off the screen!
  95. if ( ( slideIndex == 0 and dist > 0 ) or ( slideIndex == maxSlideIndex and dist < 0 ) ) then res = 0.3 else res = 1 end
  96. sliderGroup.x = sliderGroup.x+(dist*res) ; lastPos = eventX ; resist = res
  97. else
  98. local motionTime = system.getTimer()-touchTime
  99. local dist = eventX-touchPos ; local swipeDist = math_abs( dist )
  100. local overallDist = math_abs( sliderGroup.x+(slideIndex*slideDist) )
  101. local goNextSlide = false
  102. if ( resist ~= 1 ) then goNextSlide = false
  103. elseif ( motionTime <= coreSwipeTime and swipeDist >= coreSwipeDist ) then goNextSlide = true
  104. elseif ( motionTime > coreSwipeTime and overallDist >= slideDist*0.5 ) then goNextSlide = true end
  105. if ( goNextSlide == true and dist < 0 and resist == 1 ) then slideIndex = slideIndex+1
  106. elseif ( goNextSlide == true and dist > 0 and resist == 1 ) then slideIndex = slideIndex-1 end
  107. slideTween( slideIndex*-slideDist )
  108. end
  109. end
  110. ---------------------------------------
  111. --Initial setup, slide creation, etc.
  112. ---------------------------------------
  113. local function initSetup()
  114. --You may create your slides individually, or in a loop. Each slide is a display group, so objects placed within each "slide" are
  115. --in positional reference to that slide! If you set something to "x=20", it will be x=20 in relation to the slide, not the screen.
  116. --IMPORTANT!!!!! Every element that you add to a slide (images, text, whatever) MUST be added to its display group "thisSlideGroup".
  117. local thisSlideGroup
  118. --create 4 sample slides using a loop:
  119. for i=1,4 do
  120. thisSlideGroup = display.newGroup() --IMPORTANT!!! Create a new display group for each slide!
  121. --localGroup:insert(thisSlideGroup) --ACTIVATE THIS LINE IF USING DIRECTOR
  122. -- slide background (image or just a simple rect in this example)
  123. local rect = display.newRect( -ox, -oy, cw+ox+ox, ch+oy+oy-110 )
  124. thisSlideGroup:insert( rect )
  125. rect:setFillColor( i*55, 255-i*55, 220 )
  126. -- add more elements to slide
  127. local txt = display.newText( " SLIDE "..i, 0, 0, native.systemFontBold, 48 )
  128. thisSlideGroup:insert( txt )
  129. txt:setTextColor( 255, 255, 255 )
  130. txt:setReferencePoint(display.CenterLeftReferencePoint) ; txt.x = 0 ; txt.y = 128
  131. sliderGroup:insert( thisSlideGroup )
  132. thisSlideGroup.x = ((sliderGroup.numChildren-1)*slideDist)
  133. end
  134. maxSlideIndex = sliderGroup.numChildren-1
  135. --Configure slide position dots. If using images for the dots (preferable), you should create an image which is designed for the
  136. --proper resolution in your app. You may also use Corona's "display.newCircle" function, but the dots will not be anti-aliased and
  137. --thus might appear slightly jagged.
  138. local pageDots = pageDots
  139. for i = 1,maxSlideIndex+1 do
  140. --local dot = display.newCircle( dotGroup, i*40, 0, 6 ) ; dot:setFillColor(255,255,255)
  141. local dot = display.newImageRect( dotGroup, "dot.png", 12, 12 ) ; dot.x = i*40
  142. pageDots[#pageDots+1] = dot
  143. end
  144. dotGroup:setReferencePoint(display.BottomCenterReferencePoint) ; dotGroup.x = cw*0.5 ; dotGroup.y = ch-50+oy
  145. updateDots( 0 )
  146. sliderGroup:addEventListener( "touch", screenMotion ) --core touch listener (only touch listener)
  147. end
  148. ---------------------
  149. --Clean-up function
  150. ---------------------
  151. --You may use this function to clean up the dots and touch listener, or borrow these code elements to use elsewhere for the same purpose.
  152. --IMPORTANT!!! If you are using Director, you do NOT need to write any further code to clean up the slides. Because each slide is added
  153. --to Director's "localGroup", Director's recursive clean-up function will clean up the elements within each group AND the group itself.
  154. --
  155. --If you are NOT using Director, you might want to copy Director's recursive cleanup function to remove the slides & contents.
  156. function cleanUp()
  157. sliderGroup:removeEventListener( "touch", screenMotion )
  158. if ( slideTrans ~= 0 ) then transition.cancel( slideTrans ) end ; slideTrans = nil
  159. for d=#pageDots,1,-1 do local del = pageDots[d] ; pageDots[d] = nil ; display.remove( del ) ; del = nil end
  160. pageDots = nil
  161. end
  162. --Call initial setup function
  163. initSetup()
  164. --ACTIVATE THE FOLLOWING FUNCTION IF USING DIRECTOR; REMOVE IF NOT
  165. --function new()
  166. --return localGroup
  167. --end