├── appExample.sketch ├── example.framer ├── .gitignore ├── app.coffee ├── app.js ├── framer │ ├── coffee-script.js │ ├── config.json │ ├── framer.generated.js │ ├── framer.init.js │ ├── framer.js │ ├── framer.js.map │ ├── framer.modules.js │ ├── images │ │ ├── background.png │ │ ├── cursor-active.png │ │ ├── cursor-active@2x.png │ │ ├── cursor.png │ │ ├── cursor@2x.png │ │ ├── icon-120.png │ │ ├── icon-152.png │ │ ├── icon-180.png │ │ ├── icon-192.png │ │ ├── icon-76.png │ │ ├── icon-arrow.png │ │ ├── icon-arrow@2x.png │ │ ├── icon-close.png │ │ ├── icon-close@2x.png │ │ ├── icon-framer.png │ │ ├── icon-framer@2x.png │ │ ├── icon-share.png │ │ └── icon-share@2x.png │ ├── mirror.css │ ├── style.css │ └── version ├── images │ └── .gitkeep ├── imported │ ├── appExample@1x │ │ ├── images │ │ │ ├── Layer-appBackground-7E9A83CC-9F0B-4103-AF8A-DBBEDD175A7D.png │ │ │ ├── Layer-bottomBar-50498FF6-8F0F-4828-AEE5-FF748BABC962.png │ │ │ ├── Layer-bottomBarIcons-05974111-0B4D-4CD5-BF32-022B1C9046F0.png │ │ │ ├── Layer-card1-606B4BD9-B851-4D85-8495-A03985A6DE1B.png │ │ │ ├── Layer-card2-EB78F369-A7E6-4257-94E2-5CA505450D2B.png │ │ │ ├── Layer-card3-EA395A59-C6B5-4BC8-9529-E4EB420333B6.png │ │ │ ├── Layer-cell1-9A96C781-9096-45E4-AED5-3AF6DFB65918.png │ │ │ ├── Layer-cell2-B5981C78-9922-4288-AA66-98A045228411.png │ │ │ ├── Layer-cell3-2DC39858-4FEF-4DD5-A885-8EA00BC3F293.png │ │ │ ├── Layer-cell4-D4D12CC6-B2EE-4D2D-BAFE-F1705BD9B178.png │ │ │ ├── Layer-cell5-F984C832-0151-46A0-AF83-BB9C88CB69CD.png │ │ │ ├── Layer-cell6-CC8F48BB-D396-43C7-B093-3D6C4A104BE6.png │ │ │ ├── Layer-checkmark-183CCE21-82ED-46D7-827E-20F0861980EC.png │ │ │ ├── Layer-checkmark-5451E179-56FC-4E09-9355-D1F2053A009B.png │ │ │ ├── Layer-checkmark-8CF143AB-7E4B-48F2-93A7-7E981208B7B3.png │ │ │ ├── Layer-complete-86934B29-0B70-4E80-9C5C-AE6597C7B2DF.png │ │ │ ├── Layer-completeTitle-D09EBACF-D357-472E-8142-C81829CB6878.png │ │ │ ├── Layer-description-3C03D8E4-3628-49BF-A773-5D626EC2E925.png │ │ │ ├── Layer-navBar-736FC417-35B4-45E0-821E-F76DF35E679D.png │ │ │ ├── Layer-openButton-8951755B-003B-43E5-AF42-0428E2198916.png │ │ │ ├── Layer-reloadButton-BF4370BD-BA36-4A28-AE27-AD9CEA1D2243.png │ │ │ ├── Layer-star1-5C3AED2C-6CA0-44A2-9F1A-6AD9254C2882.png │ │ │ ├── Layer-star2-4A4FCCB9-7828-4F18-982A-C7BF3245C855.png │ │ │ ├── Layer-star3-81268C43-C6C1-4F26-839E-6BDB9EE0E44B.png │ │ │ └── Layer-statusBar-30CB23B9-ED45-44E7-87CB-A99D2FDA6170.png │ │ ├── layers.json │ │ └── layers.json.js │ └── appExample@2x │ │ ├── images │ │ ├── Layer-Group-2B46FF1F-6D68-4C51-A881-E96221A7C6CB.png │ │ ├── Layer-appBackground-7E9A83CC-9F0B-4103-AF8A-DBBEDD175A7D.png │ │ ├── Layer-appIcon-B415F42F-0066-4325-93EB-117BB5ED26A8.png │ │ ├── Layer-bottomBar-50498FF6-8F0F-4828-AEE5-FF748BABC962.png │ │ ├── Layer-bottomBarIcons-05974111-0B4D-4CD5-BF32-022B1C9046F0.png │ │ ├── Layer-card1-606B4BD9-B851-4D85-8495-A03985A6DE1B.png │ │ ├── Layer-card2-EB78F369-A7E6-4257-94E2-5CA505450D2B.png │ │ ├── Layer-card3-EA395A59-C6B5-4BC8-9529-E4EB420333B6.png │ │ ├── Layer-cell1-2FDC1E1D-C928-40B9-A507-EE7EAF53BA58.png │ │ ├── Layer-cell10-3E52C7D6-A343-481C-B444-1CEECFF99D94.png │ │ ├── Layer-cell11-530683A3-64C7-4E34-8A5C-3707AA29D837.png │ │ ├── Layer-cell2-B5981C78-9922-4288-AA66-98A045228411.png │ │ ├── Layer-cell3-2DC39858-4FEF-4DD5-A885-8EA00BC3F293.png │ │ ├── Layer-cell4-D4D12CC6-B2EE-4D2D-BAFE-F1705BD9B178.png │ │ ├── Layer-cell5-F984C832-0151-46A0-AF83-BB9C88CB69CD.png │ │ ├── Layer-cell6-CC8F48BB-D396-43C7-B093-3D6C4A104BE6.png │ │ ├── Layer-cell7-B0ECBA2E-38AE-482E-B20D-6CB3C12526E4.png │ │ ├── Layer-cell8-AC8C9129-710B-40A4-B806-17B3EAAB4220.png │ │ ├── Layer-cell9-BAE38E80-64EB-4EE1-81AD-D6B2AA28579B.png │ │ ├── Layer-cellContainer-6BE570AE-704D-4907-AD6A-4676988EBE6A.png │ │ ├── Layer-cells-2FB0FDD4-50C1-4C1B-A397-745156EFC8A5.png │ │ ├── Layer-checkmark-183CCE21-82ED-46D7-827E-20F0861980EC.png │ │ ├── Layer-checkmark-5451E179-56FC-4E09-9355-D1F2053A009B.png │ │ ├── Layer-checkmark-8CF143AB-7E4B-48F2-93A7-7E981208B7B3.png │ │ ├── Layer-closeButton-3708217B-86E3-48AB-93E2-FEBDA9B2A3EB.png │ │ ├── Layer-complete-86934B29-0B70-4E80-9C5C-AE6597C7B2DF.png │ │ ├── Layer-completeTitle-D09EBACF-D357-472E-8142-C81829CB6878.png │ │ ├── Layer-navBar-736FC417-35B4-45E0-821E-F76DF35E679D.png │ │ ├── Layer-openButton-211EB8A9-DB08-42DC-BF24-CF138AB17968.png │ │ ├── Layer-reloadButton-5CE709CE-B25B-4AB9-A811-80410F360B8E.png │ │ ├── Layer-springboardBackground-90BE8360-0D4B-428B-A2C7-9EBED4380E7E.png │ │ ├── Layer-springboardIcons-6A002618-48F3-4DF5-8839-86822E3ABDE6.png │ │ ├── Layer-star1-5C3AED2C-6CA0-44A2-9F1A-6AD9254C2882.png │ │ ├── Layer-star2-4A4FCCB9-7828-4F18-982A-C7BF3245C855.png │ │ ├── Layer-star3-81268C43-C6C1-4F26-839E-6BDB9EE0E44B.png │ │ └── Layer-statusBar-30CB23B9-ED45-44E7-87CB-A99D2FDA6170.png │ │ ├── layers.json │ │ └── layers.json.js ├── index.html └── modules │ └── myModule.coffee └── example.sketch /appExample.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotdestroy/framerExample/1656fa9a3616377575d9b77d87fd185e236c4227/appExample.sketch -------------------------------------------------------------------------------- /example.framer/.gitignore: -------------------------------------------------------------------------------- 1 | # Framer Git Ignore 2 | 3 | # General OSX 4 | 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | # Thumbnails 13 | ._* 14 | 15 | # Files that might appear in the root of a volume 16 | .DocumentRevisions-V100 17 | .fseventsd 18 | .Spotlight-V100 19 | .TemporaryItems 20 | .Trashes 21 | .VolumeIcon.icns 22 | 23 | # Directories potentially created on remote AFP share 24 | .AppleDB 25 | .AppleDesktop 26 | Network Trash Folder 27 | Temporary Items 28 | .apdisk 29 | 30 | 31 | # Framer Specific 32 | .temp.html 33 | framer/*.old.* 34 | framer/backup.coffee 35 | framer/backups/* 36 | framer/.*.hash 37 | -------------------------------------------------------------------------------- /example.framer/app.coffee: -------------------------------------------------------------------------------- 1 | app = Framer.Importer.load("imported/appExample@2x") 2 | 3 | # define initial positions 4 | app.appView.scale = 0 5 | app.appView.originX = 0.361 6 | app.appView.originY = 0.17 7 | app.springboard.originX = 0.365 8 | app.springboard.originY = 0.2 9 | 10 | app.star1.scale = 0 11 | app.star2.scale = 0 12 | app.star3.scale = 0 13 | 14 | app.star1.opacity = 0 15 | app.star2.opacity = 0 16 | app.star3.opacity = 0 17 | 18 | app.check1.scale = 0 19 | app.check2.scale = 0 20 | app.check3.scale = 0 21 | 22 | app.check1.opacity = 0 23 | app.check2.opacity = 0 24 | app.check3.opacity = 0 25 | 26 | app.cell1.scale = 0 27 | app.cell2.scale = 0 28 | app.cell3.scale = 0 29 | app.cell4.scale = 0 30 | app.cell5.scale = 0 31 | app.cell6.scale = 0 32 | app.cell7.scale = 0 33 | app.cell8.scale = 0 34 | app.cell9.scale = 0 35 | app.cell10.scale = 0 36 | app.cell11.scale = 0 37 | 38 | app.cell1.opacity = 0 39 | app.cell2.opacity = 0 40 | app.cell3.opacity = 0 41 | app.cell4.opacity = 0 42 | app.cell5.opacity = 0 43 | app.cell6.opacity = 0 44 | app.cell7.opacity = 0 45 | app.cell8.opacity = 0 46 | app.cell9.opacity = 0 47 | app.cell10.opacity = 0 48 | app.cell11.opacity = 0 49 | 50 | app.completeTitle.opacity = 0 51 | app.complete.scale = 0 52 | app.complete.opacity = 0 53 | 54 | app.closeButton.scale = 0 55 | 56 | # define draggables and scrollable 57 | app.card1.draggable = true 58 | app.card2.draggable = false 59 | app.card3.draggable = false 60 | 61 | scroll = ScrollComponent.wrap(app.cells) 62 | scroll.scrollHorizontal = false 63 | scroll.contentInset = 64 | bottom: 40 65 | app.cells.scale = 0 66 | 67 | # define springs 68 | cardLift = "spring(160,40,10)" 69 | cardPull = "spring(200,26,10)" 70 | cardSpring = "spring(400,22,20)" 71 | cardFill = "spring(400,22,30)" 72 | cardReturn = "spring(160,30,10)" 73 | cellSpring = "spring(320,30,0)" 74 | 75 | # define animations 76 | cardExitLeft = (layer) -> 77 | layer.animate 78 | properties: 79 | x: -750 80 | curve: cardPull 81 | 82 | cardExitRight = (layer) -> 83 | layer.animate 84 | properties: 85 | x: 750 86 | curve: cardPull 87 | 88 | completeCards = (onoff, delay) -> 89 | app.complete.animate 90 | properties: 91 | scale: onoff 92 | opacity: onoff 93 | curve: cardSpring 94 | delay: delay 95 | app.completeTitle.animate 96 | properties: 97 | opacity: onoff 98 | time: 0.3 99 | delay: 2 * delay 100 | 101 | cellScale = (layer, scaleValue, opacityValue, delayValue) -> 102 | layer.animate 103 | properties: 104 | scale: scaleValue 105 | opacity: opacityValue 106 | curve: cellSpring 107 | delay: delayValue 108 | 109 | # define conditionals 110 | currentCard = 1 111 | 112 | # open app 113 | app.appIcon.on Events.Click, -> 114 | app.appView.animate 115 | properties: 116 | scale: 1 117 | time: 0.55 118 | app.springboard.animate 119 | properties: 120 | scale: 8.4 121 | time: 0.55 122 | app.appIcon.animate 123 | properties: 124 | opacity: 0 125 | time: 0.05 126 | app.springboardIcons.animate 127 | properties: 128 | opacity: 0 129 | time: 0.55 130 | 131 | # create array for cards in Sketch file 132 | cardsArray = [app.card1, app.card2, app.card3] 133 | 134 | # apply actions and style to cards in a loop 135 | for card in cardsArray 136 | # card shadow style 137 | card.shadowY = 4 138 | card.shadowBlur = 12 139 | card.shadowColor = "rgba(0,0,0,0.16)" 140 | card.borderRadius = 12 141 | 142 | # card position states 143 | card.states.add 144 | card1: 145 | scale: 1 146 | midY: card.midY 147 | midX: card.midX 148 | card2: 149 | scale: 0.9 150 | midY: card.midY - 60 151 | midX: card.midX 152 | card3: 153 | scale: 0.8 154 | midY: card.midY - 120 155 | midX: card.midX 156 | card.states.animationOptions = 157 | curve: cardPull 158 | 159 | # cards set to initial position 160 | card.states.switchInstant(card.name) 161 | 162 | # on drag scale card 163 | card.on Events.DragStart, -> 164 | this.animate 165 | properties: 166 | scale: 1.1 167 | curve: cardLift 168 | 169 | # while dragging show overlay 170 | card.on Events.Drag, -> 171 | if this.name == "card1" 172 | if app.card1.x > 75 173 | app.star1.scale = (app.card1.x-50)/400 174 | app.star1.opacity = (app.card1.x-50)/400 175 | currentCard = 2 176 | else if app.card1.x < -75 177 | app.check1.scale = -(app.card1.x+50)/400 178 | app.check1.opacity = -(app.card1.x-50)/400 179 | currentCard = 2 180 | else 181 | app.star1.scale = 0 182 | app.check1.scale = 0 183 | if this.name == "card2" 184 | if app.card2.x > 75 185 | app.star2.scale = (app.card2.x-50)/400 186 | app.star2.opacity = (app.card2.x-50)/400 187 | currentCard = 3 188 | else if app.card2.x < -75 189 | app.check2.scale = -(app.card2.x+50)/400 190 | app.check2.opacity = -(app.card2.x-50)/400 191 | currentCard = 3 192 | else 193 | app.star2.scale = 0 194 | app.check2.scale = 0 195 | if this.name == "card3" 196 | if app.card3.x > 75 197 | app.star3.scale = (app.card3.x-50)/400 198 | app.star3.opacity = (app.card3.x-50)/400 199 | currentCard = 0 200 | else if app.card3.x < -75 201 | app.check3.scale = -(app.card3.x+50)/400 202 | app.check3.opacity = -(app.card3.x-50)/400 203 | currentCard = 0 204 | else 205 | app.star3.scale = 0 206 | app.check3.scale = 0 207 | 208 | # on drag end decide where card should go 209 | card.on Events.DragEnd, -> 210 | if this.name == "card1" 211 | if this.x > 150 212 | cardExitRight(this) 213 | app.card2.states.switch("card1") 214 | app.card3.states.switch("card2") 215 | app.card1.draggable = false 216 | app.card2.draggable = true 217 | else if this.x < -150 218 | cardExitLeft(this) 219 | app.card2.states.switch("card1") 220 | app.card3.states.switch("card2") 221 | app.card1.draggable = false 222 | app.card2.draggable = true 223 | else 224 | this.states.switch("card1") 225 | app.star1.scale = 0 226 | app.check1.scale = 0 227 | else if this.name == "card2" 228 | if this.x > 150 229 | cardExitRight(this) 230 | app.card3.states.switch("card1") 231 | app.card2.draggable = false 232 | app.card3.draggable = true 233 | else if this.x < -150 234 | cardExitLeft(this) 235 | app.card3.states.switch("card1") 236 | app.card2.draggable = false 237 | app.card3.draggable = true 238 | else 239 | this.states.switch("card1") 240 | app.star2.scale = 0 241 | app.check2.scale = 0 242 | else if this.name == "card3" 243 | if this.x > 150 244 | cardExitRight(this) 245 | completeCards(1, 0.2) 246 | app.card1.draggable = true 247 | app.card3.draggable = false 248 | else if this.x < -150 249 | cardExitLeft(this) 250 | completeCards(1, 0.2) 251 | app.card1.draggable = true 252 | app.card3.draggable = false 253 | else 254 | this.states.switch("card1") 255 | app.star3.scale = 0 256 | app.check3.scale = 0 257 | 258 | # reload cards 259 | app.reloadButton.on Events.Click, -> 260 | app.card1.draggable = true 261 | app.card2.draggable = false 262 | app.card3.draggable = false 263 | app.card1.animateStop() 264 | app.card2.animateStop() 265 | app.card3.animateStop() 266 | app.card1.x = 0 267 | app.card2.x = 0 268 | app.card3.x = 0 269 | app.card1.y = -780 270 | app.card2.y = -780 271 | app.card3.y = -780 272 | app.card1.scale = 1 273 | app.card2.scale = 1 274 | app.card3.scale = 1 275 | app.star1.scale = 0 276 | app.star2.scale = 0 277 | app.star3.scale = 0 278 | app.check1.scale = 0 279 | app.check2.scale = 0 280 | app.check3.scale = 0 281 | completeCards(0, 0) 282 | currentCard = 1 283 | Utils.delay 0.05, -> 284 | app.card1.states.switch("card1") 285 | Utils.delay 0.1, -> 286 | app.card2.states.switch("card2") 287 | Utils.delay 0.15, -> 288 | app.card3.states.switch("card3") 289 | 290 | # open current card 291 | app.openButton.on Events.Click, -> 292 | app.cells.scale = 1 293 | if currentCard != 0 294 | if currentCard == 1 295 | app.card1.animate 296 | properties: 297 | scale: 3 298 | time: 0.4 299 | if currentCard == 2 300 | app.card2.animate 301 | properties: 302 | scale: 3 303 | time: 0.4 304 | if currentCard == 3 305 | app.card3.animate 306 | properties: 307 | scale: 3 308 | time: 0.4 309 | app.navBar.animate 310 | properties: 311 | y: -128 312 | curve: cardSpring 313 | app.bottomBar.animate 314 | properties: 315 | y: 1334 316 | curve: cardSpring 317 | cellScale(app.cell1, 1, 1, 0.2) 318 | cellScale(app.cell2, 1, 1, 0.3) 319 | cellScale(app.cell3, 1, 1, 0.4) 320 | cellScale(app.cell4, 1, 1, 0.5) 321 | cellScale(app.cell5, 1, 1, 0.6) 322 | cellScale(app.cell6, 1, 1, 0.7) 323 | cellScale(app.cell7, 1, 1, 0.8) 324 | cellScale(app.cell8, 1, 1, 0.9) 325 | cellScale(app.cell9, 1, 1, 1) 326 | cellScale(app.cell10, 1, 1, 1.1) 327 | cellScale(app.cell11, 1, 1, 1.2) 328 | cellScale(app.closeButton, 1, 1, 1.1) 329 | 330 | # close open card 331 | app.closeButton.on Events.Click, -> 332 | scroll.animate 333 | properties: 334 | scrollY: 0 335 | time: 0.5 336 | cellScale(app.closeButton, 0, 0, 0) 337 | cellScale(app.cell11, 0, 0, 0) 338 | cellScale(app.cell10, 0, 0, 0) 339 | cellScale(app.cell9, 0, 0, 0) 340 | cellScale(app.cell8, 0, 0, 0) 341 | cellScale(app.cell7, 0, 0, 0) 342 | cellScale(app.cell6, 0, 0, 0) 343 | cellScale(app.cell5, 0, 0, 0.05) 344 | cellScale(app.cell4, 0, 0, 0.1) 345 | cellScale(app.cell3, 0, 0, 0.15) 346 | cellScale(app.cell2, 0, 0, 0.2) 347 | cellScale(app.cell1, 0, 0, 0.25) 348 | if currentCard == 1 349 | app.card1.animate 350 | properties: 351 | scale: 1 352 | curve: cardReturn 353 | delay: 0.3 354 | if currentCard == 2 355 | app.card2.animate 356 | properties: 357 | scale: 1 358 | curve: cardReturn 359 | delay: 0.3 360 | if currentCard == 3 361 | app.card3.animate 362 | properties: 363 | scale: 1 364 | curve: cardReturn 365 | delay: 0.3 366 | app.navBar.animate 367 | properties: 368 | y: 0 369 | curve: cardLift 370 | delay: 0.3 371 | app.bottomBar.animate 372 | properties: 373 | y: 1236 374 | curve: cardLift 375 | delay: 0.3 376 | app.cells.animate 377 | properties: 378 | scale: 0 379 | time: 0 380 | delay: 0.8 -------------------------------------------------------------------------------- /example.framer/app.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.9.3 2 | 3 | -------------------------------------------------------------------------------- /example.framer/framer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "deviceOrientation" : 0, 3 | "sharedPrototype" : 1, 4 | "contentScale" : 1, 5 | "deviceType" : "apple-iphone-6s-silver", 6 | "selectedHand" : "", 7 | "updateDelay" : 0.3, 8 | "deviceScale" : "fit", 9 | "orientation" : 0, 10 | "fullScreen" : false 11 | } -------------------------------------------------------------------------------- /example.framer/framer/framer.init.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function isFileLoadingAllowed() { 4 | return (window.location.protocol.indexOf("file") == -1) 5 | } 6 | 7 | function isHomeScreened() { 8 | return ("standalone" in window.navigator) && window.navigator.standalone == true 9 | } 10 | 11 | function isCompatibleBrowser() { 12 | return Utils.isWebKit() 13 | } 14 | 15 | var alertNode; 16 | 17 | function dismissAlert() { 18 | alertNode.parentElement.removeChild(alertNode) 19 | loadProject() 20 | } 21 | 22 | function showAlert(html) { 23 | 24 | alertNode = document.createElement("div") 25 | 26 | alertNode.classList.add("framerAlertBackground") 27 | alertNode.innerHTML = html 28 | 29 | document.addEventListener("DOMContentLoaded", function(event) { 30 | document.body.appendChild(alertNode) 31 | }) 32 | 33 | window.dismissAlert = dismissAlert; 34 | } 35 | 36 | function showBrowserAlert() { 37 | var html = "" 38 | html += "
Tap
, then choose 'Add to Home Screen' " 76 | html += "