Skip to content

Instantly share code, notes, and snippets.

@kemuri
Created October 7, 2016 14:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kemuri/b88322208c1332028df9ae61351ca183 to your computer and use it in GitHub Desktop.
Save kemuri/b88322208c1332028df9ae61351ca183 to your computer and use it in GitHub Desktop.
Advanced material design spinner for Framer
S = (n) ->
scale = 1
device = Framer.Device.deviceType
if device.slice(0, "apple-iphone".length) is "apple-iphone"
scale = Screen.width / 375
else if device.slice(0, "google-nexus".length) is "google-nexus"
scale = Screen.width / 360
return n * scale
class Line extends Layer
constructor: (size, thickness, color, rounded)->
super width: size, height: size, backgroundColor: null
# Left half
@leftHalfWrapper = new Layer
backgroundColor: null
width: @width / 2, height: @width
parent: @
clip: yes
force2d: yes
@leftHalfClip = new Layer
backgroundColor: null
x: @width / 2
width: @width / 2, height: @width
originX: 0, originY: 0.5
parent: @leftHalfWrapper
clip: yes
force2d: yes
@leftHalf = new Layer
backgroundColor: null
x: -@width / 2
width: @width, height: @width
borderRadius: @width / 2
borderWidth: thickness
borderColor: color
parent: @leftHalfClip
force2d: yes
# Right half
@rightHalfWrapper = new Layer
backgroundColor: null
x: @width / 2
width: @width / 2, height: @width
parent: @
clip: yes
force2d: yes
@rightHalfClip = new Layer
backgroundColor: null
x: -@width / 2
width: @width / 2, height: @width
originX: 1, originY: 0.5
parent: @rightHalfWrapper
clip: yes
force2d: yes
@rightHalf = new Layer
backgroundColor: null
width: @width, height: @width
borderRadius: @width / 2
borderWidth: thickness
borderColor: color
parent: @rightHalfClip
force2d: yes
#rounded lines
@startBall = new Layer
backgroundColor: color
width: thickness , height: thickness
borderRadius: (@width / 2)
x: @.width/2, y:@width/2
parent: @
force2d: yes
visible: rounded
@endBall = new Layer
backgroundColor: color
width: thickness , height: thickness
borderRadius: (@width / 2)
x: (@.width/2)-(thickness/2), y:0
parent: @
force2d: yes
visible: rounded
_v: 0 # min: 0, max: 1
@define "value",
get: -> @_v
set: (v) ->
@_v = v
angle = ((360*v)-90)*(Math.PI/180)
radius = (@.width/2) - (@startBall.width/2)
@startBall.x = (@.width/2 + Math.cos(angle) * radius) - @startBall.width/2;
@startBall.y = (@.width/2 + Math.sin(angle) * radius) - @startBall.width/2;
if v < 0.5
@rightHalfClip.rotationZ = 360 * v
@leftHalfClip.rotationZ = 0
else
@rightHalfClip.rotationZ = 180
@leftHalfClip.rotationZ = 360 * v - 180
class exports.Spinner extends Layer
colors: ["#DB4437", "#4285F4", "#0F9D58", "#F4B400"] # default
constructor: (@options={}) ->
@options.size = 48 unless @options.size
@options.thickness = 4 unless @options.thickness
@options.color = "#4285f4" unless @options.color
@options.changeColor = yes if typeof @options.changeColor is "undefined"
@options.rounded = false unless @options.rounded
super width: S(@options.size), height: S(@options.size), backgroundColor: null
@line = new Line S(@options.size), S(@options.thickness), @options.color, @options.rounded
@line.parent = @
_started: false
start: ->
@rotation = @line.value = 0
@opacity = 1
@_started = true
@_animate()
stop: ->
@_started = false
@animate
properties: opacity: 0
time: 0.2
_counter: 0
_animate: ->
rotate = new Animation
layer: @
properties: rotation: 360
time: 1.9
curve: "linear"
lineIn = new Animation
layer: @line
properties: value: 0.75
time: 0.64
curve: "cubic-bezier(0.4, 0.0, 0.2, 1)"
lineOut = new Animation
layer: @line
properties:
value: 0.03
rotation: 360
time: 0.78
curve: "cubic-bezier(0.4, 0.0, 0.2, 1)"
rotate.on Events.AnimationEnd, =>
@rotation = 0
rotate.start() if @_started
lineIn.on Events.AnimationEnd, =>
lineOut.start() if @_started
lineOut.on Events.AnimationEnd, =>
@line.rotation = 0
lineIn.start() if @_started
if @options.changeColor
@line.leftHalf.animate
properties: borderColor: @colors[@_counter]
time: 0.2
colorModel: "rgb"
@line.rightHalf.animate
properties: borderColor: @colors[@_counter]
time: 0.2
colorModel: "rgb"
@line.startBall.animate
properties: backgroundColor: @colors[@_counter]
time: 0.2
colorModel: "rgb"
@line.endBall.animate
properties: backgroundColor: @colors[@_counter]
time: 0.2
colorModel: "rgb"
@_counter++
@_counter = 0 if @_counter >= @colors.length
rotate.start()
lineIn.start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment