How do I implement a multi-touch pinch motion?
The pinch motion that you find in many iPhone apps is known as a 'gesture'. Apple don't provide support for specific gestures such as pinch leaving us as developers to implement them ourselves from touch messages. This does mean we have to do a little math but we'll work through that together in this lesson.
The pinch gesture is often used to shrink and grow items like photos. In this lesson we'll use the pinch gesture to scale a plain graphic.
* The image scaling algorithms in LiveCode have not been optimized for the iPhone yet meaning that dynamic image scaling is quite slow on the device. So in this example we are scaling a graphic which is very fast.
The stack used in this lesson can be found here: https://tinyurl.com/s3wnvnfa
1) Create a new stack, name it and save it
2) Stop the stack from being resized
3) Set the width and height of the stack to 320 x 460
1) Create a square graphic
2) Set its name to 'square'
3) Go to the colors & patterns inspector and set the 'backgroundColor' to one you like
We're going to leave the interface for a moment and look at the basic messages we receive from Rev when touches start, end and move.
on touchStart pTouchId # Sent each time a new touch is started end touchStart on touchEnd pTouchId # Sent each time a touch ends end touchEnd on touchMove pTouchId, pX, pY # Sent when any touch moves end touchMove
If a user places two fingers on the device, two touch starts messages will be sent to your stack. You will also be sent a touch ID so you can tell they are different.
Copy this script to the card or stack.
1) Looks for two touches
2) Calculates the distance between the two touches to work out if they are getting closer or further away
3) Scales the image according to the distance of the two touches,
local sTouchArray, sFRAMEWIDTH, sFRAMEHEIGHT local tempimagex, tempimagey, focusx, focusy, pinchflag on touchStart pId, pX, pY put the width of graphic "square" into sFRAMEWIDTH put the height of graphic "square" into sFRAMEHEIGHT put item 1 of the loc of graphic "square" into tempimagex put item 2 of the loc of graphic "square" into tempimagey end touchStart on touchEnd pId if the number of lines of the keys of sTouchArray is 1 then put false into pinchflag end if delete variable sTouchArray[pId] end touchEnd on touchMove pId, pX, pY if sTouchArray[pId]["startloc"] is empty then put (pX & comma & pY) into sTouchArray[pId]["startloc"] end if put (pX & comma & pY) into sTouchArray[pId]["currentloc"] -- script if user wants to move image around: if the number of lines of the keys of sTouchArray is 1 then --First lets get the data out of the array put line 1 of the keys of sTouchArray into tPointOne put sTouchArray[tPointOne]["startloc"] into tStartLoc if tStartLoc1 is not empty then put item 1 of tStartLoc into tempstartx put item 2 of tStartLoc into tempstarty put tempstartx-pX into tempdiffx put tempstarty-pY into tempdiffy put tempimagex-tempdiffx into tempimagecurrentx put tempimagey-tempdiffy into tempimagecurrenty if pinchflag is not true then set the loc of graphic "square" to tempimagecurrentx, tempimagecurrenty end if end if end if -- script when user want to pinch and zoom: if the number of lines of the keys of sTouchArray is 2 then # First lets get the data out of the array put line 1 of the keys of sTouchArray into tPointOne put line 2 of the keys of sTouchArray into tPointTwo # First lets calculate the size of the picture base on the distance # between the two touch points put sTouchArray[tPointOne]["startloc"] into tStartLoc1 put sTouchArray[tPointTwo]["startloc"] into tStartLoc2 if tStartLoc1 is not empty and tStartLoc2 is not empty then put true into pinchflag -- to avoid a jump in location when 1 finger is removed -- calculate the focus point of the zoom, it is located between the two starting touchpoints put item 1 of tStartLoc1 into focusx1 put item 2 of tStartLoc1 into focusy1 put item 1 of tStartLoc2 into focusx2 put item 2 of tStartLoc2 into focusy2 put focusx1 + round ((focusx2-focusx1)/2) into focusx put focusy1 + round ((focusy2-focusy1)/2) into focusy put resizeDistance(tStartLoc1, tStartLoc2) into tStartDistance put resizeDistance(sTouchArray[tPointOne]["currentloc"], sTouchArray[tPointTwo]["currentloc"]) into tCurrentDistance resizeGraphic tStartDistance, tCurrentDistance end if end if end touchMove function resizeDistance pLoc1, pLoc2 local dy, dx, tDistance put item 2 of pLoc1 - item 2 of pLoc2 into dy put item 1 of pLoc1 - item 1 of pLoc2 into dx put sqrt((dy*dy) + (dx*dx)) into tDistance return tDistance end resizeDistance on resizeGraphic pStartDistance, pNewDistance lock screen # Work out the percentage change between the old and new image put round((pNewDistance / pStartDistance) * 100) into tPercentage # Calculate the new width and height set the width of graphic "square" to round(sFRAMEWIDTH * (tPercentage / 100)) set the height of graphic "square" to round(sFRAMEHEIGHT * (tPercentage / 100)) -- first scale the coordinates of the focus point put tempimagex + round((focusx-tempimagex) * (tPercentage / 100)) into focusxnew put tempimagey + round((focusy-tempimagey) * (tPercentage / 100)) into focusynew -- getting the difference between original and scaled focuspoint put focusx - focusxnew into focusxdiff put focusy - focusynew into focusydiff -- calculate the new location of the graphic put tempimagex + focusxdiff into locxnew put tempimagey + focusydiff into locynew set the loc of graphic "square" to locxnew,locynew unlock screen end resizeGraphic