gems/under-os-ui/lib/under_os/ui/utils/animation.rb
module UnderOs::UI::Animation
def animate(style, options={}, &block)
if block_given?
options = style
style = nil
else
[:complete, :curve, :autoreverse, :repeat, :duration, :delay].each do |key|
options[key] = style.delete(key) if style.has_key?(key)
end
block = Proc.new{ self.style = style }
end
Animation.new(self, options, &block)
self
end
def highlight(color=:yellow, options={})
old_color = style.background
animate({background: color}, {curve: :ease_out}.merge(options))
animate({background: old_color}, {curve: :ease_in}.merge(options))
end
def fade_in(options={})
animate({opacity: 1}, options)
end
def fade_out(options={})
animate({opacity: 0}, options)
end
class Animation
CURVES = {
ease_in_out: UIViewAnimationOptionCurveEaseInOut,
ease_in: UIViewAnimationOptionCurveEaseIn,
ease_out: UIViewAnimationOptionCurveEaseOut,
linear: UIViewAnimationOptionCurveLinear
}.freeze
FX_QUEUE = {}
def initialize(view, options, &block)
@view = view
@options = options
@block = block
@options = {duration: options} if options.is_a?(Numeric)
@options[:schedule] == false ? run : schedule
end
def queue
FX_QUEUE[@view] ||= []
end
def schedule
if queue.empty?
run
else
queue << self
end
end
def run
@view.emit('animation:start')
UIView.animateWithDuration duration,
delay: delay,
options: options,
animations: ->{ @block.call },
completion: ->(finished){ run_next }
end
def duration
@options[:duration] || 0.25
end
def delay
@options[:delay] || 0.0
end
def options
options = CURVES[@options[:curve]] || @options[:curve] || UIViewAnimationCurveEaseOut
options = options | UIViewAnimationOptionAutoreverse if @options[:autoreverse]
options = options | UIViewAnimationOptionRepeat if @options[:repeat]
options | UIViewAnimationOptionAllowUserInteraction
end
def run_next
@view.emit('animation:finished')
@options[:complete].call if @options[:complete]
if next_fx = queue.shift
next_fx.run
end
end
end
end