Share Your Code

Pinch-zoom example

Posted by ldanadrian, Posted on September 30, 2011

It's simple to use, just do something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
--hide the statusbar
display.setStatusBar( display.HiddenStatusBar )
 
--include the mtouch library
local mtouch = require( "mtouch" )
 
--create the zoom object - an image
local image     = nil
 
local function OnZoomIn( event )
 --grow our image
 image.xScale = image.xScale * 1.01
 image.yScale = image.yScale * 1.01
 print("new width="..image.contentWidth)
end
 
local function OnZoomOut( event )
 --shrink our image
 image.xScale = image.xScale / 1.01
 image.yScale = image.yScale / 1.01
 print("new width="..image.contentWidth)
end
 
local function main()
 --add the image
 image = display.newImage("image.jpg" )
 --set the imaage to the center of the device
 image.x = display.contentWidth  * 0.5
 image.y = display.contentHeight * 0.5
 --create the pinch zoom over our image
 mtouch.setZoomObject( image )
 mtouch.setOnZoomIn  ( OnZoomIn  ) 
 mtouch.setOnZoomOut ( OnZoomOut  )
 --add the fictive touch for the simulator - comment this if you are deploying to device!
 mtouch.setFictiveSimulatorTouch( 100, 100 )
end
 
main()

And the mtouch module:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
module(..., package.seeall)
-- activate multitouch
system.activate( "multitouch" )
 
-- math helpers
local sqrt         = math.sqrt
local abs     = math.abs
-- current touches
local touches      = {}
-- last zoom distance - I use this to compare with current distance
-- if its smaller then zoom out, else  zoom in
local lastDistance = 0
local zoomObject   = nil      --the zoom object
local OnZoomIn     = nil      --the zoom in event
local OnZoomOut    = nil      --the zoom out event
--fictive touch
local fictiveTouch = {}
fictiveTouch.id = "QHHJGL10"
 
-----------------------------------------------
-- counts a dictionary
-----------------------------------------------
local function CountDictionary(dict)
 local ret = 0
 for k, v in pairs(dict) do
  ret = ret + 1
 end
 return ret
end
 
-----------------------------------------------
-- returns an element at some index in a dictionary
-----------------------------------------------
local function GetDictElAtIndex( dict, index )
 local temp = 0
 local ret  = nil
 for k, v in pairs(dict) do
  if( temp == index ) then
   ret   = v
   break
  end
  temp   = temp + 1
 end
 return ret
end
 
-----------------------------------------------
-- update x and y for a specific touch-event
-----------------------------------------------
local function UpdateTouch( event )
 local id  = event.id
 local obj = event.target
 local  x  = event.x
 local  y  = event.y
 if touches[id] then
  touches[id].x = x
  touches[id].y = y
 end
end
 
-----------------------------------------------
-- calculate the distance between two touches 
-----------------------------------------------
local function DistanceBetween2T( t1, t2 )
 local ret = 0
 local deltax = t2.x - t1.x
 local deltay = t2.y - t1.y
 ret          = sqrt( deltax * deltax + deltay * deltay )
 return ret
end
-----------------------------------------------
-- touch listener
-----------------------------------------------
function on_touch( event )
 local ret = false
 if     event.phase == "began" then
  --register this touch
  touches[ event.id ] = event
 elseif event.phase == "moved" then
  UpdateTouch(event)
  --verify if i have at least 2 touches
  if( CountDictionary(touches) >= 2 ) then
   zoomObject.touching = true
   --gets the first 2 touches and calculate the distance between them
   local touch1 = GetDictElAtIndex( touches, 0 )
   local touch2 = GetDictElAtIndex( touches, 1 )
   local dist   = DistanceBetween2T( touch1, touch2 )
   --
   local args        = {}
   args.distance     = dist
   args.lastdistance = lastDistance
   args.difference   = abs( lastDistance - dist )
   args.touch1       = touch1
   args.touch2       = touch2
   if lastDistance ~= -1 then
    if dist < lastDistance then 
     --zoom out
     if OnZoomOut ~= nil then OnZoomOut( args ) end
    else
     --zoom in
     if OnZoomIn  ~= nil then  OnZoomIn( args ) end
    end
    ret = true
   end
   --save the lastdistance
   lastDistance = dist
  end
 elseif event.phase == "ended" then
  --remove this touch from list
  touches[ event.id ]  = nil
  lastDistance    = -1
  zoomObject.touching = false
 end
 return ret
end
 
-----------------------------------------------
-- properties
-----------------------------------------------
function setZoomObject( obj )
 zoomObject          = obj
 zoomObject.touching = false
 -- register table listener
 zoomObject:addEventListener( "touch", on_touch )
end
 
 
-----------------------------------------------
-- returns current zoom object
-----------------------------------------------
function getZoomObject() 
 return zoomObject
end
 
-----------------------------------------------
-- returns the number of current touches
-----------------------------------------------
function getNrTouches() 
 return CountDictionary(touches)
end
 
-----------------------------------------------
-- sets the zoomin event function
-----------------------------------------------
function setOnZoomIn( event )
 OnZoomIn = event
end
 
-----------------------------------------------
-- sets the zoomout event function
-----------------------------------------------
function setOnZoomOut( event )
 OnZoomOut = event
end
 
-----------------------------------------------
-- for the simulator: create a fictive touch
-----------------------------------------------
function setFictiveSimulatorTouch( x, y)
 fictiveTouch.x = x; fictiveTouch.y = y
 touches[ fictiveTouch.id ] = fictiveTouch
 fictiveTouch.rect = display.newRect( fictiveTouch.x, fictiveTouch.y, 20, 20 )
end
 
-----------------------------------------------
-- for the simulator: removes a fictive touch
-----------------------------------------------
function removeFictiveSimulatorTouch()
 touches[ fictiveTouch.id ] = nil
 fictiveTouch.rect:removeSelf()
end
 
-----------------------------------------------
-- clean me
-----------------------------------------------
function clean()
 zoomObject:removeEventListener( "touch", on_touch )
end


Replies

sembleton
User offline. Last seen 15 weeks 2 days ago. Offline
Joined: 22 Aug 2011

this works nicely...I need to be able to distinguish between a single touch and a multitouch on the same object...any ideas?

Thanks!!