├── .DS_Store
├── Examples
├── .DS_Store
├── AppleWatchActivities.framer
│ ├── .gitignore
│ ├── app.coffee
│ ├── framer
│ │ ├── .bookmark
│ │ ├── coffee-script.js
│ │ ├── config.json
│ │ ├── design.vekter
│ │ ├── framer.generated.js
│ │ ├── framer.init.js
│ │ ├── framer.js
│ │ ├── framer.js.map
│ │ ├── framer.modules.js
│ │ ├── framer.vekter.js
│ │ ├── images
│ │ │ ├── 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
│ │ ├── style.css
│ │ └── version
│ ├── images
│ │ └── .gitkeep
│ ├── index.html
│ └── modules
│ │ └── circleModule.coffee
└── Countdown.framer
│ ├── .gitignore
│ ├── app.coffee
│ ├── framer
│ ├── .bookmark
│ ├── coffee-script.js
│ ├── config.json
│ ├── design.vekter
│ ├── framer.generated.js
│ ├── framer.init.js
│ ├── framer.js
│ ├── framer.js.map
│ ├── framer.modules.js
│ ├── framer.vekter.js
│ ├── images
│ │ ├── 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
│ ├── style.css
│ └── version
│ ├── images
│ └── .gitkeep
│ ├── index.html
│ └── modules
│ └── circleModule.coffee
├── README.md
├── applewatchactivities.gif
├── circleModule.coffee
└── countdown.gif
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/.DS_Store
--------------------------------------------------------------------------------
/Examples/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/.DS_Store
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.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 | # Framer Specific
31 | .*.html
32 | framer/*.old*
33 | framer/.*.hash
34 | framer/backup.coffee
35 | framer/backups/*
36 | framer/manifest.txt
37 | framer/metadata.json
38 | framer/preview.png
39 | framer/social-880x460.png
40 | framer/social-1200x630.png
41 |
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/app.coffee:
--------------------------------------------------------------------------------
1 | # Project Info
2 | # This info is presented in a widget when you share.
3 | # http://framerjs.com/docs/#info.info
4 |
5 | Framer.Info =
6 | title: "Apple Watch Activities"
7 | author: "Jonathan Arnold"
8 | twitter: "@servusjon"
9 | description: "Build with SVGCircle Module. Learn more: https://github.com/ServusJon/SVGCircle-Module-for-FramerJS"
10 |
11 | {Circle} = require "circleModule"
12 |
13 | padding = 20
14 |
15 | loadingCircle = new Circle
16 | circleSize: 300
17 | topColor: "#ff150f"
18 | bottomColor: "#ff23bd"
19 | strokeWidth: 40
20 | # hasLinearEasing: true
21 | loadingCircle.center()
22 |
23 | loadingCircle2 = new Circle
24 | circleSize: 220 - padding
25 | strokeWidth: 40
26 | topColor: "#7cc201"
27 | bottomColor: "#a3fe00"
28 | loadingCircle2.center()
29 |
30 | loadingCircle3 = new Circle
31 | circleSize: 140 - padding * 2
32 | strokeWidth: 40
33 | topColor: "#1baca6"
34 | bottomColor: "#18e1e9"
35 | loadingCircle3.center()
36 |
37 | loadingCircle.changeTo(80, 2)
38 | loadingCircle2.changeTo(60, 2)
39 | loadingCircle3.changeTo(30, 2)
40 |
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/.bookmark:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/.bookmark
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "orientation" : 0,
3 | "updateDelay" : 0.3,
4 | "designModeSelected" : 0,
5 | "cachedDeviceHeight" : 0,
6 | "contentScale" : 1,
7 | "cachedDeviceWidth" : 0,
8 | "deviceType" : "fullscreen",
9 | "sharedPrototype" : 0,
10 | "propertyPanelToggleStates" : {
11 |
12 | },
13 | "projectId" : "5916C71F-6B6D-4A4A-8AA2-A984D21C7925",
14 | "deviceOrientation" : 0,
15 | "selectedHand" : "",
16 | "showBezel" : 0,
17 | "foldedCodeRanges" : [
18 | "{107, 213}"
19 | ],
20 | "deviceScale" : 1
21 | }
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/design.vekter:
--------------------------------------------------------------------------------
1 | {
2 | "version" : 20,
3 | "root" : {
4 | "id" : "tB0fhMSIV",
5 | "__class" : "CanvasNode",
6 | "parentid" : null,
7 | "children" : [
8 |
9 | ]
10 | }
11 | }
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/framer.generated.js:
--------------------------------------------------------------------------------
1 | // This is autogenerated by Framer
2 |
3 |
4 | if (!window.Framer && window._bridge) {window._bridge('runtime.error', {message:'[framer.js] Framer library missing or corrupt. Select File → Update Framer Library.'})}
5 | if (DeviceComponent) {DeviceComponent.Devices["iphone-6-silver"].deviceImageJP2 = false};
6 | if (window.Framer) {window.Framer.Defaults.DeviceView = {"deviceScale":1,"selectedHand":"","deviceType":"fullscreen","contentScale":1,"hideBezel":true,"orientation":0};
7 | }
8 | if (window.Framer) {window.Framer.Defaults.DeviceComponent = {"deviceScale":1,"selectedHand":"","deviceType":"fullscreen","contentScale":1,"hideBezel":true,"orientation":0};
9 | }
10 | window.FramerStudioInfo = {"deviceImagesUrl":"\/_server\/resources\/DeviceImages","documentTitle":"AppleWatchActivities.framer"};
11 |
12 | Framer.Device = new Framer.DeviceView();
13 | Framer.Device.setupContext();
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.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 += "
"
39 | html += "
Error: Not A WebKit Browser "
40 | html += "Your browser is not supported.
Please use Safari or Chrome.
"
41 | html += "
Try anyway "
42 | html += "
"
43 |
44 | showAlert(html)
45 | }
46 |
47 | function showFileLoadingAlert() {
48 | var html = ""
49 | html += ""
50 | html += "
Error: Local File Restrictions "
51 | html += "Preview this prototype with Framer Mirror or learn more about "
52 | html += "
file restrictions .
"
53 | html += "
Try anyway "
54 | html += "
"
55 |
56 | showAlert(html)
57 | }
58 |
59 | function loadProject(callback) {
60 | CoffeeScript.load("app.coffee", callback)
61 | }
62 |
63 | function setDefaultPageTitle() {
64 | // If no title was set we set it to the project folder name so
65 | // you get a nice name on iOS if you bookmark to desktop.
66 | document.addEventListener("DOMContentLoaded", function() {
67 | if (document.title == "") {
68 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) {
69 | document.title = window.FramerStudioInfo.documentTitle
70 | } else {
71 | document.title = window.location.pathname.replace(/\//g, "")
72 | }
73 | }
74 | })
75 | }
76 |
77 | function init() {
78 |
79 | if (Utils.isFramerStudio()) {
80 | return
81 | }
82 |
83 | setDefaultPageTitle()
84 |
85 | if (!isCompatibleBrowser()) {
86 | return showBrowserAlert()
87 | }
88 |
89 | if (!isFileLoadingAllowed()) {
90 | return showFileLoadingAlert()
91 | }
92 |
93 | loadProject(function(){
94 | // CoffeeScript: Framer?.CurrentContext?.emit?("loaded:project")
95 | var context;
96 | if (typeof Framer !== "undefined" && Framer !== null) {
97 | if ((context = Framer.CurrentContext) != null) {
98 | if (typeof context.emit === "function") {
99 | context.emit("loaded:project");
100 | }
101 | }
102 | }
103 | })
104 | }
105 |
106 | init()
107 |
108 | })()
109 |
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/framer.modules.js:
--------------------------------------------------------------------------------
1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n \n \n \n \n \n \n \n";
80 | self = this;
81 | Utils.domComplete(function() {
82 | return self.path = document.querySelector("#" + self.circleID);
83 | });
84 | this.proxy = new Layer({
85 | opacity: 0,
86 | name: "circuleModuleProxy"
87 | });
88 | this.proxy.sendToBack();
89 | this.proxy.on(Events.AnimationEnd, function(animation, layer) {
90 | return self.onFinished();
91 | });
92 | this.proxy.on('change:x', function() {
93 | var offset;
94 | offset = Utils.modulate(this.x, [0, 500], [self.pathLength, 0]);
95 | self.path.setAttribute('stroke-dashoffset', offset);
96 | if (self.options.hasCounter !== null) {
97 | numberNow = Utils.round(self.proxy.x / 5);
98 | return counter.html = numberNow;
99 | }
100 | });
101 | Utils.domComplete(function() {
102 | return self.proxy.x = 0.1;
103 | });
104 | }
105 |
106 | Circle.prototype.changeTo = function(value, time) {
107 | var customCurve;
108 | if (time === void 0) {
109 | time = 2;
110 | }
111 | if (this.options.hasLinearEasing === true) {
112 | customCurve = "linear";
113 | } else {
114 | customCurve = "ease-in-out";
115 | }
116 | this.proxy.animate({
117 | properties: {
118 | x: 500 * (value / 100)
119 | },
120 | time: time,
121 | curve: customCurve
122 | });
123 | return this.currentValue = value;
124 | };
125 |
126 | Circle.prototype.startAt = function(value) {
127 | this.proxy.animate({
128 | properties: {
129 | x: 500 * (value / 100)
130 | },
131 | time: 0.001
132 | });
133 | return this.currentValue = value;
134 | };
135 |
136 | Circle.prototype.hide = function() {
137 | return this.opacity = 0;
138 | };
139 |
140 | Circle.prototype.show = function() {
141 | return this.opacity = 1;
142 | };
143 |
144 | Circle.prototype.onFinished = function() {};
145 |
146 | return Circle;
147 |
148 | })(Layer);
149 |
150 |
151 | },{}]},{},[])
152 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhbWVyLm1vZHVsZXMuanMiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL1VzZXJzL0pvbmF0aGFuLkFybm9sZC9EZXNrdG9wL2dpdGh1Yi9TVkdDaXJjbGUtTW9kdWxlLWZvci1GcmFtZXJKUy9FeGFtcGxlcy9BcHBsZVdhdGNoQWN0aXZpdGllcy5mcmFtZXIvbW9kdWxlcy9jaXJjbGVNb2R1bGUuY29mZmVlIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJjbGFzcyBleHBvcnRzLkNpcmNsZSBleHRlbmRzIExheWVyXG5cdGN1cnJlbnRWYWx1ZTogbnVsbFxuXG5cdGNvbnN0cnVjdG9yOiAoQG9wdGlvbnM9e30pIC0+XG5cblx0XHRAb3B0aW9ucy5jaXJjbGVTaXplID89IDMwMFxuXHRcdEBvcHRpb25zLnN0cm9rZVdpZHRoID89IDI0XG5cdFx0QG9wdGlvbnMubGluZWNhcCA/PSBcInJvdW5kXCJcblxuXHRcdEBvcHRpb25zLnN0cm9rZUNvbG9yID89IFwiI2ZjMjQ1Y1wiXG5cdFx0QG9wdGlvbnMudG9wQ29sb3IgPz0gbnVsbFxuXHRcdEBvcHRpb25zLmJvdHRvbUNvbG9yID89IG51bGxcblxuXHRcdEBvcHRpb25zLmhhc0NvdW50ZXIgPz0gbnVsbFxuXHRcdEBvcHRpb25zLmNvdW50ZXJDb2xvciA/PSBcIiNmZmZcIlxuXHRcdEBvcHRpb25zLmNvdW50ZXJGb250U2l6ZSA/PSA2MFxuXHRcdEBvcHRpb25zLmhhc0xpbmVhckVhc2luZyA/PSBmYWxzZVxuXG5cdFx0QG9wdGlvbnMudmFsdWUgPSAyXG5cblx0XHRAb3B0aW9ucy52aWV3Qm94ID0gKEBvcHRpb25zLmNpcmNsZVNpemUpICsgQG9wdGlvbnMuc3Ryb2tlV2lkdGhcblxuXHRcdHN1cGVyIEBvcHRpb25zXG5cblx0XHRALmJhY2tncm91bmRDb2xvciA9IFwiXCJcblx0XHRALmhlaWdodCA9IEBvcHRpb25zLnZpZXdCb3hcblx0XHRALndpZHRoID0gQG9wdGlvbnMudmlld0JveFxuXHRcdEAucm90YXRpb24gPSAtOTBcblxuXG5cdFx0QC5wYXRoTGVuZ3RoID0gTWF0aC5QSSAqIEBvcHRpb25zLmNpcmNsZVNpemVcblxuXHRcdEAuY2lyY2xlSUQgPSBcImNpcmNsZVwiICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpKjEwMDApXG5cdFx0QC5ncmFkaWVudElEID0gXCJjaXJjbGVcIiArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSoxMDAwKVxuXG5cdFx0IyBQdXQgdGhpcyBpbnNpZGUgbGluZWFyZ3JhZGllbnRcblx0XHQjIGdyYWRpZW50VW5pdHM9XCJ1c2VyU3BhY2VPblVzZVwiXG5cdFx0IyAgICB4MT1cIjAlXCIgeTE9XCIwJVwiIHgyPVwiNTAlXCIgeTI9XCIwJVwiIGdyYWRpZW50VHJhbnNmb3JtPVwicm90YXRlKDEyMClcIlxuXG5cblx0XHRpZiBAb3B0aW9ucy5oYXNDb3VudGVyIGlzbnQgbnVsbFxuXHRcdFx0Y291bnRlciA9IG5ldyBMYXllclxuXHRcdFx0XHRwYXJlbnQ6IEBcblx0XHRcdFx0aHRtbDogXCJcIlxuXHRcdFx0XHR3aWR0aDogQC53aWR0aFxuXHRcdFx0XHRoZWlnaHQ6IEAuaGVpZ2h0XG5cdFx0XHRcdGJhY2tncm91bmRDb2xvcjogXCJcIlxuXHRcdFx0XHRyb3RhdGlvbjogOTBcblx0XHRcdFx0Y29sb3I6IEBvcHRpb25zLmNvdW50ZXJDb2xvclxuXG5cdFx0XHRzdHlsZSA9IHtcblx0XHRcdFx0dGV4dEFsaWduOiBcImNlbnRlclwiXG5cdFx0XHRcdGZvbnRTaXplOiBcIiN7QG9wdGlvbnMuY291bnRlckZvbnRTaXplfXB4XCJcblx0XHRcdFx0bGluZUhlaWdodDogXCIje0AuaGVpZ2h0fXB4XCJcblx0XHRcdFx0Zm9udFdlaWdodDogXCI2MDBcIlxuXHRcdFx0XHRmb250RmFtaWx5OiBcIi1hcHBsZS1zeXN0ZW0sIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWZcIlxuXHRcdFx0XHRib3hTaXppbmc6IFwiYm9yZGVyLWJveFwiXG5cdFx0XHRcdGhlaWdodDogQC5oZWlnaHRcblx0XHRcdH1cblxuXHRcdFx0Y291bnRlci5zdHlsZSA9IHN0eWxlXG5cblx0XHRcdG51bWJlclN0YXJ0ID0gMFxuXHRcdFx0bnVtYmVyRW5kID0gMTAwXG5cdFx0XHRudW1iZXJEdXJhdGlvbiA9IDJcblxuXHRcdFx0bnVtYmVyTm93ID0gbnVtYmVyU3RhcnRcblx0XHRcdG51bWJlckludGVydmFsID0gbnVtYmVyRW5kIC0gbnVtYmVyU3RhcnRcblxuXG5cdFx0QC5odG1sID0gXCJcIlwiXG5cdFx0XHQ8c3ZnIHZpZXdCb3g9Jy0je0BvcHRpb25zLnN0cm9rZVdpZHRoLzJ9IC0je0BvcHRpb25zLnN0cm9rZVdpZHRoLzJ9ICN7QG9wdGlvbnMudmlld0JveH0gI3tAb3B0aW9ucy52aWV3Qm94fScgPlxuXHRcdFx0XHQ8ZGVmcz5cblx0XHRcdFx0ICAgIDxsaW5lYXJHcmFkaWVudCBpZD0nI3tAZ3JhZGllbnRJRH0nID5cblx0XHRcdFx0ICAgICAgICA8c3RvcCBvZmZzZXQ9XCIwJVwiIHN0b3AtY29sb3I9JyN7aWYgQG9wdGlvbnMudG9wQ29sb3IgaXNudCBudWxsIHRoZW4gQG9wdGlvbnMuYm90dG9tQ29sb3IgZWxzZSBAb3B0aW9ucy5zdHJva2VDb2xvcn0nLz5cblx0XHRcdFx0ICAgICAgICA8c3RvcCBvZmZzZXQ9XCIxMDAlXCIgc3RvcC1jb2xvcj0nI3tpZiBAb3B0aW9ucy50b3BDb2xvciBpc250IG51bGwgdGhlbiBAb3B0aW9ucy50b3BDb2xvciBlbHNlIEBvcHRpb25zLnN0cm9rZUNvbG9yfScgc3RvcC1vcGFjaXR5PVwiMVwiIC8+XG5cdFx0XHRcdCAgICA8L2xpbmVhckdyYWRpZW50PlxuXHRcdFx0XHQ8L2RlZnM+XG5cdFx0XHRcdDxjaXJjbGUgaWQ9JyN7QGNpcmNsZUlEfSdcblx0XHRcdFx0XHRcdGZpbGw9J25vbmUnXG5cdFx0XHRcdFx0XHRzdHJva2UtbGluZWNhcD0nI3tAb3B0aW9ucy5saW5lY2FwfSdcblx0XHRcdFx0XHRcdHN0cm9rZS13aWR0aCAgICAgID0gJyN7QG9wdGlvbnMuc3Ryb2tlV2lkdGh9J1xuXHRcdFx0XHRcdFx0c3Ryb2tlLWRhc2hhcnJheSAgPSAnI3tALnBhdGhMZW5ndGh9J1xuXHRcdFx0XHRcdFx0c3Ryb2tlLWRhc2hvZmZzZXQgPSAnMCdcblx0XHRcdFx0XHRcdHN0cm9rZT1cInVybCgjI3tAZ3JhZGllbnRJRH0pXCJcblx0XHRcdFx0XHRcdHN0cm9rZS13aWR0aD1cIjEwXCJcblx0XHRcdFx0XHRcdGN4ID0gJyN7QG9wdGlvbnMuY2lyY2xlU2l6ZS8yfSdcblx0XHRcdFx0XHRcdGN5ID0gJyN7QG9wdGlvbnMuY2lyY2xlU2l6ZS8yfSdcblx0XHRcdFx0XHRcdHIgID0gJyN7QG9wdGlvbnMuY2lyY2xlU2l6ZS8yfSc+XG5cdFx0XHQ8L3N2Zz5cIlwiXCJcblxuXHRcdHNlbGYgPSBAXG5cdFx0VXRpbHMuZG9tQ29tcGxldGUgLT5cblx0XHRcdHNlbGYucGF0aCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjI3tzZWxmLmNpcmNsZUlEfVwiKVxuXG5cdFx0QHByb3h5ID0gbmV3IExheWVyXG5cdFx0XHRvcGFjaXR5OiAwXG5cdFx0XHRuYW1lOiBcImNpcmN1bGVNb2R1bGVQcm94eVwiXG5cdFx0XHRcblx0XHRAcHJveHkuc2VuZFRvQmFjaygpXG5cblx0XHRAcHJveHkub24gRXZlbnRzLkFuaW1hdGlvbkVuZCwgKGFuaW1hdGlvbiwgbGF5ZXIpIC0+XG5cdFx0XHRzZWxmLm9uRmluaXNoZWQoKVxuXG5cdFx0QHByb3h5Lm9uICdjaGFuZ2U6eCcsIC0+XG5cblx0XHRcdG9mZnNldCA9IFV0aWxzLm1vZHVsYXRlKEAueCwgWzAsIDUwMF0sIFtzZWxmLnBhdGhMZW5ndGgsIDBdKVxuXG5cdFx0XHRzZWxmLnBhdGguc2V0QXR0cmlidXRlICdzdHJva2UtZGFzaG9mZnNldCcsIG9mZnNldFxuXG5cdFx0XHRpZiBzZWxmLm9wdGlvbnMuaGFzQ291bnRlciBpc250IG51bGxcblx0XHRcdFx0bnVtYmVyTm93ID0gVXRpbHMucm91bmQoc2VsZi5wcm94eS54IC8gNSlcblx0XHRcdFx0Y291bnRlci5odG1sID0gbnVtYmVyTm93XG5cblx0XHRVdGlscy5kb21Db21wbGV0ZSAtPlxuXHRcdFx0c2VsZi5wcm94eS54ID0gMC4xXG5cblx0Y2hhbmdlVG86ICh2YWx1ZSwgdGltZSkgLT5cblx0XHRpZiB0aW1lIGlzIHVuZGVmaW5lZFxuXHRcdFx0dGltZSA9IDJcblxuXHRcdGlmIEBvcHRpb25zLmhhc0xpbmVhckVhc2luZyBpcyB0cnVlXG5cdFx0XHRjdXN0b21DdXJ2ZSA9IFwibGluZWFyXCJcblx0XHRlbHNlXG5cdFx0XHRjdXN0b21DdXJ2ZSA9IFwiZWFzZS1pbi1vdXRcIlxuXG5cdFx0QHByb3h5LmFuaW1hdGVcblx0XHRcdHByb3BlcnRpZXM6XG5cdFx0XHRcdHg6IDUwMCAqICh2YWx1ZSAvIDEwMClcblx0XHRcdHRpbWU6IHRpbWVcblx0XHRcdGN1cnZlOiBjdXN0b21DdXJ2ZVxuXG5cdFx0QGN1cnJlbnRWYWx1ZSA9IHZhbHVlXG5cblx0c3RhcnRBdDogKHZhbHVlKSAtPlxuXHRcdEBwcm94eS5hbmltYXRlXG5cdFx0XHRwcm9wZXJ0aWVzOlxuXHRcdFx0XHR4OiA1MDAgKiAodmFsdWUgLyAxMDApXG5cdFx0XHR0aW1lOiAwLjAwMVxuXG5cdFx0QGN1cnJlbnRWYWx1ZSA9IHZhbHVlXG5cblxuXG5cdGhpZGU6IC0+XG5cdFx0QC5vcGFjaXR5ID0gMFxuXG5cdHNob3c6IC0+XG5cdFx0QC5vcGFjaXR5ID0gMVxuXG5cdG9uRmluaXNoZWQ6IC0+XG5cbiIsIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQ0FBO0FEQUEsSUFBQTs7O0FBQU0sT0FBTyxDQUFDOzs7bUJBQ2IsWUFBQSxHQUFjOztFQUVELGdCQUFDLE9BQUQ7QUFFWixRQUFBO0lBRmEsSUFBQyxDQUFBLDRCQUFELFVBQVM7O1VBRWQsQ0FBQyxhQUFjOzs7V0FDZixDQUFDLGNBQWU7OztXQUNoQixDQUFDLFVBQVc7OztXQUVaLENBQUMsY0FBZTs7O1dBQ2hCLENBQUMsV0FBWTs7O1dBQ2IsQ0FBQyxjQUFlOzs7V0FFaEIsQ0FBQyxhQUFjOzs7V0FDZixDQUFDLGVBQWdCOzs7V0FDakIsQ0FBQyxrQkFBbUI7OztXQUNwQixDQUFDLGtCQUFtQjs7SUFFNUIsSUFBQyxDQUFBLE9BQU8sQ0FBQyxLQUFULEdBQWlCO0lBRWpCLElBQUMsQ0FBQSxPQUFPLENBQUMsT0FBVCxHQUFvQixJQUFDLENBQUEsT0FBTyxDQUFDLFVBQVYsR0FBd0IsSUFBQyxDQUFBLE9BQU8sQ0FBQztJQUVwRCx3Q0FBTSxJQUFDLENBQUEsT0FBUDtJQUVBLElBQUMsQ0FBQyxlQUFGLEdBQW9CO0lBQ3BCLElBQUMsQ0FBQyxNQUFGLEdBQVcsSUFBQyxDQUFBLE9BQU8sQ0FBQztJQUNwQixJQUFDLENBQUMsS0FBRixHQUFVLElBQUMsQ0FBQSxPQUFPLENBQUM7SUFDbkIsSUFBQyxDQUFDLFFBQUYsR0FBYSxDQUFDO0lBR2QsSUFBQyxDQUFDLFVBQUYs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
153 |
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/framer.vekter.js:
--------------------------------------------------------------------------------
1 | (function(scope) {if (scope["__vekterVariables"]) { scope["__vekterVariables"].map(function(variable) { delete scope[variable] } ) };Object.assign(scope, {});scope["__vekterVariables"] = [""];if (typeof Framer.CurrentContext.layout === 'function') {Framer.CurrentContext.layout()};})(window);
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/images/cursor-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/images/cursor-active.png
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/images/cursor-active@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/images/cursor-active@2x.png
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/images/cursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/images/cursor.png
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/images/cursor@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/images/cursor@2x.png
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/images/icon-120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/images/icon-120.png
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/images/icon-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/images/icon-152.png
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/images/icon-180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/images/icon-180.png
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/images/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/images/icon-192.png
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/images/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/framer/images/icon-76.png
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | border: none;
5 | -webkit-user-select: none;
6 | -webkit-tap-highlight-color: rgba(0,0,0,0);
7 | }
8 |
9 | body {
10 | background-color: #fff;
11 | font: 28px/1em "Helvetica";
12 | color: gray;
13 | overflow: hidden;
14 | }
15 |
16 | a {
17 | color: gray;
18 | }
19 |
20 | body {
21 | cursor: url('images/cursor.png') 32 32, auto;
22 | cursor: -webkit-image-set(
23 | url('images/cursor.png') 1x,
24 | url('images/cursor@2x.png') 2x
25 | ) 32 32, auto;
26 | }
27 |
28 | body:active {
29 | cursor: url('images/cursor-active.png') 32 32, auto;
30 | cursor: -webkit-image-set(
31 | url('images/cursor-active.png') 1x,
32 | url('images/cursor-active@2x.png') 2x
33 | ) 32 32, auto;
34 | }
35 |
36 | .framerAlertBackground {
37 | position: absolute; top:0px; left:0px; right:0px; bottom:0px;
38 | z-index: 1000;
39 | background-color: #fff;
40 | }
41 |
42 | .framerAlert {
43 | font:400 14px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif;
44 | -webkit-font-smoothing:antialiased;
45 | color:#616367; text-align:center;
46 | position: absolute; top:40%; left:50%; width:260px; margin-left:-130px;
47 | }
48 | .framerAlert strong { font-weight:500; color:#000; margin-bottom:8px; display:block; }
49 | .framerAlert a { color:#28AFFA; }
50 | .framerAlert .btn {
51 | font-weight:500; text-decoration:none; line-height:1;
52 | display:inline-block; padding:6px 12px 7px 12px;
53 | border-radius:3px; margin-top:12px;
54 | background:#28AFFA; color:#fff;
55 | }
56 |
57 | ::-webkit-scrollbar {
58 | display: none;
59 | }
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/framer/version:
--------------------------------------------------------------------------------
1 | 12
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/images/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/AppleWatchActivities.framer/images/.gitkeep
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Examples/AppleWatchActivities.framer/modules/circleModule.coffee:
--------------------------------------------------------------------------------
1 | class exports.Circle extends Layer
2 | currentValue: null
3 |
4 | constructor: (@options={}) ->
5 |
6 | @options.circleSize ?= 300
7 | @options.strokeWidth ?= 24
8 | @options.linecap ?= "round"
9 |
10 | @options.strokeColor ?= "#fc245c"
11 | @options.topColor ?= null
12 | @options.bottomColor ?= null
13 |
14 | @options.hasCounter ?= null
15 | @options.counterColor ?= "#fff"
16 | @options.counterFontSize ?= 60
17 | @options.hasLinearEasing ?= false
18 |
19 | @options.value = 2
20 |
21 | @options.viewBox = (@options.circleSize) + @options.strokeWidth
22 |
23 | super @options
24 |
25 | @.backgroundColor = ""
26 | @.height = @options.viewBox
27 | @.width = @options.viewBox
28 | @.rotation = -90
29 |
30 |
31 | @.pathLength = Math.PI * @options.circleSize
32 |
33 | @.circleID = "circle" + Math.floor(Math.random()*1000)
34 | @.gradientID = "circle" + Math.floor(Math.random()*1000)
35 |
36 | # Put this inside lineargradient
37 | # gradientUnits="userSpaceOnUse"
38 | # x1="0%" y1="0%" x2="50%" y2="0%" gradientTransform="rotate(120)"
39 |
40 |
41 | if @options.hasCounter isnt null
42 | counter = new Layer
43 | parent: @
44 | html: ""
45 | width: @.width
46 | height: @.height
47 | backgroundColor: ""
48 | rotation: 90
49 | color: @options.counterColor
50 |
51 | style = {
52 | textAlign: "center"
53 | fontSize: "#{@options.counterFontSize}px"
54 | lineHeight: "#{@.height}px"
55 | fontWeight: "600"
56 | fontFamily: "-apple-system, Helvetica, Arial, sans-serif"
57 | boxSizing: "border-box"
58 | height: @.height
59 | }
60 |
61 | counter.style = style
62 |
63 | numberStart = 0
64 | numberEnd = 100
65 | numberDuration = 2
66 |
67 | numberNow = numberStart
68 | numberInterval = numberEnd - numberStart
69 |
70 |
71 | @.html = """
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
90 | """
91 |
92 | self = @
93 | Utils.domComplete ->
94 | self.path = document.querySelector("##{self.circleID}")
95 |
96 | @proxy = new Layer
97 | opacity: 0
98 | name: "circuleModuleProxy"
99 |
100 | @proxy.sendToBack()
101 |
102 | @proxy.on Events.AnimationEnd, (animation, layer) ->
103 | self.onFinished()
104 |
105 | @proxy.on 'change:x', ->
106 |
107 | offset = Utils.modulate(@.x, [0, 500], [self.pathLength, 0])
108 |
109 | self.path.setAttribute 'stroke-dashoffset', offset
110 |
111 | if self.options.hasCounter isnt null
112 | numberNow = Utils.round(self.proxy.x / 5)
113 | counter.html = numberNow
114 |
115 | Utils.domComplete ->
116 | self.proxy.x = 0.1
117 |
118 | changeTo: (value, time) ->
119 | if time is undefined
120 | time = 2
121 |
122 | if @options.hasLinearEasing is true
123 | customCurve = "linear"
124 | else
125 | customCurve = "ease-in-out"
126 |
127 | @proxy.animate
128 | properties:
129 | x: 500 * (value / 100)
130 | time: time
131 | curve: customCurve
132 |
133 | @currentValue = value
134 |
135 | startAt: (value) ->
136 | @proxy.animate
137 | properties:
138 | x: 500 * (value / 100)
139 | time: 0.001
140 |
141 | @currentValue = value
142 |
143 |
144 |
145 | hide: ->
146 | @.opacity = 0
147 |
148 | show: ->
149 | @.opacity = 1
150 |
151 | onFinished: ->
152 |
153 |
--------------------------------------------------------------------------------
/Examples/Countdown.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 | # Framer Specific
31 | .*.html
32 | framer/*.old*
33 | framer/.*.hash
34 | framer/backup.coffee
35 | framer/backups/*
36 | framer/manifest.txt
37 | framer/metadata.json
38 | framer/preview.png
39 | framer/social-880x460.png
40 | framer/social-1200x630.png
41 |
--------------------------------------------------------------------------------
/Examples/Countdown.framer/app.coffee:
--------------------------------------------------------------------------------
1 | # Project Info
2 | # This info is presented in a widget when you share.
3 | # http://framerjs.com/docs/#info.info
4 |
5 | Framer.Info =
6 | title: "Apple Watch Activities"
7 | author: "Jonathan Arnold"
8 | twitter: "@servusjon"
9 | description: "Build with SVGCircle Module. Learn more: https://github.com/ServusJon/SVGCircle-Module-for-FramerJS"
10 |
11 |
12 | {Circle} = require "circleModule"
13 |
14 | circleMaxWidth = 160
15 | strokeWidth = 26
16 | circlePadding = 6
17 |
18 | loadingCircle = new Circle
19 | circleWidth: circleMaxWidth
20 | topColor: "#ff150f"
21 | bottomColor: "#ff23bd"
22 | strokeWidth: strokeWidth
23 | hasCounter: true
24 | counterColor: "#ff1d6a"
25 | hasLinearEasing: true
26 | loadingCircle.center()
27 |
28 | loadingCircle.changeTo(100)
29 |
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/.bookmark:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/.bookmark
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "orientation" : 0,
3 | "updateDelay" : 0.3,
4 | "designModeSelected" : 0,
5 | "cachedDeviceHeight" : 0,
6 | "contentScale" : 1,
7 | "cachedDeviceWidth" : 0,
8 | "deviceType" : "fullscreen",
9 | "sharedPrototype" : 0,
10 | "propertyPanelToggleStates" : {
11 |
12 | },
13 | "projectId" : "3D937E69-52A6-4769-A424-E93D321BF58D",
14 | "deviceOrientation" : 0,
15 | "selectedHand" : "",
16 | "showBezel" : 0,
17 | "foldedCodeRanges" : [
18 | "{107, 213}"
19 | ],
20 | "deviceScale" : 1
21 | }
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/design.vekter:
--------------------------------------------------------------------------------
1 | {
2 | "version" : 20,
3 | "root" : {
4 | "id" : "tB0fhMSIV",
5 | "__class" : "CanvasNode",
6 | "parentid" : null,
7 | "children" : [
8 |
9 | ]
10 | }
11 | }
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/framer.generated.js:
--------------------------------------------------------------------------------
1 | // This is autogenerated by Framer
2 |
3 |
4 | if (!window.Framer && window._bridge) {window._bridge('runtime.error', {message:'[framer.js] Framer library missing or corrupt. Select File → Update Framer Library.'})}
5 | if (DeviceComponent) {DeviceComponent.Devices["iphone-6-silver"].deviceImageJP2 = false};
6 | if (window.Framer) {window.Framer.Defaults.DeviceView = {"deviceScale":1,"selectedHand":"","deviceType":"fullscreen","contentScale":1,"hideBezel":true,"orientation":0};
7 | }
8 | if (window.Framer) {window.Framer.Defaults.DeviceComponent = {"deviceScale":1,"selectedHand":"","deviceType":"fullscreen","contentScale":1,"hideBezel":true,"orientation":0};
9 | }
10 | window.FramerStudioInfo = {"deviceImagesUrl":"\/_server\/resources\/DeviceImages","documentTitle":"Countdown.framer"};
11 |
12 | Framer.Device = new Framer.DeviceView();
13 | Framer.Device.setupContext();
--------------------------------------------------------------------------------
/Examples/Countdown.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 += ""
39 | html += "
Error: Not A WebKit Browser "
40 | html += "Your browser is not supported.
Please use Safari or Chrome.
"
41 | html += "
Try anyway "
42 | html += "
"
43 |
44 | showAlert(html)
45 | }
46 |
47 | function showFileLoadingAlert() {
48 | var html = ""
49 | html += ""
50 | html += "
Error: Local File Restrictions "
51 | html += "Preview this prototype with Framer Mirror or learn more about "
52 | html += "
file restrictions .
"
53 | html += "
Try anyway "
54 | html += "
"
55 |
56 | showAlert(html)
57 | }
58 |
59 | function loadProject(callback) {
60 | CoffeeScript.load("app.coffee", callback)
61 | }
62 |
63 | function setDefaultPageTitle() {
64 | // If no title was set we set it to the project folder name so
65 | // you get a nice name on iOS if you bookmark to desktop.
66 | document.addEventListener("DOMContentLoaded", function() {
67 | if (document.title == "") {
68 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) {
69 | document.title = window.FramerStudioInfo.documentTitle
70 | } else {
71 | document.title = window.location.pathname.replace(/\//g, "")
72 | }
73 | }
74 | })
75 | }
76 |
77 | function init() {
78 |
79 | if (Utils.isFramerStudio()) {
80 | return
81 | }
82 |
83 | setDefaultPageTitle()
84 |
85 | if (!isCompatibleBrowser()) {
86 | return showBrowserAlert()
87 | }
88 |
89 | if (!isFileLoadingAllowed()) {
90 | return showFileLoadingAlert()
91 | }
92 |
93 | loadProject(function(){
94 | // CoffeeScript: Framer?.CurrentContext?.emit?("loaded:project")
95 | var context;
96 | if (typeof Framer !== "undefined" && Framer !== null) {
97 | if ((context = Framer.CurrentContext) != null) {
98 | if (typeof context.emit === "function") {
99 | context.emit("loaded:project");
100 | }
101 | }
102 | }
103 | })
104 | }
105 |
106 | init()
107 |
108 | })()
109 |
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/framer.modules.js:
--------------------------------------------------------------------------------
1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n \n \n \n \n \n \n \n";
80 | self = this;
81 | Utils.domComplete(function() {
82 | return self.path = document.querySelector("#" + self.circleID);
83 | });
84 | this.proxy = new Layer({
85 | opacity: 0,
86 | name: "circuleModuleProxy"
87 | });
88 | this.proxy.sendToBack();
89 | this.proxy.on(Events.AnimationEnd, function(animation, layer) {
90 | return self.onFinished();
91 | });
92 | this.proxy.on('change:x', function() {
93 | var offset;
94 | offset = Utils.modulate(this.x, [0, 500], [self.pathLength, 0]);
95 | self.path.setAttribute('stroke-dashoffset', offset);
96 | if (self.options.hasCounter !== null) {
97 | numberNow = Utils.round(self.proxy.x / 5);
98 | return counter.html = numberNow;
99 | }
100 | });
101 | Utils.domComplete(function() {
102 | return self.proxy.x = 0.1;
103 | });
104 | }
105 |
106 | Circle.prototype.changeTo = function(value, time) {
107 | var customCurve;
108 | if (time === void 0) {
109 | time = 2;
110 | }
111 | if (this.options.hasLinearEasing === true) {
112 | customCurve = "linear";
113 | } else {
114 | customCurve = "ease-in-out";
115 | }
116 | this.proxy.animate({
117 | properties: {
118 | x: 500 * (value / 100)
119 | },
120 | time: time,
121 | curve: customCurve
122 | });
123 | return this.currentValue = value;
124 | };
125 |
126 | Circle.prototype.startAt = function(value) {
127 | this.proxy.animate({
128 | properties: {
129 | x: 500 * (value / 100)
130 | },
131 | time: 0.001
132 | });
133 | return this.currentValue = value;
134 | };
135 |
136 | Circle.prototype.hide = function() {
137 | return this.opacity = 0;
138 | };
139 |
140 | Circle.prototype.show = function() {
141 | return this.opacity = 1;
142 | };
143 |
144 | Circle.prototype.onFinished = function() {};
145 |
146 | return Circle;
147 |
148 | })(Layer);
149 |
150 |
151 | },{}]},{},[])
152 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhbWVyLm1vZHVsZXMuanMiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL1VzZXJzL0pvbmF0aGFuLkFybm9sZC9EZXNrdG9wL2dpdGh1Yi9TVkdDaXJjbGUtTW9kdWxlLWZvci1GcmFtZXJKUy9FeGFtcGxlcy9Db3VudGRvd24uZnJhbWVyL21vZHVsZXMvY2lyY2xlTW9kdWxlLmNvZmZlZSIsIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiXSwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgZXhwb3J0cy5DaXJjbGUgZXh0ZW5kcyBMYXllclxuXHRjdXJyZW50VmFsdWU6IG51bGxcblxuXHRjb25zdHJ1Y3RvcjogKEBvcHRpb25zPXt9KSAtPlxuXG5cdFx0QG9wdGlvbnMuY2lyY2xlU2l6ZSA/PSAzMDBcblx0XHRAb3B0aW9ucy5zdHJva2VXaWR0aCA/PSAyNFxuXHRcdEBvcHRpb25zLmxpbmVjYXAgPz0gXCJyb3VuZFwiXG5cblx0XHRAb3B0aW9ucy5zdHJva2VDb2xvciA/PSBcIiNmYzI0NWNcIlxuXHRcdEBvcHRpb25zLnRvcENvbG9yID89IG51bGxcblx0XHRAb3B0aW9ucy5ib3R0b21Db2xvciA/PSBudWxsXG5cblx0XHRAb3B0aW9ucy5oYXNDb3VudGVyID89IG51bGxcblx0XHRAb3B0aW9ucy5jb3VudGVyQ29sb3IgPz0gXCIjZmZmXCJcblx0XHRAb3B0aW9ucy5jb3VudGVyRm9udFNpemUgPz0gNjBcblx0XHRAb3B0aW9ucy5oYXNMaW5lYXJFYXNpbmcgPz0gZmFsc2VcblxuXHRcdEBvcHRpb25zLnZhbHVlID0gMlxuXG5cdFx0QG9wdGlvbnMudmlld0JveCA9IChAb3B0aW9ucy5jaXJjbGVTaXplKSArIEBvcHRpb25zLnN0cm9rZVdpZHRoXG5cblx0XHRzdXBlciBAb3B0aW9uc1xuXG5cdFx0QC5iYWNrZ3JvdW5kQ29sb3IgPSBcIlwiXG5cdFx0QC5oZWlnaHQgPSBAb3B0aW9ucy52aWV3Qm94XG5cdFx0QC53aWR0aCA9IEBvcHRpb25zLnZpZXdCb3hcblx0XHRALnJvdGF0aW9uID0gLTkwXG5cblxuXHRcdEAucGF0aExlbmd0aCA9IE1hdGguUEkgKiBAb3B0aW9ucy5jaXJjbGVTaXplXG5cblx0XHRALmNpcmNsZUlEID0gXCJjaXJjbGVcIiArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSoxMDAwKVxuXHRcdEAuZ3JhZGllbnRJRCA9IFwiY2lyY2xlXCIgKyBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkqMTAwMClcblxuXHRcdCMgUHV0IHRoaXMgaW5zaWRlIGxpbmVhcmdyYWRpZW50XG5cdFx0IyBncmFkaWVudFVuaXRzPVwidXNlclNwYWNlT25Vc2VcIlxuXHRcdCMgICAgeDE9XCIwJVwiIHkxPVwiMCVcIiB4Mj1cIjUwJVwiIHkyPVwiMCVcIiBncmFkaWVudFRyYW5zZm9ybT1cInJvdGF0ZSgxMjApXCJcblxuXG5cdFx0aWYgQG9wdGlvbnMuaGFzQ291bnRlciBpc250IG51bGxcblx0XHRcdGNvdW50ZXIgPSBuZXcgTGF5ZXJcblx0XHRcdFx0cGFyZW50OiBAXG5cdFx0XHRcdGh0bWw6IFwiXCJcblx0XHRcdFx0d2lkdGg6IEAud2lkdGhcblx0XHRcdFx0aGVpZ2h0OiBALmhlaWdodFxuXHRcdFx0XHRiYWNrZ3JvdW5kQ29sb3I6IFwiXCJcblx0XHRcdFx0cm90YXRpb246IDkwXG5cdFx0XHRcdGNvbG9yOiBAb3B0aW9ucy5jb3VudGVyQ29sb3JcblxuXHRcdFx0c3R5bGUgPSB7XG5cdFx0XHRcdHRleHRBbGlnbjogXCJjZW50ZXJcIlxuXHRcdFx0XHRmb250U2l6ZTogXCIje0BvcHRpb25zLmNvdW50ZXJGb250U2l6ZX1weFwiXG5cdFx0XHRcdGxpbmVIZWlnaHQ6IFwiI3tALmhlaWdodH1weFwiXG5cdFx0XHRcdGZvbnRXZWlnaHQ6IFwiNjAwXCJcblx0XHRcdFx0Zm9udEZhbWlseTogXCItYXBwbGUtc3lzdGVtLCBIZWx2ZXRpY2EsIEFyaWFsLCBzYW5zLXNlcmlmXCJcblx0XHRcdFx0Ym94U2l6aW5nOiBcImJvcmRlci1ib3hcIlxuXHRcdFx0XHRoZWlnaHQ6IEAuaGVpZ2h0XG5cdFx0XHR9XG5cblx0XHRcdGNvdW50ZXIuc3R5bGUgPSBzdHlsZVxuXG5cdFx0XHRudW1iZXJTdGFydCA9IDBcblx0XHRcdG51bWJlckVuZCA9IDEwMFxuXHRcdFx0bnVtYmVyRHVyYXRpb24gPSAyXG5cblx0XHRcdG51bWJlck5vdyA9IG51bWJlclN0YXJ0XG5cdFx0XHRudW1iZXJJbnRlcnZhbCA9IG51bWJlckVuZCAtIG51bWJlclN0YXJ0XG5cblxuXHRcdEAuaHRtbCA9IFwiXCJcIlxuXHRcdFx0PHN2ZyB2aWV3Qm94PSctI3tAb3B0aW9ucy5zdHJva2VXaWR0aC8yfSAtI3tAb3B0aW9ucy5zdHJva2VXaWR0aC8yfSAje0BvcHRpb25zLnZpZXdCb3h9ICN7QG9wdGlvbnMudmlld0JveH0nID5cblx0XHRcdFx0PGRlZnM+XG5cdFx0XHRcdCAgICA8bGluZWFyR3JhZGllbnQgaWQ9JyN7QGdyYWRpZW50SUR9JyA+XG5cdFx0XHRcdCAgICAgICAgPHN0b3Agb2Zmc2V0PVwiMCVcIiBzdG9wLWNvbG9yPScje2lmIEBvcHRpb25zLnRvcENvbG9yIGlzbnQgbnVsbCB0aGVuIEBvcHRpb25zLmJvdHRvbUNvbG9yIGVsc2UgQG9wdGlvbnMuc3Ryb2tlQ29sb3J9Jy8+XG5cdFx0XHRcdCAgICAgICAgPHN0b3Agb2Zmc2V0PVwiMTAwJVwiIHN0b3AtY29sb3I9JyN7aWYgQG9wdGlvbnMudG9wQ29sb3IgaXNudCBudWxsIHRoZW4gQG9wdGlvbnMudG9wQ29sb3IgZWxzZSBAb3B0aW9ucy5zdHJva2VDb2xvcn0nIHN0b3Atb3BhY2l0eT1cIjFcIiAvPlxuXHRcdFx0XHQgICAgPC9saW5lYXJHcmFkaWVudD5cblx0XHRcdFx0PC9kZWZzPlxuXHRcdFx0XHQ8Y2lyY2xlIGlkPScje0BjaXJjbGVJRH0nXG5cdFx0XHRcdFx0XHRmaWxsPSdub25lJ1xuXHRcdFx0XHRcdFx0c3Ryb2tlLWxpbmVjYXA9JyN7QG9wdGlvbnMubGluZWNhcH0nXG5cdFx0XHRcdFx0XHRzdHJva2Utd2lkdGggICAgICA9ICcje0BvcHRpb25zLnN0cm9rZVdpZHRofSdcblx0XHRcdFx0XHRcdHN0cm9rZS1kYXNoYXJyYXkgID0gJyN7QC5wYXRoTGVuZ3RofSdcblx0XHRcdFx0XHRcdHN0cm9rZS1kYXNob2Zmc2V0ID0gJzAnXG5cdFx0XHRcdFx0XHRzdHJva2U9XCJ1cmwoIyN7QGdyYWRpZW50SUR9KVwiXG5cdFx0XHRcdFx0XHRzdHJva2Utd2lkdGg9XCIxMFwiXG5cdFx0XHRcdFx0XHRjeCA9ICcje0BvcHRpb25zLmNpcmNsZVNpemUvMn0nXG5cdFx0XHRcdFx0XHRjeSA9ICcje0BvcHRpb25zLmNpcmNsZVNpemUvMn0nXG5cdFx0XHRcdFx0XHRyICA9ICcje0BvcHRpb25zLmNpcmNsZVNpemUvMn0nPlxuXHRcdFx0PC9zdmc+XCJcIlwiXG5cblx0XHRzZWxmID0gQFxuXHRcdFV0aWxzLmRvbUNvbXBsZXRlIC0+XG5cdFx0XHRzZWxmLnBhdGggPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiIyN7c2VsZi5jaXJjbGVJRH1cIilcblxuXHRcdEBwcm94eSA9IG5ldyBMYXllclxuXHRcdFx0b3BhY2l0eTogMFxuXHRcdFx0bmFtZTogXCJjaXJjdWxlTW9kdWxlUHJveHlcIlxuXHRcdFx0XG5cdFx0QHByb3h5LnNlbmRUb0JhY2soKVxuXG5cdFx0QHByb3h5Lm9uIEV2ZW50cy5BbmltYXRpb25FbmQsIChhbmltYXRpb24sIGxheWVyKSAtPlxuXHRcdFx0c2VsZi5vbkZpbmlzaGVkKClcblxuXHRcdEBwcm94eS5vbiAnY2hhbmdlOngnLCAtPlxuXG5cdFx0XHRvZmZzZXQgPSBVdGlscy5tb2R1bGF0ZShALngsIFswLCA1MDBdLCBbc2VsZi5wYXRoTGVuZ3RoLCAwXSlcblxuXHRcdFx0c2VsZi5wYXRoLnNldEF0dHJpYnV0ZSAnc3Ryb2tlLWRhc2hvZmZzZXQnLCBvZmZzZXRcblxuXHRcdFx0aWYgc2VsZi5vcHRpb25zLmhhc0NvdW50ZXIgaXNudCBudWxsXG5cdFx0XHRcdG51bWJlck5vdyA9IFV0aWxzLnJvdW5kKHNlbGYucHJveHkueCAvIDUpXG5cdFx0XHRcdGNvdW50ZXIuaHRtbCA9IG51bWJlck5vd1xuXG5cdFx0VXRpbHMuZG9tQ29tcGxldGUgLT5cblx0XHRcdHNlbGYucHJveHkueCA9IDAuMVxuXG5cdGNoYW5nZVRvOiAodmFsdWUsIHRpbWUpIC0+XG5cdFx0aWYgdGltZSBpcyB1bmRlZmluZWRcblx0XHRcdHRpbWUgPSAyXG5cblx0XHRpZiBAb3B0aW9ucy5oYXNMaW5lYXJFYXNpbmcgaXMgdHJ1ZVxuXHRcdFx0Y3VzdG9tQ3VydmUgPSBcImxpbmVhclwiXG5cdFx0ZWxzZVxuXHRcdFx0Y3VzdG9tQ3VydmUgPSBcImVhc2UtaW4tb3V0XCJcblxuXHRcdEBwcm94eS5hbmltYXRlXG5cdFx0XHRwcm9wZXJ0aWVzOlxuXHRcdFx0XHR4OiA1MDAgKiAodmFsdWUgLyAxMDApXG5cdFx0XHR0aW1lOiB0aW1lXG5cdFx0XHRjdXJ2ZTogY3VzdG9tQ3VydmVcblxuXHRcdEBjdXJyZW50VmFsdWUgPSB2YWx1ZVxuXG5cdHN0YXJ0QXQ6ICh2YWx1ZSkgLT5cblx0XHRAcHJveHkuYW5pbWF0ZVxuXHRcdFx0cHJvcGVydGllczpcblx0XHRcdFx0eDogNTAwICogKHZhbHVlIC8gMTAwKVxuXHRcdFx0dGltZTogMC4wMDFcblxuXHRcdEBjdXJyZW50VmFsdWUgPSB2YWx1ZVxuXG5cblxuXHRoaWRlOiAtPlxuXHRcdEAub3BhY2l0eSA9IDBcblxuXHRzaG93OiAtPlxuXHRcdEAub3BhY2l0eSA9IDFcblxuXHRvbkZpbmlzaGVkOiAtPlxuXG4iLCIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUNBQTtBREFBLElBQUE7OztBQUFNLE9BQU8sQ0FBQzs7O21CQUNiLFlBQUEsR0FBYzs7RUFFRCxnQkFBQyxPQUFEO0FBRVosUUFBQTtJQUZhLElBQUMsQ0FBQSw0QkFBRCxVQUFTOztVQUVkLENBQUMsYUFBYzs7O1dBQ2YsQ0FBQyxjQUFlOzs7V0FDaEIsQ0FBQyxVQUFXOzs7V0FFWixDQUFDLGNBQWU7OztXQUNoQixDQUFDLFdBQVk7OztXQUNiLENBQUMsY0FBZTs7O1dBRWhCLENBQUMsYUFBYzs7O1dBQ2YsQ0FBQyxlQUFnQjs7O1dBQ2pCLENBQUMsa0JBQW1COzs7V0FDcEIsQ0FBQyxrQkFBbUI7O0lBRTVCLElBQUMsQ0FBQSxPQUFPLENBQUMsS0FBVCxHQUFpQjtJQUVqQixJQUFDLENBQUEsT0FBTyxDQUFDLE9BQVQsR0FBb0IsSUFBQyxDQUFBLE9BQU8sQ0FBQyxVQUFWLEdBQXdCLElBQUMsQ0FBQSxPQUFPLENBQUM7SUFFcEQsd0NBQU0sSUFBQyxDQUFBLE9BQVA7SUFFQSxJQUFDLENBQUMsZUFBRixHQUFvQjtJQUNwQixJQUFDLENBQUMsTUFBRixHQUFXLElBQUMsQ0FBQSxPQUFPLENBQUM7SUFDcEIsSUFBQyxDQUFDLEtBQUYsR0FBVSxJQUFDLENBQUEsT0FBTyxDQUFDO0lBQ25CLElBQUMsQ0FBQyxRQUFGLEdBQWEsQ0FBQztJQUdkLElBQUMsQ0FBQyxVQUFGLEdBQWUsSUFBSSxD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
153 |
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/framer.vekter.js:
--------------------------------------------------------------------------------
1 | (function(scope) {if (scope["__vekterVariables"]) { scope["__vekterVariables"].map(function(variable) { delete scope[variable] } ) };Object.assign(scope, {});scope["__vekterVariables"] = [""];if (typeof Framer.CurrentContext.layout === 'function') {Framer.CurrentContext.layout()};})(window);
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/images/cursor-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/images/cursor-active.png
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/images/cursor-active@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/images/cursor-active@2x.png
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/images/cursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/images/cursor.png
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/images/cursor@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/images/cursor@2x.png
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/images/icon-120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/images/icon-120.png
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/images/icon-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/images/icon-152.png
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/images/icon-180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/images/icon-180.png
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/images/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/images/icon-192.png
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/images/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/framer/images/icon-76.png
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | border: none;
5 | -webkit-user-select: none;
6 | -webkit-tap-highlight-color: rgba(0,0,0,0);
7 | }
8 |
9 | body {
10 | background-color: #fff;
11 | font: 28px/1em "Helvetica";
12 | color: gray;
13 | overflow: hidden;
14 | }
15 |
16 | a {
17 | color: gray;
18 | }
19 |
20 | body {
21 | cursor: url('images/cursor.png') 32 32, auto;
22 | cursor: -webkit-image-set(
23 | url('images/cursor.png') 1x,
24 | url('images/cursor@2x.png') 2x
25 | ) 32 32, auto;
26 | }
27 |
28 | body:active {
29 | cursor: url('images/cursor-active.png') 32 32, auto;
30 | cursor: -webkit-image-set(
31 | url('images/cursor-active.png') 1x,
32 | url('images/cursor-active@2x.png') 2x
33 | ) 32 32, auto;
34 | }
35 |
36 | .framerAlertBackground {
37 | position: absolute; top:0px; left:0px; right:0px; bottom:0px;
38 | z-index: 1000;
39 | background-color: #fff;
40 | }
41 |
42 | .framerAlert {
43 | font:400 14px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif;
44 | -webkit-font-smoothing:antialiased;
45 | color:#616367; text-align:center;
46 | position: absolute; top:40%; left:50%; width:260px; margin-left:-130px;
47 | }
48 | .framerAlert strong { font-weight:500; color:#000; margin-bottom:8px; display:block; }
49 | .framerAlert a { color:#28AFFA; }
50 | .framerAlert .btn {
51 | font-weight:500; text-decoration:none; line-height:1;
52 | display:inline-block; padding:6px 12px 7px 12px;
53 | border-radius:3px; margin-top:12px;
54 | background:#28AFFA; color:#fff;
55 | }
56 |
57 | ::-webkit-scrollbar {
58 | display: none;
59 | }
--------------------------------------------------------------------------------
/Examples/Countdown.framer/framer/version:
--------------------------------------------------------------------------------
1 | 12
--------------------------------------------------------------------------------
/Examples/Countdown.framer/images/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/Examples/Countdown.framer/images/.gitkeep
--------------------------------------------------------------------------------
/Examples/Countdown.framer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Examples/Countdown.framer/modules/circleModule.coffee:
--------------------------------------------------------------------------------
1 | class exports.Circle extends Layer
2 | currentValue: null
3 |
4 | constructor: (@options={}) ->
5 |
6 | @options.circleSize ?= 300
7 | @options.strokeWidth ?= 24
8 | @options.linecap ?= "round"
9 |
10 | @options.strokeColor ?= "#fc245c"
11 | @options.topColor ?= null
12 | @options.bottomColor ?= null
13 |
14 | @options.hasCounter ?= null
15 | @options.counterColor ?= "#fff"
16 | @options.counterFontSize ?= 60
17 | @options.hasLinearEasing ?= false
18 |
19 | @options.value = 2
20 |
21 | @options.viewBox = (@options.circleSize) + @options.strokeWidth
22 |
23 | super @options
24 |
25 | @.backgroundColor = ""
26 | @.height = @options.viewBox
27 | @.width = @options.viewBox
28 | @.rotation = -90
29 |
30 |
31 | @.pathLength = Math.PI * @options.circleSize
32 |
33 | @.circleID = "circle" + Math.floor(Math.random()*1000)
34 | @.gradientID = "circle" + Math.floor(Math.random()*1000)
35 |
36 | # Put this inside lineargradient
37 | # gradientUnits="userSpaceOnUse"
38 | # x1="0%" y1="0%" x2="50%" y2="0%" gradientTransform="rotate(120)"
39 |
40 |
41 | if @options.hasCounter isnt null
42 | counter = new Layer
43 | parent: @
44 | html: ""
45 | width: @.width
46 | height: @.height
47 | backgroundColor: ""
48 | rotation: 90
49 | color: @options.counterColor
50 |
51 | style = {
52 | textAlign: "center"
53 | fontSize: "#{@options.counterFontSize}px"
54 | lineHeight: "#{@.height}px"
55 | fontWeight: "600"
56 | fontFamily: "-apple-system, Helvetica, Arial, sans-serif"
57 | boxSizing: "border-box"
58 | height: @.height
59 | }
60 |
61 | counter.style = style
62 |
63 | numberStart = 0
64 | numberEnd = 100
65 | numberDuration = 2
66 |
67 | numberNow = numberStart
68 | numberInterval = numberEnd - numberStart
69 |
70 |
71 | @.html = """
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
90 | """
91 |
92 | self = @
93 | Utils.domComplete ->
94 | self.path = document.querySelector("##{self.circleID}")
95 |
96 | @proxy = new Layer
97 | opacity: 0
98 | name: "circuleModuleProxy"
99 |
100 | @proxy.sendToBack()
101 |
102 | @proxy.on Events.AnimationEnd, (animation, layer) ->
103 | self.onFinished()
104 |
105 | @proxy.on 'change:x', ->
106 |
107 | offset = Utils.modulate(@.x, [0, 500], [self.pathLength, 0])
108 |
109 | self.path.setAttribute 'stroke-dashoffset', offset
110 |
111 | if self.options.hasCounter isnt null
112 | numberNow = Utils.round(self.proxy.x / 5)
113 | counter.html = numberNow
114 |
115 | Utils.domComplete ->
116 | self.proxy.x = 0.1
117 |
118 | changeTo: (value, time) ->
119 | if time is undefined
120 | time = 2
121 |
122 | if @options.hasLinearEasing is true
123 | customCurve = "linear"
124 | else
125 | customCurve = "ease-in-out"
126 |
127 | @proxy.animate
128 | properties:
129 | x: 500 * (value / 100)
130 | time: time
131 | curve: customCurve
132 |
133 | @currentValue = value
134 |
135 | startAt: (value) ->
136 | @proxy.animate
137 | properties:
138 | x: 500 * (value / 100)
139 | time: 0.001
140 |
141 | @currentValue = value
142 |
143 |
144 |
145 | hide: ->
146 | @.opacity = 0
147 |
148 | show: ->
149 | @.opacity = 1
150 |
151 | onFinished: ->
152 |
153 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SVG Circle Module for Loading, Countdown or for fun
2 |
3 | #### Live Demo
4 | Apple Watch Activities: [http://share.framerjs.com/0w3wirptkfc9/](http://share.framerjs.com/0w3wirptkfc9/)
5 | Countdown: [http://share.framerjs.com/8as5o1wn1f0a/](http://share.framerjs.com/8as5o1wn1f0a/)
6 |
7 |
8 |
9 |
10 | Thank you [Henrique Gusso](https://twitter.com/gusso) for writing that [great article](https://medium.com/@gusso/draw-and-animate-an-svg-circle-in-framer-d4bc3a9863c1#.9kdfcl942).
11 |
12 | ## Setup
13 | 1. Download the `circleModule.coffee` file
14 | 2. Create or open a framer project and drop `circleModule.coffee` inside the /modules folder
15 | 3. Add `{Circle} = require "circleModule"` at the top of your document (case-sensitive).
16 |
17 | ## Add Circle
18 | ```coffeescript
19 | circle = new Circle
20 | ```
21 | You can also change the size of the circle `circleSize: 400` and the strokeSize `circleSize: 20`.
22 |
23 | ## Start Animation or set value initial value
24 | You can animate to a certain value (percent-based). You can change the value any time in your prototype.
25 | ```coffeescript
26 | circle.changeTo(50) # Animates to 50% of circle in the default time
27 |
28 | # Options: Speed (in seconds)
29 | circle.changeTo(50, 10) # Animates to 50% of circle in the 10s
30 | ```
31 |
32 | Or just set a initial value (percent-based)
33 | ```coffeescript
34 | circle.startAt(10)
35 | ```
36 |
37 | ## Countdown
38 | You can use the circle also for countdowns
39 | ```coffeescript
40 | countdownCircle = new Circle
41 | hasCounter: true
42 | ```
43 |
44 | Change the text color `counterColor: "#fff"` and font-size `counterFontSize: 20` to your liking.
45 |
46 | ## Callback
47 | You can get a callback when animation is completed
48 | ```coffeescript
49 | circle.onFinished = ->
50 | print "animation done"
51 | ```
52 |
53 | Get the current value of the circle
54 | ```coffeescript
55 | circle.onFinished = ->
56 | if circle.currentValue == 80 # TRUE if circle was animated to "circle.changeTo(80)"
57 | print "80%"
58 | ```
59 |
60 | ## Coloring / Gradients
61 | You can either use a plain color (default) for the circle or a gradient.
62 | ```coffeescript
63 | gradientCircle = new Circle
64 | topColor: "#7cc201"
65 | bottomColor: "#a3fe00"
66 |
67 | plainCircle = new Circle
68 | color: "#7cc201"
69 | ```
70 |
71 |
72 | ## Show / Hide Circle
73 | You can easily animate the circles visibilty using standard framer functions. For instant changes:
74 | ```coffeescript
75 | circle.hide()
76 | circle.show()
77 | ```
78 |
79 | ## Optional Properties
80 | You can also customize the circle with following properties:
81 |
82 | | property | Description|
83 | | ------------- | ------------- |
84 | | `circleSize` | The size of the circle (default: 300) |
85 | | `strokeWidth` | The thickness of the stroke (default: 24) |
86 | | `strokeColor` | The color of the stroke (default: "#fc245c") |
87 | | `linecap` | The shape of the stroke's endcaps. Use "butt", "round" or "square" (default: "round") |
88 | | `topColor` | Top Gradient Color |
89 | | `bottomColor` | Bottom Gradient Color |
90 | | `hasCounter` | Set it to `true`, will show a countdown label (default: null) |
91 | | `counterColor` | Text color of countdown label (default: "#fff") |
92 | | `counterFontSize` | Font size of countdown label (default: 60) |
93 | | `hasLinearEasing` | Allows to change the animation curve to "linear" for "ease-in-out". Set it to `true (default: null) |
94 |
95 | ```coffeescript
96 | loadingCircle = new Circle
97 | circleSize: 200
98 | strokeWidth: 30
99 | linecap: "round"
100 |
101 | topColor: "#ff150f"
102 | bottomColor: "#ff23bd"
103 |
104 | hasCounter: true
105 | counterColor: "#fff"
106 | hasLinearEasing: true
107 |
108 | counterColor: "red"
109 | counterFontSize: 100
110 |
111 | loadingCircle.center() # center the circle
112 |
113 | loadingCircle.changeTo(100)
114 |
115 | loadingCircle.onFinished = ->
116 | print "animation is done"
117 | ```
118 |
--------------------------------------------------------------------------------
/applewatchactivities.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/applewatchactivities.gif
--------------------------------------------------------------------------------
/circleModule.coffee:
--------------------------------------------------------------------------------
1 | class exports.Circle extends Layer
2 | currentValue: null
3 |
4 | constructor: (@options={}) ->
5 |
6 | @options.circleSize ?= 300
7 | @options.strokeWidth ?= 24
8 | @options.linecap ?= "round"
9 |
10 | @options.strokeColor ?= "#fc245c"
11 | @options.topColor ?= null
12 | @options.bottomColor ?= null
13 |
14 | @options.hasCounter ?= null
15 | @options.counterColor ?= "#fff"
16 | @options.counterFontSize ?= 60
17 | @options.hasLinearEasing ?= false
18 |
19 | @options.value = 2
20 |
21 | @options.viewBox = (@options.circleSize) + @options.strokeWidth
22 |
23 | super @options
24 |
25 | @.backgroundColor = ""
26 | @.height = @options.viewBox
27 | @.width = @options.viewBox
28 | @.rotation = -90
29 |
30 |
31 | @.pathLength = Math.PI * @options.circleSize
32 |
33 | @.circleID = "circle" + Math.floor(Math.random()*1000)
34 | @.gradientID = "circle" + Math.floor(Math.random()*1000)
35 |
36 | # Put this inside lineargradient
37 | # gradientUnits="userSpaceOnUse"
38 | # x1="0%" y1="0%" x2="50%" y2="0%" gradientTransform="rotate(120)"
39 |
40 |
41 | if @options.hasCounter isnt null
42 | counter = new Layer
43 | parent: @
44 | html: ""
45 | width: @.width
46 | height: @.height
47 | backgroundColor: ""
48 | rotation: 90
49 | color: @options.counterColor
50 |
51 | style = {
52 | textAlign: "center"
53 | fontSize: "#{@options.counterFontSize}px"
54 | lineHeight: "#{@.height}px"
55 | fontWeight: "600"
56 | fontFamily: "-apple-system, Helvetica, Arial, sans-serif"
57 | boxSizing: "border-box"
58 | height: @.height
59 | }
60 |
61 | counter.style = style
62 |
63 | numberStart = 0
64 | numberEnd = 100
65 | numberDuration = 2
66 |
67 | numberNow = numberStart
68 | numberInterval = numberEnd - numberStart
69 |
70 |
71 | @.html = """
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
90 | """
91 |
92 | self = @
93 | Utils.domComplete ->
94 | self.path = document.querySelector("##{self.circleID}")
95 |
96 | @proxy = new Layer
97 | opacity: 0
98 | name: "circuleModuleProxy"
99 |
100 | @proxy.sendToBack()
101 |
102 | @proxy.on Events.AnimationEnd, (animation, layer) ->
103 | self.onFinished()
104 |
105 | @proxy.on 'change:x', ->
106 |
107 | offset = Utils.modulate(@.x, [0, 500], [self.pathLength, 0])
108 |
109 | self.path.setAttribute 'stroke-dashoffset', offset
110 |
111 | if self.options.hasCounter isnt null
112 | numberNow = Utils.round(self.proxy.x / 5)
113 | counter.html = numberNow
114 |
115 | Utils.domComplete ->
116 | self.proxy.x = 0.1
117 |
118 | changeTo: (value, time) ->
119 | if time is undefined
120 | time = 2
121 |
122 | if @options.hasLinearEasing is true
123 | customCurve = "linear"
124 | else
125 | customCurve = "ease-in-out"
126 |
127 | @proxy.animate
128 | properties:
129 | x: 500 * (value / 100)
130 | time: time
131 | curve: customCurve
132 |
133 | @currentValue = value
134 |
135 | startAt: (value) ->
136 | @proxy.animate
137 | properties:
138 | x: 500 * (value / 100)
139 | time: 0.001
140 |
141 | @currentValue = value
142 |
143 |
144 |
145 | hide: ->
146 | @.opacity = 0
147 |
148 | show: ->
149 | @.opacity = 1
150 |
151 | onFinished: ->
152 |
153 |
--------------------------------------------------------------------------------
/countdown.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ServusJon/SVGCircle-Module-for-FramerJS/4fbbea8b5bbce544a7144d98c95e0c673b062915/countdown.gif
--------------------------------------------------------------------------------