Created
June 3, 2014 02:38
-
-
Save simple10/4045cd8dff2756dbcd12 to your computer and use it in GitHub Desktop.
Famo.us masonry style layout in coffeescript – handles reflowing elements when window or container size changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FloatLayout = require 'layouts/FloatLayout' | |
layout = new FloatLayout | |
layout.sequenceFrom surfaces | |
layout.on 'afterAnimate', => | |
console.log 'animate finished' | |
surfaces = [ | |
# Array of surfaces | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ReflowLayout = require 'layouts/ReflowLayout' | |
# Float items in a responsive layout | |
class FloatLayout extends ReflowLayout | |
@DEFAULT_OPTIONS: | |
resizeDelay: 200 | |
transition: | |
duration: 200 | |
getSize: -> | |
@_size | |
reflow: (size) -> | |
i = 0 | |
col = 0 | |
row = 0 | |
len = @getSequenceLength() | |
# assume items are all the same size for now | |
itemSize = @getSequence().getSize() | |
while i < len | |
x = col * itemSize[0] | |
col++ | |
if x + itemSize[0] > size[0] | |
x = 0 | |
col = 1 | |
row++ | |
y = row * itemSize[1] | |
if @_modifiers[i] is undefined | |
@_createModifier i, itemSize, [x, y, 0], 1 | |
else | |
@_animateModifier i, itemSize, [x, y, 0], 1 | |
i++ | |
@_size = [size[0], itemSize[1]*(row+1)] | |
module.exports = FloatLayout | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ContextualView = require 'famous/views/ContextualView' | |
ViewSequence = require 'famous/core/ViewSequence' | |
OptionsManager = require 'famous/core/OptionsManager' | |
Modifier = require 'famous/core/Modifier' | |
Transform = require 'famous/core/Transform' | |
Transitionable = require 'famous/transitions/Transitionable' | |
TransitionableTransform = require 'famous/transitions/TransitionableTransform' | |
Timer = require 'famous/utilities/Timer' | |
# TODO: make sure pull request for ContextView is applied: https://github.com/Famous/views/pull/50 | |
class ReflowLayout extends ContextualView | |
@DEFAULT_OPTIONS: | |
# Amount of milliseconds to debounce resize events before calling reflow | |
resizeDelay: 200 | |
# Transition settings for repositioning items | |
transition: | |
duration: 200 | |
_nodes: null | |
_modifiers: [] | |
_states: [] | |
_contextSizeCache: [undefined, undefined] | |
_size: null | |
_animationCount: 0 | |
constructor: (options) -> | |
super | |
# TODO: make sure pull request is in master https://github.com/Famous/core/pull/32 | |
@_debouncedReflow = Timer.debounce @_reflow, @options.resizeDelay or 200 | |
getSize: -> | |
@_size or @options.size | |
### | |
# Sets the collection of renderables. | |
# | |
# @method sequenceFrom | |
# @param {Array|ViewSequence} sequence Either an array of renderables or a Famous viewSequence. | |
# @chainable | |
### | |
sequenceFrom: (sequence) -> | |
@_nodes = if sequence instanceof Array then new ViewSequence(sequence) else sequence | |
@ | |
getSequence: -> | |
@_nodes | |
# TODO: ANSWER THIS .... | |
# Why does ViewSequence create a new node when getNext is called on the last node? | |
# Felix is fixing this. | |
getSequenceLength: -> | |
@_nodes._.array.length | |
### | |
# Recalculate layout. | |
# | |
# Do reflow math here in subclass. | |
# See GridLayout for example. | |
### | |
reflow: (size) -> | |
# Override in subclass | |
_beforeReflow: (size) -> | |
return false if size[0] is @_contextSizeCache[0] and size[1] is @_contextSizeCache[1] | |
# reflow immediately the first time | |
if @_contextSizeCache[0] == undefined | |
@_reflow size | |
else | |
@_debouncedReflow size | |
@_contextSizeCache = size.slice 0 | |
_reflow: (size) -> | |
@_animationCount = 0 | |
@reflow size | |
@_eventOutput.emit 'reflow' | |
### | |
# Apply changes from this component to the corresponding document element. | |
# This includes changes to classes, styles, size, content, opacity, origin, | |
# and matrix transforms. | |
# | |
# @private | |
# @method commit | |
# @param {Context} context commit context | |
### | |
commit: (context) -> | |
return false unless @getSequenceLength() | |
transform = context.transform | |
opacity = context.opacity | |
origin = context.origin | |
size = context.size | |
return false unless size | |
@_beforeReflow size | |
sequence = @getSequence() | |
result = [] | |
i = 0 | |
len = @_modifiers.length | |
while sequence and i < len | |
item = sequence.get() | |
modifier = @_modifiers[i] | |
result.push modifier.modify | |
origin: origin | |
target: item.render() | |
sequence = sequence.getNext() | |
i++ | |
transform = Transform.moveThen [ -size[0] * origin[0], -size[1] * origin[1], 0 ], transform | |
{ | |
transform: transform | |
opacity: opacity | |
size: size | |
target: result | |
} | |
### | |
# Call from reflow. | |
# See GridLayout for example. | |
### | |
_createModifier: (index, size, position, opacity) -> | |
trans = | |
transform: new TransitionableTransform Transform.translate position... | |
opacity: new Transitionable opacity | |
size: new Transitionable size | |
@_states[index] = trans | |
@_modifiers[index] = new Modifier trans | |
### | |
# Call from reflow. | |
# See GridLayout for example. | |
### | |
_animateModifier: (index, size, position, opacity) -> | |
@_animationCount++ | |
currState = @_states[index] | |
currSize = currState.size | |
currOpacity = currState.opacity | |
currTransform = currState.transform | |
transition = @options.transition | |
currTransform.halt() | |
currOpacity.halt() | |
currSize.halt() | |
currTransform.setTranslate position, transition, @_afterAnimate | |
currSize.set size, transition | |
currOpacity.set opacity, transition | |
_afterAnimate: => | |
@_animationCount -= 1 | |
@_eventOutput.emit 'afterAnimate' if @_animationCount <= 0 | |
module.exports = ReflowLayout |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment