Good pinch-to-zoom in image object?
Brian Milby
brian at milby7.com
Sat Jan 27 17:11:02 EST 2018
Thanks!
I guess it is time to set up a GitHub repo for stuff I work on. I think
this would be a good thing to post as a behavior stack only script.
On Sat, Jan 27, 2018 at 1:48 PM Richard Gaskin via use-livecode <
use-livecode at lists.runrev.com> wrote:
> Brian Milby wrote:
>
> > Here's what I came up with. It is a little slow though. It's pretty
> > much a port of the code that I linked. I had to adapt to the way move
> > events are issued in LC (particularly that a touch start does not
> > include coordinates). I also added the ability to continue moving
> > when a zoom stops (only one touch ended). I initially was calling the
> > "updateImage" handler using send in time (and checking pending
> > messages to avoid calling multiple times), but the code is fast enough
> > to not benefit from that (adding delay made it less smooth, the
> > "updateImage" handler always seemed to finish before another move
> > event was queued).
> >
> > I put the code in the graphic. I called the "initGraphic" handler
> > from the card preOpenCard handler.
>
> Very kind of you, Brian. Thanks! Much obliged.
>
> I just gave it a whirl and it seems to work rather well. MUCH better
> for me than embedding an entire browser app inside my app just to get a
> good pinch.
>
> Since I was working on an image rather than a graphic, I modded the
> script to use a script-local object specifier rather than the hard-wired
> graphic reference, then added a mouseDown handler to trigger your init
> so I could test it easily.
>
> While I was at it I re-wrapped a few things to hopefully fit better here
> for others to easily copy-n-paste.
>
> Thanks again - it's nicely done.
>
> @Michael Doub: another candidate for MasterLib?
>
> --
> Richard Gaskin
> Fourth World Systems
>
>
> ------
>
>
> local panning, \
> zooming, \
> startX0, startY0, \
> startX1, startY1, \
> endX0, endY0, \
> endX1, endY1, \
> startDistanceBetweenFingers, \
> endDistanceBetweenFingers, \
> pinchRatio, \
> imgWidth, imgHeight, \
> currentContinuousZoom, \
> currentOffsetX, currentOffsetY, \
> currentWidth, currentHeight, \
> newContinuousZoom, \
> newHeight, newWidth, \
> newOffsetX, newOffsetY, \
> centerPointStartX, centerPointStartY, \
> centerPointEndX, centerPointEndY, \
> translateFromZoomingX, translateFromZoomingY, \
> translateFromTranslatingX, translateFromTranslatingY, \
> translateTotalX, translateTotalY, \
> percentageOfImageAtPinchPointX, \
> percentageOfImageAtPinchPointY, \
> sTouchArray, sTouch0, sTouch1
>
> local sZoomObj
>
> on mouseDown
> put the long id of me into sZoomObj -- Change this to specify object
> initGraphic
> end mouseDown
>
>
> on initGraphic
> local tLoc
> put the width of sZoomObj into imgWidth
> put the height of sZoomObj into imgHeight
> put 1.0 into currentContinuousZoom
> put the left of sZoomObj into currentOffsetX
> put the top of sZoomObj into currentOffsetY
> put imgWidth into currentWidth
> put imgHeight into currentHeight
> end initGraphic
>
> on touchMove pID, pX, pY
> -- capture current position
> put pX into sTouchArray[pID]["x"]
> put pY into sTouchArray[pID]["y"]
>
> -- since the touch start doesn't include location, need to handle
> -- the calculations here
> if sTouchArray[pID]["started"] is empty then
> put true into sTouchArray[pID]["started"]
> if the number of lines of the keys of sTouchArray is 1 then
> put pID into sTouch0
> put pX into startX0
> put pY into startY0
> else if the number of lines of the keys of sTouchArray is 2 then
> put pID into sTouch1
> put sTouchArray[sTouch0]["x"] into startX0
> put sTouchArray[sTouch0]["y"] into startY0
> put pX into startX1
> put pY into startY1
> put ((startX0 + startX1) / 2.0) into centerPointStartX
> put ((startY0 + startY1) / 2.0) into centerPointStartY
> put (centerPointStartX - currentOffsetX) / currentWidth \
> into percentageOfImageAtPinchPointX
> put (centerPointStartY - currentOffsetY) / currentHeight \
> into percentageOfImageAtPinchPointY
> put sqrt((startX1-startX0)^2 + (startY1-startY0)^2) \
> into startDistanceBetweenFingers
> end if
> updatePanZoomState
> exit touchMove
> end if
>
> -- record the end touch locations for the move
> if panning then
> put pX into endX0
> put pY into endY0
> else if zooming then
> put sTouchArray[sTouch0]["x"] into endX0
> put sTouchArray[sTouch0]["y"] into endY0
> put sTouchArray[sTouch1]["x"] into endX1
> put sTouchArray[sTouch1]["y"] into endY1
> end if
>
> updateImage
> end touchMove
>
> on touchEnd pID
> put true into sTouchArray[pID]["ended"]
> updateImage
> end touchEnd
>
> on updateImage
> lock screen
> if panning then
> put endX0 - startX0 into translateFromTranslatingX
> put endY0 - startY0 into translateFromTranslatingY
> put currentOffsetX + translateFromTranslatingX into newOffsetX
> put currentOffsetY + translateFromTranslatingY into newOffsetY
> else if zooming then
> -- Calculate current distance between points to get new-to-old
> -- pinch ratio and calc width and height
> put sqrt((endX1-endX0)^2 + (endY1-endY0)^2) \
> into endDistanceBetweenFingers
> put endDistanceBetweenFingers/startDistanceBetweenFingers \
> into pinchRatio
> put pinchRatio * currentContinuousZoom into newContinuousZoom
> put imgWidth * newContinuousZoom into newWidth
> put imgHeight * newContinuousZoom into newHeight
>
> -- Get the point between the two touches, relative to upper-left
> -- corner of image
> put ((endX0 + endX1) / 2.0) into centerPointEndX
> put ((endY0 + endY1) / 2.0) into centerPointEndY
>
> -- This is the translation due to pinch-zooming
> put (currentWidth - newWidth) * percentageOfImageAtPinchPointX \
> into translateFromZoomingX
> put (currentHeight - newHeight) * percentageOfImageAtPinchPointY \
> into translateFromZoomingY
>
> -- And this is the translation due to translation of the
> -- centerpoint between the two fingers
> put centerPointEndX - centerPointStartX into \
> translateFromTranslatingX
> put centerPointEndY - centerPointStartY into \
> translateFromTranslatingY
>
> -- Total translation is from two components:
> -- (1) changing height and width from zooming and
> -- (2) from the two fingers translating in unity
> put translateFromZoomingX + translateFromTranslatingX \
> into translateTotalX
> put translateFromZoomingY + translateFromTranslatingY \
> into translateTotalY
>
> -- the new offset is the old/current one plus the total
> -- translation component
> put currentOffsetX + translateTotalX into newOffsetX
> put currentOffsetY + translateTotalY into newOffsetY
>
> -- Set the image attributes on the card
> set the width of sZoomObj to newWidth
> set the height of sZoomObj to newHeight
> end if
> set the left of sZoomObj to newOffsetX
> set the top of sZoomObj to newOffsetY
>
> -- clear touch array for ended touches after updating
> repeat for each key tKey in sTouchArray
> if sTouchArray[tKey]["ended"] then
> if tKey is sTouch0 then
> put sTouch1 into sTouch0
> put endX1 into endX0
> put endY1 into endY0
> end if
> if panning or zooming then
> put newOffsetX into currentOffsetX
> put newOffsetY into currentOffsetY
> end if
> if zooming then
> put newWidth into currentWidth
> put newHeight into currentHeight
> put newContinuousZoom into currentContinuousZoom
> put endX0 into startX0
> put endY0 into startY0
> end if
> delete variable sTouchArray[tKey]
> end if
> end repeat
> updatePanZoomState
> unlock screen
> end updateImage
>
> on updatePanZoomState
> put false into panning
> put false into zooming
> if the number of lines of the keys of sTouchArray is 1 then
> put true into panning
> else if the number of lines of the keys of sTouchArray is 2 then
> put true into zooming
> end if
> end updatePanZoomState
>
>
>
>
> _______________________________________________
> use-livecode mailing list
> use-livecode at lists.runrev.com
> Please visit this url to subscribe, unsubscribe and manage your
> subscription preferences:
> http://lists.runrev.com/mailman/listinfo/use-livecode
>
More information about the use-livecode
mailing list