原生JavaScript 瀑布流 实现 zx-waterfall
栏目: JavaScript · 发布时间: 6年前
内容简介:源码地址:InstallES6+
源码地址: https://github.com/capricornc...
使用说明
Install zx-waterfall
using npm
npm i --save zx-waterfall
ES6+
import ZxWaterfall from 'zx-waterfall'
const waterfall = new ZxWaterfall({
// HTMLElement, waterfall items's outer container
container: document.getElementById('zxWaterfall'),
// children item selector, eg. '.item-container'
itemSelector: '.item-wrapper',
// item's spacing, unit px
gutter: 20,
// item's width
itemWidth: 300
})
// reset
waterfall.reset()
// loaMedias
waterfall.loadMedia(['http://xx.com/aaa.jpg'])
// change
waterfall.change()
browser
<script src="path/zx-waterfall.min.js"></script>
demo
https://capricorncd.github.io...
注意
-
container's style must bestyle.position=relative|absolute|fixed
参数options
-
container:
HTMLElement瀑布流外容器.
-
containerWidth:
Number瀑布流宽度,如果初始化时外容器未隐藏状态则需使用该参数.
默认获取外容器宽度.
-
itemSelector:
String子元素选择器,比如 样式名'.item-container'.
-
gutter:
Number元素间的间隔.
-
verticalGutter:
Number元素间垂直方向间隔,默认使用gutter值.
-
itemWidth:
Number元素宽度, 默认
300, 会根据容器宽度自动调整. -
forceItemWidth:
Boolean强制元素宽度,即使用itemWidth作为宽度值,默认
false. -
align:
String, Optional valueleft|center|right强制宽度时,元素显示靠边位置,默认
center.
源码
/**
* preload image
* @param url
* @param handler
*/
function loadImage (url, handler) {
let $el = document.createElement('img')
$el.src = url
$el.onload = handler
$el.onerror = handler
$el = null
}
/**
* to int
* @param m
* @returns {number}
*/
function int (m) {
let n = parseInt(m)
return isNaN(n) ? 0 : n
}
/**
* convert pseudoArray to array
* @param pseudoArray
* @param index
* @returns {T[]}
*/
function slice (pseudoArray, index) {
return Array.prototype.slice.call(pseudoArray, int(index))
}
// default options
const DEF_OPTIONS = {
// HTMLElement, waterfall items's outer container
container: null,
// container's width, container are hidden when initialized
// default get container offsetWidth when it's visible
containerWidth: 0,
// children item selector, eg. '.item-container'
itemSelector: '',
// item's spacing, unit px
gutter: 20,
// item's vertical spacing, default use gutter's value
verticalGutter: 0,
// item's width
itemWidth: 300,
// force item width
forceItemWidth: false,
// Horizontal align when forceItemWidth is true
align: 'center'
}
/**
* ZxWaterfall
*/
class ZxWaterfall {
/**
* constructor
* @param opts
*/
constructor (opts) {
opts = Object.assign({}, DEF_OPTIONS, opts)
// check container
if (!opts.container || opts.container.nodeType !== 1) {
throw new TypeError(`Instancing parameter 'container' is not HTMLElement.`)
}
// check itemSelector
if (!opts.itemSelector || typeof opts.itemSelector !== 'string') {
throw new TypeError(`Instancing parameter 'itemSelector' is null or is't a string.`)
}
// check verticalGutter
if (!opts.verticalGutter) {
opts.verticalGutter = opts.gutter
}
// item number
this.count = 0
this.opts = opts
this._init()
// clone this.reset
this._resetClone = this.reset.bind(this)
window.addEventListener('resize', this._resetClone)
}
/**
* initialization
* @private
*/
_init () {
let opts = this.opts
// container width
let containerWidth = int(opts.containerWidth) || opts.container.offsetWidth
// column number
let columnNum = Math.floor(containerWidth / (opts.itemWidth + opts.gutter))
// opts.itemWidth when opts.forceItemWidth = true
// else use compute new width
this.itemWidth = opts.forceItemWidth
? opts.itemWidth
: (containerWidth - (columnNum + 1) * opts.gutter) / columnNum
// column current height array
this.columns = Array(columnNum)
this.columns.fill(0, 0)
// offset left when forceItemWidth=true
this.offsetLeft = 0
if (opts.forceItemWidth) {
let residualSpaceWidth = containerWidth - (this.itemWidth + opts.gutter) * columnNum - opts.gutter
switch (opts.align) {
case 'center':
this.offsetLeft = residualSpaceWidth / 2
break
case 'right':
this.offsetLeft = residualSpaceWidth
break
}
}
}
/**
* set items position
* @private
*/
_setPosition () {
let opts = this.opts
// get new item elements
let $childs = slice(opts.container.querySelectorAll(opts.itemSelector), this.count)
// console.log(this.count, $childs)
let len = $childs.length
// reset this.count value
this.count += len
// handle new $item
let i, $item
for (i = 0; i < len; i++) {
$item = $childs[i]
if (!$item) continue
$item.style.position = 'absolute'
$item.style.width = this.itemWidth + 'px'
$item.style.display = 'inline-block'
// get columns min value
let min = Math.min.apply(null, this.columns)
let index = this.columns.findIndex(val => val === min)
// set $item position
$item.style.top = `${min + opts.verticalGutter}px`
$item.style.left = `${this.offsetLeft + (this.itemWidth + opts.gutter) * index + opts.gutter}px`
// reset waterfall current column height value
let itemHeight = $item.offsetHeight
this.columns[index] = min + itemHeight + opts.verticalGutter
// update container new min height style
// opts.container.style.minHeight = Math.max.apply(null, this.columns) + opts.verticalGutter + 'px'
}
}
/**
* container's items number change
*/
change () {
// reset postion, when new item element append to container, or remove
this._setPosition()
}
/**
* reset
*/
reset () {
this.count = 0
this._init()
this._setPosition()
}
/**
* preload media items
* @param arr media source urls array
* @returns {Promise<any>}
*/
loadMedia (arr) {
return new Promise(resolve => {
if (Array.isArray(arr) && arr.length) {
let len = arr.length
let count = 0
/* eslint-disable */
arr.forEach(url => {
loadImage(url, () => {
count++
if (len === count) resolve()
})
})
} else {
resolve()
}
})
}
/**
* destroy
* removeEventListener window resize
*/
destroy () {
window.removeEventListener('resize', this._resetClone)
}
}
export default ZxWaterfall
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java编程的逻辑
马俊昌 / 机械工业出版社 / 2018-1-1 / 99
Java专家撰写,力求透彻讲解每个知识点,逐步建立编程知识图谱。本书以Java语言为例,由基础概念入手,到背后实现原理与逻辑,再到应用实践,融会贯通。 全书共六大部分,其要点如下。 第一部分(第1~2章)讲解计算机程序的基本执行流程与元素,以及数据背后的二进制表示,帮读者掌握编程的基本概念。 第二部分(第3~7章)讲解面向对象的编程原理与逻辑,涉及类、继承与多态、接口与抽象类、异......一起来看看 《Java编程的逻辑》 这本书的介绍吧!