Think LiveCode can’t be sexy? It can be when you use it to swipe through photos and rate them based on whatever fancy strikes you. This article will describe how to build a Tinder-style photo rating behavior that uses swipe gestures to approve or reject photos (this structure is often called a “card stack” in web development circles). Swiping a photo triggers dragging that provides two levels of user feedback and can be customized.



Before you get started, you’ll need to get yourself a copy FontAwesome, a free glyph font (also known as an icon font) that contains hundreds of useful icons for use on web sites and in apps. Download the font and load it on your system so that LiveCode has access to all the tasty icons.

Also, note that this demo was built using LiveCode 7 on Mac OS X.



Now, if we’re going to build a sexy photo rating app, we need to start with a sexy name. Since this app is going to rely heavily on swiping, let’s do what all the trendy startups do and choose a name without vowels: swypr.

Sweet. Now we can hire some Silicon Valley interns to get on the phones and start hitting up venture capitalists with our wicked cool app idea. But if we’re going to pitch VC’s, we’ll need to build a demo to show the concept. To help you with this important task, a prototype stack has been made available for you, so you can get investors drooling and throwing money at you.

To view the stack in LiveCode, copy the following line and execute it in your LiveCode message box:

Once the stack has loaded, start swiping, er, swypng. You’ll see that swiping right tints the photo green and stamps it with a thumbs up icon (keeper), while swiping left tints the photo red and flags it with your disapproval (as if). Notice that the photo can be dragged anywhere on the card and rotates in the direction of the swipe. Sexy, right? There’s also a “change my mind” threshold that will send the photo back to the central starting point if the swipe distance is less than a minimum value.

This direct interaction combined with image rotation makes for a more visceral and satisfying user experience, compared to simply tapping a button. One might even call it — you guessed it: “sexy.”



Here’s a representation of the app structure which is isn’t particularly complicated, but will illustrate how things are arranged.


The photo group indicated has a behavior assigned to it that handles all the interaction, while code in the card script manages the display of the photos. Using a behavior script isn’t required, but it works nicely here to limit interaction to the group, and makes it possible to add additional mouse/touch processing to the group, if desired.



When the photo group is touched/clicked, a snapshot image of the group is generated, and snapshot data for each icon state (approve and reject) is stored in 2 local variables. The source object for the icons is a button located off screen, which has its textFont set to FontAwesome. Icons are assigned using the button using the numToCodepoint function since the characters we want are high level Unicode symbols in the font. And we’re generating snapshots of these elements because currently the only objects that can be rotated in LiveCode are images and graphics.




While the swipe event takes place, the behavior script applies the appropriate icon data to the overlay image, based on the direction of the swipe, and rotates both the photo group and icon snapshots. Since the icon is displayed in a separate image, it can change independently of the photo group snapshot.

Along with some basic initialization handlers, the card script has a routine that replaces the current photo data with text data of the next photo to be displayed. All 15 photos in this stack are stored as custom properties of the card. Of course, the shipping version of swypr will access real photos in friends’ Instagram feeds, but for now the photos are stored internally for demo purposes (and to wow investors).

Let’s look at the meat of the demo: the photo group’s behavior script. The behavior button sits in a small resources substack of the swypr mainstack.




The script of the button is shown below — it’s commented in the demo stack so you can see what takes place in each step of the interaction.


First we set up some variables to store various values for use in the handlers below, and establish the “swipe threshold” value: the minimum distance an image needs to be dragged to be considered a valid swipe.

local allowSwipe, cX, theSnapshot, theStatus, theLoc, theVoffset
local approveIt, rejectIt
constant theSwipeThreshold = 100


The mouseDown handler generates the snapshots that are used during while dragging: one snapshot of the photogroup, and one of the icon overlay. This script also loads the next image to be displayed into the photo group so we can see the upcoming image while the current image image is being dragged.

before mouseDown
   put mouseH() into cX
   put item 2 of loc of memouseV() into theVoffset
   lock screen
   import snapshot from me
   put long id of last img into theSnapshot
   put loc of me into theLoc
   set loc of theSnapshot to theLoc
   set resizeQuality of theSnapshot to “good”
   set colorOverlay of theSnapshot to defaultColorOverlay()
   set layerMode of theSnapshot to “dynamic”
   set label of btn “status” to numToCodepoint(61575)
   export snapshot from btn “status” to approveIt as PNG — GENERATE APPROVE OVERLAY DATA
   set label of btn “status” to numToCodepoint(61576)
   export snapshot from btn “status” to rejectIt as PNG — GENERATE REJECT OVERLAY DATA
   clone theSnapshot
   put long id of it into theStatus
   set loc of theStatus to loc of theSnapshot
   set resizeQuality of theStatus to “good”
   set text of theStatus to empty
   set ink of theStatus to “blendScreen”
   set the uCurrentState of theStatus to empty
   set layerMode of theStatus to “dynamic”
   dispatch “loadNextPhoto” to this cd
   unlock screen
   put true into allowSwipe
end mouseDown


The mouseMove portion of the script handles the all drag action: it tracks the X,Y position of the user’s mouse/touch, and positions/rotates the snapshots. It also swaps the good/bad icon snapshots based on whether the snapshot is dragged right or left, and applies the appropriate green or red color to the colorOverlay graphic effect of the photo snapshot.

