Skip to content

Instantly share code, notes, and snippets.

@aprilandjan
Created November 30, 2016 15:22
Show Gist options
  • Save aprilandjan/e96880ba96182ebf1d9d87f133487943 to your computer and use it in GitHub Desktop.
Save aprilandjan/e96880ba96182ebf1d9d87f133487943 to your computer and use it in GitHub Desktop.
/**
* Created by Merlin on 16/11/30.
*/
const map = new Map()
function getElement (el) {
if (typeof el === 'string') {
el = document.querySelector(el)
}
return el
}
function getColumnDistribution (num) {
var arr = []
for (var i = 0; i < num; i++) {
arr.push(Math.floor(100 * i / num).toFixed(3) + '%')
}
return arr
}
function getHeightDistribution (num) {
var arr = []
for (var i = 0; i < num; i++) {
arr.push(0)
}
return arr
}
/**
* 实现 masonry layout
*/
class Masonry {
static init (box, config) {
box = getElement(box)
var instance = map.get(box)
if (!instance) {
instance = new Masonry(box, config)
map.set(box, instance)
}
return instance
}
/**
*
* slot: 槽选择器
* columnCount: 列数
* columnDistribution: 列分布
*
* @param config
*/
constructor (box, config) {
// 容器
this.box = box
// 槽选择器
this.slotSelector = config.slot
// 列数
this.columnCount = config.columnCount
// 列分布
this.columnDistribution = config.columnDistribution || getColumnDistribution(this.columnCount)
// 高度分布
this.heightDistribution = getHeightDistribution(this.columnCount)
// 当前最低的那个槽的序号
this.minIndex = 0
// 当前处理了的序号
this.arragedIndex = 0
}
/**
* 重新布局
*/
resetLayout () {
this.arragedIndex = 0
this.heightDistribution = getHeightDistribution(this.columnCount)
this.minIndex = 0
this.updateLayout()
}
/**
* 如果 slots 数量变化了, 只布局新增的 slot
*/
updateLayout () {
var slots = this.box.querySelectorAll(this.slotSelector)
console.log(slots)
var total = slots.length
for (var i = this.arragedIndex; i < total; i++) {
let slot = slots[i]
let rect = slot.getBoundingClientRect()
slot.style.cssText = `left: ${this.columnDistribution[this.minIndex]}; top: ${this.heightDistribution[this.minIndex]}px;`
this.heightDistribution[this.minIndex] += rect.height
let min = Math.min.apply(Math, this.heightDistribution)
this.minIndex = this.heightDistribution.indexOf(min)
this.arragedIndex ++
}
let max = Math.max.apply(Math, this.heights)
this.box.style.cssText = `height:${max}px;`
}
}
export default Masonry
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment