-
-
Save MrRaindrop/a6374b67b3c3d4d12039 to your computer and use it in GitHub Desktop.
js: react+线性分割算法实现的类似flickr的图片布局
This file contains hidden or 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
var React = require('react'); | |
var EventListener = require('react/lib/EventListener'); | |
var partition = require('linear-partitioning'); | |
var TileLayout = React.createClass({ | |
getDefaultProps: function() { | |
return { | |
gutter: 0, | |
photos: [] | |
} | |
}, | |
getInitialState: function() { | |
return { | |
photos: this.props.photos, | |
gutter: this.props.gutter, | |
viewBounding: this.props.viewBounding, | |
size: [] | |
} | |
}, | |
componentDidMount: function() { | |
this.initLayout(); | |
this._resizeListener = EventListener.listen(window, 'resize', this.initLayout); | |
}, | |
componentWillUnmout: function() { | |
this._resizeListener.remove(); | |
}, | |
render: function() { | |
var photos = this.state.photos; | |
var blank = <p className="blank">(空)</p>; | |
return ( | |
<div className="tile-layout-container"> | |
{ photos.length ? photos.map(this.getGridCell) : blank } | |
</div> | |
); | |
}, | |
getGridCell: function(photo, i) { | |
var size = this.state.size[i] || []; | |
var gutter = this.state.gutter; | |
var style = { | |
padding: gutter, | |
width: size[0] - gutter * 2, | |
height: size[1] - gutter * 2 | |
}; | |
return ( | |
<div key={ i } className="tile-layout-cell" style={ style }> | |
<a href={ photo.raw } target="_blank"> | |
<img src={ photo.url } /> | |
</a> | |
</div> | |
); | |
}, | |
initLayout: function() { | |
var photos = this.state.photos; | |
var size = []; | |
if (photos.length == 0) { | |
return; | |
} | |
var bounding = this.state.viewBounding; | |
var idealHeight = bounding[1]; | |
var photoWidth = photos.map(function(p) { | |
return idealHeight * p.aspect_ratio | 0; | |
}); | |
var totalWidth = photoWidth.reduce(function(a, b) { | |
return a + b; | |
}); | |
if (totalWidth <= bounding[0]) { | |
size = photos.map(function(p, i) { | |
return [photoWidth[i], idealHeight]; | |
}); | |
this.setState({ | |
size: size | |
}); | |
return; | |
} | |
var rows = totalWidth / bounding[0] | 0; | |
var ratioSeq = photos.map(function(p) { | |
return p.aspect_ratio * 100 | 0; | |
}); | |
partitionTable = partition(ratioSeq, rows); | |
var index = 0; | |
partitionTable.forEach(function(row) { | |
var buff_size = []; | |
var rowRatio = row.reduce(function(sum, r) { | |
buff_size.push(index); | |
return sum + photos[index++].aspect_ratio; | |
}, 0); | |
var rowHeight = bounding[0] / rowRatio | 0; | |
buff_size = buff_size.map(function(index) { | |
return [rowHeight * photos[index].aspect_ratio | 0, rowHeight]; | |
}); | |
size = size.concat(buff_size); | |
}); | |
this.setState({ | |
size: size | |
}); | |
} | |
}); | |
module.exports = TileLayout; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment