Pinch Zoom Gesture

Features demonstrated:

Locations events, buttons, touch

Code:

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
-- activate multitouch
system.activate( "multitouch" )
 
-- add bkgd image to screen
local background = display.newImage( "aquariumbackgroundIPhone.jpg", 0, 0 )
 
local function calculateDelta( previousTouches, event )
        local id,touch = next( previousTouches )
        if event.id == id then
                id,touch = next( previousTouches, id )
                assert( id ~= event.id )
        end
 
        local dx = touch.x - event.x
        local dy = touch.y - event.y
        return dx, dy
end
 
-- create a table listener object for the bkgd image
function background:touch( event )
        local result = true
 
        local phase = event.phase
 
        local previousTouches = self.previousTouches
 
        local numTotalTouches = 1
        if ( previousTouches ) then
                -- add in total from previousTouches, subtract one if event is already in the array
                numTotalTouches = numTotalTouches + self.numPreviousTouches
                if previousTouches[event.id] then
                        numTotalTouches = numTotalTouches - 1
                end
        end
 
        if "began" == phase then
                -- Very first "began" event
                if ( not self.isFocus ) then
                        -- Subsequent touch events will target button even if they are outside the stageBounds of button
                        display.getCurrentStage():setFocus( self )
                        self.isFocus = true
 
                        previousTouches = {}
                        self.previousTouches = previousTouches
                        self.numPreviousTouches = 0
                elseif ( not self.distance ) then
                        local dx,dy
 
                        if previousTouches and ( numTotalTouches ) >= 2 then
                                dx,dy = calculateDelta( previousTouches, event )
                        end
 
                        -- initialize to distance between two touches
                        if ( dx and dy ) then
                                local d = math.sqrt( dx*dx + dy*dy )
                                if ( d > 0 ) then
                                        self.distance = d
                                        self.xScaleOriginal = self.xScale
                                        self.yScaleOriginal = self.yScale
                                        print( "distance = " .. self.distance )
                                end
                        end
                end
 
                if not previousTouches[event.id] then
                        self.numPreviousTouches = self.numPreviousTouches + 1
                end
                previousTouches[event.id] = event
 
        elseif self.isFocus then
                if "moved" == phase then
                        if ( self.distance ) then
                                local dx,dy
                                if previousTouches and ( numTotalTouches ) >= 2 then
                                        dx,dy = calculateDelta( previousTouches, event )
                                end
        
                                if ( dx and dy ) then
                                        local newDistance = math.sqrt( dx*dx + dy*dy )
                                        local scale = newDistance / self.distance
                                        print( "newDistance(" ..newDistance .. ") / distance(" .. self.distance .. ") = scale("..  scale ..")" )
                                        if ( scale > 0 ) then
                                                self.xScale = self.xScaleOriginal * scale
                                                self.yScale = self.yScaleOriginal * scale
                                        end
                                end
                        end
 
                        if not previousTouches[event.id] then
                                self.numPreviousTouches = self.numPreviousTouches + 1
                        end
                        previousTouches[event.id] = event
 
                elseif "ended" == phase or "cancelled" == phase then
                        if previousTouches[event.id] then
                                self.numPreviousTouches = self.numPreviousTouches - 1
                                previousTouches[event.id] = nil
                        end
 
                        if ( #previousTouches > 0 ) then
                                -- must be at least 2 touches remaining to pinch/zoom
                                self.distance = nil
                        else
                                -- previousTouches is empty so no more fingers are touching the screen
                                -- Allow touch events to be sent normally to the objects they "hit"
                                display.getCurrentStage():setFocus( nil )
 
                                self.isFocus = false
                                self.distance = nil
                                self.xScaleOriginal = nil
                                self.yScaleOriginal = nil
 
                                -- reset array
                                self.previousTouches = nil
                                self.numPreviousTouches = nil
                        end
                end
        end
 
        return result
end
 
-- Determine if running on Corona Simulator
--
local isSimulator = "simulator" == system.getInfo("environment")
 
-- Multitouch Events not supported on Simulator
--
if isSimulator then
        msg = display.newText( "Multitouch not supported on Simulator!", 0, 20, "Verdana-Bold", 14 )
        msg.x = display.contentWidth/2          -- center title
        msg.y = display.contentHeight/2         -- center title
        msg:setTextColor( 255,255,0 )
end
 
-- register table listener
background:addEventListener( "touch", background )