原生JavaScript 瀑布流 实现 zx-waterfall
栏目: JavaScript · 发布时间: 5年前
内容简介:源码地址: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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。