before mouseMove X,Y
   if not allowSwipe then exit mouseMove
   put X,0 into p1
   put cX,0 into p2
   put getDistance(p1,p2) into theDistance
   if X > cX then multiply theDistance by -1
   if theDistance >= 0 then
      put 255,0,0 into theColor — RED
      put “unhappy” into theState
      put rejectIt into theMode
      put 0,255,0 into theColor — GREEN
      put “happy” into theState
      put approveIt into theMode
   end if
   lock screen
   rotateImage theSnapshot, theDistance
   put colorOverlay of theSnapshot into theArray
   put theColor into theArray[“color”]
   put min(180,round(abs(theDistance * 0.8))) into theArray[“opacity”]
   set colorOverlay of theSnapshot to theArray — APPLY COLOR OVERLAY TO THE SNAPSHOT
   put theLoc into theNewLoc
   subtract theDistance from item 1 of theNewLoc
   put Y + theVoffset into item 2 of theNewLoc
   set loc of theSnapshot to theNewLoc — POSITION THE SNAPSHOT
   rotateImage theStatus, theDistance
   if the uCurrentState of theStatus <> theState then
      set text of theStatus to theMode
      set the uCurrentState of theStatus to theState
   end if
   set loc of theStatus to theNewLoc — POSITION THE OVERLAY
   unlock screen
end mouseMove


The rotation function is separated out in the script so it can be easily applied to both snapshots and called wherever needed.

command rotateImage pImage, pDistance
   set angle of pImage to (pDistance/8) — ADJUST “8” TO INCREASE OR DECREASE ROTATION
end rotateImage


When the user is done swiping, the mouseUp and mouseRelease handlers stop all dragging action, clear out the temporary snapshots, and increment the photo count (after a completed swipe). It’s always good practice to employ a mouseRelease handler along with mouseUp in case the user’s mouse/touch is released outside the dragged object.

before mouseUp
end mouseUp
before mouseRelease
end mouseRelease
command clearSwipe
   put false into allowSwipe
   if not exists(theSnapshot) then exit clearSwipe
   local revertFlag
   put loc of theSnapshot into theSnapLoc
   put 0 into item 2 of theSnapLoc
   put loc of me into myLoc
   put 0 into item 2 of myLoc
   if getDistance(theSnapLoc,myLoc) <= theSwipeThreshold then
      delete theStatus
      put true into revertFlag
      dispatch “updateCountStatus” to this cd
      repeat with N = 10 to 100 step 10
         lock screen
         set blendLevel of theSnapshot to N
         set blendLevel of theStatus to N
         unlock screen
         wait 0 millisecs
      end repeat
   end if
   if revertFlag then dispatch “revertPhoto” to this cd
   delete theSnapshot
   if exists(theStatus) then delete theStatus
end clearSwipe


Remember the swipe threshold variable? The snapBack handler takes care of returning the photo snapshot to its starting point if the swipe distance doesn’t exceed the swipe threshold value set at the beginning of the script. To make life easier, the status (thumb) snapshot is deleted before sending this command, so we only need to reset the photo snapshot.

command snapBack
   put angle of theSnapshot into theAngle — USE THE ANGLE OF ROTATION AS THE NUMBER OF STEPS TO RESTORE
   put theAngle into theSteps
   put colorOverlay[“opacity”] of theSnapshot into theOpacity
   put 1 into theDifference
   if theAngle > 180 then
      put 360 – theAngle into theSteps
      put -1 into theDifference
   end if
   put max(1,theSteps) into theSteps — PREVENT DIVIDE BY ZERO ERROR
   put (item 1 of loc of theSnapshot – item 1 of loc of me) / theSteps into hStep
   put (item 2 of loc of theSnapshot – item 2 of loc of me) / theSteps into vStep
   put theOpacity / theSteps into oStep
   repeat theSteps
      put loc of theSnapshot into theLoc
      subtract hStep from item 1 of theLoc
      subtract vStep from item 2 of theLoc
      subtract theDifference from theAngle
      subtract oStep from theOpacity
      lock screen
      set loc of theSnapshot to theLoc
      set angle of theSnapshot to theAngle
      set colorOverlay[“opacity”] of theSnapshot to round(theOpacity)
      unlock screen
      wait 0 millisecs
   end repeat
   set loc of theSnapshot to loc of me
end snapBack


Remember how I said the behavior can be customized? The most obvious options to change are the green/red color overlays and the rating icons. For example, thumb images don’t go over well in certain parts of the world, so you could change the FontAwesome glyph ids to something like 61720 (happy face) and 61721 (sad face). You could also change the degree of rotation if, for example, your app ran in landscape orientation and more space was available to swipe.
Another option is to replace item 2 of theNewLoc value in the mouseMove handler with item 2 of the loc of the photo group. This change limits the movement of the snapshot to horizontal motion only, producing a slightly more formal/rigid feel that might be more suited to a product catalog.


While the interaction that swypr offers is pretty good, it could be made sexier by applying some inertia to the swipe. This would enable the snapshot to slide off the screen on its own with a bit of momentum behind it, instead of halting abruptly as soon as the swipe event ends. But the engineering team will have to pull a couple of all-nighters to finish up that feature, so we’ll save that effect for our meeting with the investors…


Now that you have the basics for building a Tinder-style rating app, what will you make? You don’t have to limit yourself to dating prospects: you could display real estate photos, text passages, song clips, or references to almost any type of media.


Sure, photos of people might be alluring, but when all is said and done, some of the sexiest things worth sharing are ideas.

(Visited 534 times, 1 visits today)