aboutsummaryrefslogtreecommitdiff
path: root/src/site/components/grid/waterfall/Waterfall.vue
diff options
context:
space:
mode:
authorPitu <[email protected]>2018-09-16 01:09:02 -0300
committerPitu <[email protected]>2018-09-16 01:09:02 -0300
commitfe10a00ba9a3c30d8718ca004ccd19518466f5bd (patch)
tree369752f59a88dd03df1e9752be0ba166bf93c933 /src/site/components/grid/waterfall/Waterfall.vue
parentFirst version of start script (diff)
downloadhost.fuwn.me-fe10a00ba9a3c30d8718ca004ccd19518466f5bd.tar.xz
host.fuwn.me-fe10a00ba9a3c30d8718ca004ccd19518466f5bd.zip
Site
Diffstat (limited to 'src/site/components/grid/waterfall/Waterfall.vue')
-rw-r--r--src/site/components/grid/waterfall/Waterfall.vue181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/site/components/grid/waterfall/Waterfall.vue b/src/site/components/grid/waterfall/Waterfall.vue
new file mode 100644
index 0000000..9827075
--- /dev/null
+++ b/src/site/components/grid/waterfall/Waterfall.vue
@@ -0,0 +1,181 @@
+<style>
+ .waterfall {
+ position: relative;
+ }
+</style>
+<template>
+ <div class="waterfall">
+ <slot/>
+ </div>
+</template>
+<script>
+// import {quickSort, getMinIndex, _, sum} from './util'
+
+const quickSort = (arr, type) => {
+ let left = [];
+ let right = [];
+ let povis;
+ if (arr.length <= 1) {
+ return arr;
+ }
+ povis = arr[0];
+ for (let i = 1; i < arr.length; i++) {
+ if (arr[i][type] < povis[type]) {
+ left.push(arr[i]);
+ } else {
+ right.push(arr[i]);
+ }
+ }
+ return quickSort(left, type).concat(povis, quickSort(right, type))
+};
+
+const getMinIndex = arr => {
+ let pos = 0;
+ for (let i = 0; i < arr.length; i++) {
+ if (arr[pos] > arr[i]) {
+ pos = i;
+ }
+ }
+ return pos;
+};
+
+const _ = {
+ on(el, type, func, capture = false) {
+ el.addEventListener(type, func, capture);
+ },
+ off(el, type, func, capture = false) {
+ el.removeEventListener(type, func, capture);
+ }
+};
+
+const sum = arr => arr.reduce((sum, val) => sum + val);
+export default {
+ name: 'Waterfall',
+ props: {
+ gutterWidth: {
+ type: Number,
+ default: 0
+ },
+ gutterHeight: {
+ type: Number,
+ default: 0
+ },
+ resizable: {
+ type: Boolean,
+ default: true
+ },
+ align: {
+ type: String,
+ default: 'center'
+ },
+ fixWidth: {
+ type: Number
+ },
+ minCol: {
+ type: Number,
+ default: 1
+ },
+ maxCol: {
+ type: Number
+ },
+ percent: {
+ type: Array
+ }
+ },
+ data() {
+ return {
+ timer: null,
+ colNum: 0,
+ lastWidth: 0,
+ percentWidthArr: []
+ };
+ },
+ created() {
+ this.$on('itemRender', () => {
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+ this.timer = setTimeout(() => {
+ this.render();
+ }, 0);
+ });
+ },
+ mounted() {
+ this.resizeHandle();
+ this.$watch('resizable', this.resizeHandle);
+ },
+ methods: {
+ calulate(arr) {
+ let pageWidth = this.fixWidth ? this.fixWidth : this.$el.offsetWidth;
+ // 百分比布局计算
+ if (this.percent) {
+ this.colNum = this.percent.length;
+ const total = sum(this.percent);
+ this.percentWidthArr = this.percent.map(value => (value / total) * pageWidth);
+ this.lastWidth = 0;
+ // 正常布局计算
+ } else {
+ this.colNum = parseInt(pageWidth / (arr.width + this.gutterWidth));
+ if (this.minCol && this.colNum < this.minCol) {
+ this.colNum = this.minCol;
+ this.lastWidth = 0;
+ } else if (this.maxCol && this.colNum > this.maxCol) {
+ this.colNum = this.maxCol;
+ this.lastWidth = pageWidth - (arr.width + this.gutterWidth) * this.colNum + this.gutterWidth;
+ } else {
+ this.lastWidth = pageWidth - (arr.width + this.gutterWidth) * this.colNum + this.gutterWidth;
+ }
+ }
+ },
+ resizeHandle() {
+ if (this.resizable) {
+ _.on(window, 'resize', this.render, false);
+ } else {
+ _.off(window, 'resize', this.render, false);
+ }
+ },
+ render() {
+ // 重新排序
+ let childArr = [];
+ childArr = this.$children.map(child => child.getMeta());
+ childArr = quickSort(childArr, 'order');
+ // 计算列数
+ this.calulate(childArr[0])
+ let offsetArr = Array(this.colNum).fill(0);
+ // 渲染
+ childArr.forEach(child => {
+ let position = getMinIndex(offsetArr);
+ // 百分比布局渲染
+ if (this.percent) {
+ let left = 0;
+ child.el.style.width = `${this.percentWidthArr[position]}px`;
+ if (position === 0) {
+ left = 0;
+ } else {
+ for (let i = 0; i < position; i++) {
+ left += this.percentWidthArr[i];
+ }
+ }
+ child.el.style.left = `${left}px`;
+ // 正常布局渲染
+ } else {
+ if (this.align === 'left') { // eslint-disable-line no-lonely-if
+ child.el.style.left = `${position * (child.width + this.gutterWidth)}px`;
+ } else if (this.align === 'right') {
+ child.el.style.left = `${position * (child.width + this.gutterWidth) + this.lastWidth}px`;
+ } else {
+ child.el.style.left = `${position * (child.width + this.gutterWidth) + this.lastWidth / 2}px`;
+ }
+ }
+ if (child.height === 0) {
+ return;
+ }
+ child.el.style.top = `${offsetArr[position]}px`;
+ offsetArr[position] += (child.height + this.gutterHeight);
+ this.$el.style.height = `${Math.max.apply(Math, offsetArr)}px`;
+ });
+ this.$emit('rendered', this);
+ }
+ }
+};
+</script>