feat: 添加topology轮播类型
This commit is contained in:
@@ -1,837 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="item"
|
|
||||||
class="vue-grid-item"
|
|
||||||
:class="classObj"
|
|
||||||
:style="style"
|
|
||||||
>
|
|
||||||
<slot></slot>
|
|
||||||
<span v-if="resizableAndNotStatic" ref="handle" :class="resizableHandleClass"></span>
|
|
||||||
<!--<span v-if="draggable" ref="dragHandle" class="vue-draggable-handle"></span>-->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<style>
|
|
||||||
.vue-grid-item {
|
|
||||||
transition: all 200ms ease;
|
|
||||||
transition-property: left, top, right;
|
|
||||||
/* add right for rtl */
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-grid-item.no-touch {
|
|
||||||
-ms-touch-action: none;
|
|
||||||
touch-action: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-grid-item.cssTransforms {
|
|
||||||
transition-property: transform;
|
|
||||||
left: 0;
|
|
||||||
right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-grid-item.cssTransforms.render-rtl {
|
|
||||||
left: auto;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-grid-item.resizing {
|
|
||||||
opacity: 0.6;
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-grid-item.vue-draggable-dragging {
|
|
||||||
transition:none;
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-grid-item.vue-grid-placeholder {
|
|
||||||
background: red;
|
|
||||||
opacity: 0.2;
|
|
||||||
transition-duration: 100ms;
|
|
||||||
z-index: 2;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
-o-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-grid-item > .vue-resizable-handle {
|
|
||||||
position: absolute;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg08IS0tIEdlbmVyYXRvcjogQWRvYmUgRmlyZXdvcmtzIENTNiwgRXhwb3J0IFNWRyBFeHRlbnNpb24gYnkgQWFyb24gQmVhbGwgKGh0dHA6Ly9maXJld29ya3MuYWJlYWxsLmNvbSkgLiBWZXJzaW9uOiAwLjYuMSAgLS0+DTwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DTxzdmcgaWQ9IlVudGl0bGVkLVBhZ2UlMjAxIiB2aWV3Qm94PSIwIDAgNiA2IiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSINCXhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQl4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjZweCIgaGVpZ2h0PSI2cHgiDT4NCTxnIG9wYWNpdHk9IjAuMzAyIj4NCQk8cGF0aCBkPSJNIDYgNiBMIDAgNiBMIDAgNC4yIEwgNCA0LjIgTCA0LjIgNC4yIEwgNC4yIDAgTCA2IDAgTCA2IDYgTCA2IDYgWiIgZmlsbD0iIzAwMDAwMCIvPg0JPC9nPg08L3N2Zz4=');
|
|
||||||
background-position: bottom right;
|
|
||||||
padding: 0 3px 3px 0;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-origin: content-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
cursor: se-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-grid-item > .vue-rtl-resizable-handle {
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAuMDAwMDAwMDAwMDAwMDAyIiBoZWlnaHQ9IjEwLjAwMDAwMDAwMDAwMDAwMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KIDwhLS0gQ3JlYXRlZCB3aXRoIE1ldGhvZCBEcmF3IC0gaHR0cDovL2dpdGh1Yi5jb20vZHVvcGl4ZWwvTWV0aG9kLURyYXcvIC0tPgogPGc+CiAgPHRpdGxlPmJhY2tncm91bmQ8L3RpdGxlPgogIDxyZWN0IGZpbGw9Im5vbmUiIGlkPSJjYW52YXNfYmFja2dyb3VuZCIgaGVpZ2h0PSIxMiIgd2lkdGg9IjEyIiB5PSItMSIgeD0iLTEiLz4KICA8ZyBkaXNwbGF5PSJub25lIiBvdmVyZmxvdz0idmlzaWJsZSIgeT0iMCIgeD0iMCIgaGVpZ2h0PSIxMDAlIiB3aWR0aD0iMTAwJSIgaWQ9ImNhbnZhc0dyaWQiPgogICA8cmVjdCBmaWxsPSJ1cmwoI2dyaWRwYXR0ZXJuKSIgc3Ryb2tlLXdpZHRoPSIwIiB5PSIwIiB4PSIwIiBoZWlnaHQ9IjEwMCUiIHdpZHRoPSIxMDAlIi8+CiAgPC9nPgogPC9nPgogPGc+CiAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogIDxsaW5lIGNhbnZhcz0iI2ZmZmZmZiIgY2FudmFzLW9wYWNpdHk9IjEiIHN0cm9rZS1saW5lY2FwPSJ1bmRlZmluZWQiIHN0cm9rZS1saW5lam9pbj0idW5kZWZpbmVkIiBpZD0ic3ZnXzEiIHkyPSItNzAuMTc4NDA3IiB4Mj0iMTI0LjQ2NDE3NSIgeTE9Ii0zOC4zOTI3MzciIHgxPSIxNDQuODIxMjg5IiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlPSIjMDAwIiBmaWxsPSJub25lIi8+CiAgPGxpbmUgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2UtbGluZWNhcD0idW5kZWZpbmVkIiBzdHJva2UtbGluZWpvaW49InVuZGVmaW5lZCIgaWQ9InN2Z181IiB5Mj0iOS4xMDY5NTciIHgyPSIwLjk0NzI0NyIgeTE9Ii0wLjAxODEyOCIgeDE9IjAuOTQ3MjQ3IiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiLz4KICA8bGluZSBzdHJva2UtbGluZWNhcD0idW5kZWZpbmVkIiBzdHJva2UtbGluZWpvaW49InVuZGVmaW5lZCIgaWQ9InN2Z183IiB5Mj0iOSIgeDI9IjEwLjA3MzUyOSIgeTE9IjkiIHgxPSItMC42NTU2NCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM2NjY2NjYiIGZpbGw9Im5vbmUiLz4KIDwvZz4KPC9zdmc+);
|
|
||||||
background-position: bottom left;
|
|
||||||
padding-left: 3px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-origin: content-box;
|
|
||||||
cursor: sw-resize;
|
|
||||||
right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-grid-item.disable-userselect {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
import { setTopLeft, setTopRight, setTransformRtl, setTransform } from './gridItemUtils'
|
|
||||||
import { getControlPosition, createCoreData } from 'vue-grid-layout/src/helpers/draggableUtils'
|
|
||||||
import { getDocumentDir } from './gridItemDOM'
|
|
||||||
// var eventBus = require('./eventBus');
|
|
||||||
|
|
||||||
const interact = require('interactjs')
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'GridItem',
|
|
||||||
props: {
|
|
||||||
/* cols: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
}, */
|
|
||||||
/* containerWidth: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
|
|
||||||
},
|
|
||||||
rowHeight: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
margin: {
|
|
||||||
type: Array,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
maxRows: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
}, */
|
|
||||||
isDraggable: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
isResizable: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
/* useCssTransforms: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
static: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
minH: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
minW: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
maxH: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: Infinity
|
|
||||||
},
|
|
||||||
maxW: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: Infinity
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
w: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
h: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
i: {
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
dragIgnoreFrom: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: 'a, button'
|
|
||||||
},
|
|
||||||
dragAllowFrom: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
resizeIgnoreFrom: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: 'a, button'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
inject: ['eventBus'],
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
cols: 1,
|
|
||||||
containerWidth: 100,
|
|
||||||
rowHeight: 30,
|
|
||||||
margin: [10, 10],
|
|
||||||
maxRows: Infinity,
|
|
||||||
draggable: null,
|
|
||||||
resizable: null,
|
|
||||||
useCssTransforms: true,
|
|
||||||
|
|
||||||
isDragging: false,
|
|
||||||
dragging: null,
|
|
||||||
isResizing: false,
|
|
||||||
resizing: null,
|
|
||||||
lastX: NaN,
|
|
||||||
lastY: NaN,
|
|
||||||
lastW: NaN,
|
|
||||||
lastH: NaN,
|
|
||||||
style: {},
|
|
||||||
rtl: false,
|
|
||||||
|
|
||||||
dragEventSet: false,
|
|
||||||
resizeEventSet: false,
|
|
||||||
|
|
||||||
previousW: null,
|
|
||||||
previousH: null,
|
|
||||||
previousX: null,
|
|
||||||
previousY: null,
|
|
||||||
innerX: this.x,
|
|
||||||
innerY: this.y,
|
|
||||||
innerW: this.w,
|
|
||||||
innerH: this.h
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
const self = this
|
|
||||||
|
|
||||||
// Accessible refernces of functions for removing in beforeDestroy
|
|
||||||
self.updateWidthHandler = function (width) {
|
|
||||||
self.updateWidth(width)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.compactHandler = function (layout) {
|
|
||||||
self.compact(layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.setDraggableHandler = function (isDraggable) {
|
|
||||||
if (self.isDraggable === null) {
|
|
||||||
self.draggable = isDraggable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.setResizableHandler = function (isResizable) {
|
|
||||||
if (self.isResizable === null) {
|
|
||||||
self.resizable = isResizable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.setRowHeightHandler = function (rowHeight) {
|
|
||||||
self.rowHeight = rowHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
self.setMaxRowsHandler = function (maxRows) {
|
|
||||||
self.maxRows = maxRows
|
|
||||||
}
|
|
||||||
|
|
||||||
self.directionchangeHandler = () => {
|
|
||||||
this.rtl = getDocumentDir() === 'rtl'
|
|
||||||
this.compact()
|
|
||||||
}
|
|
||||||
|
|
||||||
self.setColNum = (colNum) => {
|
|
||||||
self.cols = parseInt(colNum)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.eventBus.$on('updateWidth', self.updateWidthHandler)
|
|
||||||
this.eventBus.$on('compact', self.compactHandler)
|
|
||||||
this.eventBus.$on('setDraggable', self.setDraggableHandler)
|
|
||||||
this.eventBus.$on('setResizable', self.setResizableHandler)
|
|
||||||
this.eventBus.$on('setRowHeight', self.setRowHeightHandler)
|
|
||||||
this.eventBus.$on('setMaxRows', self.setMaxRowsHandler)
|
|
||||||
this.eventBus.$on('directionchange', self.directionchangeHandler)
|
|
||||||
this.eventBus.$on('setColNum', self.setColNum)
|
|
||||||
|
|
||||||
this.rtl = getDocumentDir() === 'rtl'
|
|
||||||
},
|
|
||||||
beforeDestroy: function () {
|
|
||||||
const self = this
|
|
||||||
// Remove listeners
|
|
||||||
this.eventBus.$off('updateWidth', self.updateWidthHandler)
|
|
||||||
this.eventBus.$off('compact', self.compactHandler)
|
|
||||||
this.eventBus.$off('setDraggable', self.setDraggableHandler)
|
|
||||||
this.eventBus.$off('setResizable', self.setResizableHandler)
|
|
||||||
this.eventBus.$off('setRowHeight', self.setRowHeightHandler)
|
|
||||||
this.eventBus.$off('setMaxRows', self.setMaxRowsHandler)
|
|
||||||
this.eventBus.$off('directionchange', self.directionchangeHandler)
|
|
||||||
this.eventBus.$off('setColNum', self.setColNum)
|
|
||||||
this.interactObj.unset() // destroy interact intance
|
|
||||||
},
|
|
||||||
mounted: function () {
|
|
||||||
this.cols = this.$parent.colNum
|
|
||||||
this.rowHeight = this.$parent.rowHeight
|
|
||||||
this.containerWidth = this.$parent.width !== null ? this.$parent.width : 100
|
|
||||||
this.margin = this.$parent.margin !== undefined ? this.$parent.margin : [10, 10]
|
|
||||||
this.maxRows = this.$parent.maxRows
|
|
||||||
if (this.isDraggable === null) {
|
|
||||||
this.draggable = this.$parent.isDraggable
|
|
||||||
} else {
|
|
||||||
this.draggable = this.isDraggable
|
|
||||||
}
|
|
||||||
if (this.isResizable === null) {
|
|
||||||
this.resizable = this.$parent.isResizable
|
|
||||||
} else {
|
|
||||||
this.resizable = this.isResizable
|
|
||||||
}
|
|
||||||
this.useCssTransforms = this.$parent.useCssTransforms
|
|
||||||
this.createStyle()
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
isDraggable: function () {
|
|
||||||
this.draggable = this.isDraggable
|
|
||||||
},
|
|
||||||
static: function () {
|
|
||||||
this.tryMakeDraggable()
|
|
||||||
this.tryMakeResizable()
|
|
||||||
},
|
|
||||||
draggable: function () {
|
|
||||||
this.tryMakeDraggable()
|
|
||||||
},
|
|
||||||
isResizable: function () {
|
|
||||||
this.resizable = this.isResizable
|
|
||||||
},
|
|
||||||
resizable: function () {
|
|
||||||
this.tryMakeResizable()
|
|
||||||
},
|
|
||||||
rowHeight: function () {
|
|
||||||
this.createStyle()
|
|
||||||
this.emitContainerResized()
|
|
||||||
},
|
|
||||||
cols: function () {
|
|
||||||
this.tryMakeResizable()
|
|
||||||
this.createStyle()
|
|
||||||
this.emitContainerResized()
|
|
||||||
},
|
|
||||||
containerWidth: function () {
|
|
||||||
this.tryMakeResizable()
|
|
||||||
this.createStyle()
|
|
||||||
this.emitContainerResized()
|
|
||||||
},
|
|
||||||
x: function (newVal) {
|
|
||||||
this.innerX = newVal
|
|
||||||
this.createStyle()
|
|
||||||
},
|
|
||||||
y: function (newVal) {
|
|
||||||
console.log(newVal)
|
|
||||||
this.innerY = newVal
|
|
||||||
this.createStyle()
|
|
||||||
},
|
|
||||||
h: function (newVal) {
|
|
||||||
this.innerH = newVal
|
|
||||||
this.createStyle()
|
|
||||||
// this.emitContainerResized();
|
|
||||||
},
|
|
||||||
w: function (newVal) {
|
|
||||||
this.innerW = newVal
|
|
||||||
this.createStyle()
|
|
||||||
// this.emitContainerResized();
|
|
||||||
},
|
|
||||||
renderRtl: function () {
|
|
||||||
// console.log("### renderRtl");
|
|
||||||
this.tryMakeResizable()
|
|
||||||
this.createStyle()
|
|
||||||
},
|
|
||||||
minH: function () {
|
|
||||||
this.tryMakeResizable()
|
|
||||||
},
|
|
||||||
maxH: function () {
|
|
||||||
this.tryMakeResizable()
|
|
||||||
},
|
|
||||||
minW: function () {
|
|
||||||
this.tryMakeResizable()
|
|
||||||
},
|
|
||||||
maxW: function () {
|
|
||||||
this.tryMakeResizable()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
classObj () {
|
|
||||||
return {
|
|
||||||
'vue-resizable': this.resizableAndNotStatic,
|
|
||||||
static: this.static,
|
|
||||||
resizing: this.isResizing,
|
|
||||||
'vue-draggable-dragging': this.isDragging,
|
|
||||||
cssTransforms: this.useCssTransforms,
|
|
||||||
'render-rtl': this.renderRtl,
|
|
||||||
'disable-userselect': this.isDragging,
|
|
||||||
'no-touch': this.isAndroid && this.draggableOrResizableAndNotStatic
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resizableAndNotStatic () {
|
|
||||||
return this.resizable && !this.static
|
|
||||||
},
|
|
||||||
draggableOrResizableAndNotStatic () {
|
|
||||||
return (this.draggable || this.resizable) && !this.static
|
|
||||||
},
|
|
||||||
isAndroid () {
|
|
||||||
return navigator.userAgent.toLowerCase().indexOf('android') !== -1
|
|
||||||
},
|
|
||||||
renderRtl () {
|
|
||||||
return (this.$parent.isMirrored) ? !this.rtl : this.rtl
|
|
||||||
},
|
|
||||||
resizableHandleClass () {
|
|
||||||
if (this.renderRtl) {
|
|
||||||
return 'vue-resizable-handle vue-rtl-resizable-handle'
|
|
||||||
} else {
|
|
||||||
return 'vue-resizable-handle'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
createStyle: function () {
|
|
||||||
if (this.x + this.w > this.cols) {
|
|
||||||
this.innerX = 0
|
|
||||||
this.innerW = (this.w > this.cols) ? this.cols : this.w
|
|
||||||
} else {
|
|
||||||
this.innerX = this.x
|
|
||||||
this.innerW = this.w
|
|
||||||
}
|
|
||||||
const pos = this.calcPosition(this.innerX, this.innerY, this.innerW, this.innerH)
|
|
||||||
|
|
||||||
if (this.isDragging) {
|
|
||||||
pos.top = this.dragging.top
|
|
||||||
// Add rtl support
|
|
||||||
if (this.renderRtl) {
|
|
||||||
pos.right = this.dragging.left
|
|
||||||
} else {
|
|
||||||
pos.left = this.dragging.left
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.isResizing) {
|
|
||||||
pos.width = this.resizing.width
|
|
||||||
pos.height = this.resizing.height
|
|
||||||
}
|
|
||||||
|
|
||||||
let style
|
|
||||||
// CSS Transforms support (default)
|
|
||||||
if (this.useCssTransforms) {
|
|
||||||
// Add rtl support
|
|
||||||
if (this.renderRtl) {
|
|
||||||
style = setTransformRtl(pos.top, pos.right, pos.width, pos.height)
|
|
||||||
} else {
|
|
||||||
style = setTransform(pos.top, pos.left, pos.width, pos.height)
|
|
||||||
}
|
|
||||||
} else { // top,left (slow)
|
|
||||||
// Add rtl support
|
|
||||||
if (this.renderRtl) {
|
|
||||||
style = setTopRight(pos.top, pos.right, pos.width, pos.height)
|
|
||||||
} else {
|
|
||||||
style = setTopLeft(pos.top, pos.left, pos.width, pos.height)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.style = style
|
|
||||||
},
|
|
||||||
emitContainerResized () {
|
|
||||||
// this.style has width and height with trailing 'px'. The
|
|
||||||
// resized event is without them
|
|
||||||
const styleProps = {}
|
|
||||||
for (const prop of ['width', 'height']) {
|
|
||||||
const val = this.style[prop]
|
|
||||||
const matches = val.match(/^(\d+)px$/)
|
|
||||||
if (!matches) { return }
|
|
||||||
styleProps[prop] = matches[1]
|
|
||||||
}
|
|
||||||
this.$emit('container-resized', this.i, this.h, this.w, styleProps.height, styleProps.width)
|
|
||||||
},
|
|
||||||
handleResize: function (event) {
|
|
||||||
if (this.static) return
|
|
||||||
const position = getControlPosition(event)
|
|
||||||
// Get the current drag point from the event. This is used as the offset.
|
|
||||||
if (position == null) return // not possible but satisfies flow
|
|
||||||
const { x, y } = position
|
|
||||||
|
|
||||||
const newSize = { width: 0, height: 0 }
|
|
||||||
let pos
|
|
||||||
switch (event.type) {
|
|
||||||
case 'resizestart': {
|
|
||||||
this.previousW = this.innerW
|
|
||||||
this.previousH = this.innerH
|
|
||||||
pos = this.calcPosition(this.innerX, this.innerY, this.innerW, this.innerH)
|
|
||||||
newSize.width = pos.width
|
|
||||||
newSize.height = pos.height
|
|
||||||
this.resizing = newSize
|
|
||||||
this.isResizing = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'resizemove': {
|
|
||||||
// console.log("### resize => " + event.type + ", lastW=" + this.lastW + ", lastH=" + this.lastH);
|
|
||||||
const coreEvent = createCoreData(this.lastW, this.lastH, x, y)
|
|
||||||
if (this.renderRtl) {
|
|
||||||
newSize.width = this.resizing.width - coreEvent.deltaX
|
|
||||||
} else {
|
|
||||||
newSize.width = this.resizing.width + coreEvent.deltaX
|
|
||||||
}
|
|
||||||
newSize.height = this.resizing.height + coreEvent.deltaY
|
|
||||||
|
|
||||||
/// console.log("### resize => " + event.type + ", deltaX=" + coreEvent.deltaX + ", deltaY=" + coreEvent.deltaY);
|
|
||||||
this.resizing = newSize
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'resizeend': {
|
|
||||||
// console.log("### resize end => x=" +this.innerX + " y=" + this.innerY + " w=" + this.innerW + " h=" + this.innerH);
|
|
||||||
pos = this.calcPosition(this.innerX, this.innerY, this.innerW, this.innerH)
|
|
||||||
newSize.width = pos.width
|
|
||||||
newSize.height = pos.height
|
|
||||||
// console.log("### resize end => " + JSON.stringify(newSize));
|
|
||||||
this.resizing = null
|
|
||||||
this.isResizing = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get new WH
|
|
||||||
pos = this.calcWH(newSize.height, newSize.width)
|
|
||||||
if (pos.w < this.minW) {
|
|
||||||
pos.w = this.minW
|
|
||||||
}
|
|
||||||
if (pos.w > this.maxW) {
|
|
||||||
pos.w = this.maxW
|
|
||||||
}
|
|
||||||
if (pos.h < this.minH) {
|
|
||||||
pos.h = this.minH
|
|
||||||
}
|
|
||||||
if (pos.h > this.maxH) {
|
|
||||||
pos.h = this.maxH
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (pos.h < 1) {
|
|
||||||
// pos.h = 1;
|
|
||||||
// }
|
|
||||||
// if (pos.w < 1) {
|
|
||||||
// pos.w = 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.lastW = x
|
|
||||||
this.lastH = y
|
|
||||||
|
|
||||||
if (this.innerW !== pos.w || this.innerH !== pos.h) {
|
|
||||||
this.$emit('resize', this.i, pos.h, pos.w, newSize.height, newSize.width)
|
|
||||||
}
|
|
||||||
if (event.type === 'resizeend' && (this.previousW !== this.innerW || this.previousH !== this.innerH)) {
|
|
||||||
this.$emit('resized', this.i, pos.h, pos.w, newSize.height, newSize.width)
|
|
||||||
}
|
|
||||||
this.eventBus.$emit('resizeEvent', event.type, this.i, this.innerX, this.innerY, pos.h, pos.w)
|
|
||||||
},
|
|
||||||
handleDrag (event) {
|
|
||||||
if (this.static) return
|
|
||||||
if (this.isResizing) return
|
|
||||||
|
|
||||||
const position = getControlPosition(event)
|
|
||||||
|
|
||||||
// Get the current drag point from the event. This is used as the offset.
|
|
||||||
if (position === null) return // not possible but satisfies flow
|
|
||||||
const { x, y } = position
|
|
||||||
|
|
||||||
// let shouldUpdate = false;
|
|
||||||
const newPosition = { top: 0, left: 0 }
|
|
||||||
switch (event.type) {
|
|
||||||
case 'dragstart': {
|
|
||||||
this.previousX = this.innerX
|
|
||||||
this.previousY = this.innerY
|
|
||||||
|
|
||||||
const parentRect = event.target.offsetParent.getBoundingClientRect()
|
|
||||||
const clientRect = event.target.getBoundingClientRect()
|
|
||||||
if (this.renderRtl) {
|
|
||||||
newPosition.left = (clientRect.right - parentRect.right) * -1
|
|
||||||
} else {
|
|
||||||
newPosition.left = clientRect.left - parentRect.left
|
|
||||||
}
|
|
||||||
newPosition.top = clientRect.top - parentRect.top
|
|
||||||
this.dragging = newPosition
|
|
||||||
this.isDragging = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'dragend': {
|
|
||||||
if (!this.isDragging) return
|
|
||||||
const parentRect = event.target.offsetParent.getBoundingClientRect()
|
|
||||||
const clientRect = event.target.getBoundingClientRect()
|
|
||||||
// Add rtl support
|
|
||||||
if (this.renderRtl) {
|
|
||||||
newPosition.left = (clientRect.right - parentRect.right) * -1
|
|
||||||
} else {
|
|
||||||
newPosition.left = clientRect.left - parentRect.left
|
|
||||||
}
|
|
||||||
newPosition.top = clientRect.top - parentRect.top
|
|
||||||
// console.log("### drag end => " + JSON.stringify(newPosition));
|
|
||||||
// console.log("### DROP: " + JSON.stringify(newPosition));
|
|
||||||
this.dragging = null
|
|
||||||
this.isDragging = false
|
|
||||||
// shouldUpdate = true;
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'dragmove': {
|
|
||||||
const coreEvent = createCoreData(this.lastX, this.lastY, x, y)
|
|
||||||
// Add rtl support
|
|
||||||
if (this.renderRtl) {
|
|
||||||
newPosition.left = this.dragging.left - coreEvent.deltaX
|
|
||||||
} else {
|
|
||||||
newPosition.left = this.dragging.left + coreEvent.deltaX
|
|
||||||
}
|
|
||||||
newPosition.top = this.dragging.top + coreEvent.deltaY
|
|
||||||
// console.log("### drag => " + event.type + ", x=" + x + ", y=" + y);
|
|
||||||
// console.log("### drag => " + event.type + ", deltaX=" + coreEvent.deltaX + ", deltaY=" + coreEvent.deltaY);
|
|
||||||
// console.log("### drag end => " + JSON.stringify(newPosition));
|
|
||||||
this.dragging = newPosition
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get new XY
|
|
||||||
let pos
|
|
||||||
if (this.renderRtl) {
|
|
||||||
pos = this.calcXY(newPosition.top, newPosition.left)
|
|
||||||
} else {
|
|
||||||
pos = this.calcXY(newPosition.top, newPosition.left)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.lastX = x
|
|
||||||
this.lastY = y
|
|
||||||
|
|
||||||
if (this.innerX !== pos.x || this.innerY !== pos.y) {
|
|
||||||
this.$emit('move', this.i, pos.x, pos.y)
|
|
||||||
}
|
|
||||||
if (event.type === 'dragend' && (this.previousX !== this.innerX || this.previousY !== this.innerY)) {
|
|
||||||
this.$emit('moved', this.i, pos.x, pos.y)
|
|
||||||
}
|
|
||||||
this.eventBus.$emit('dragEvent', event.type, this.i, pos.x, pos.y, this.innerH, this.innerW)
|
|
||||||
},
|
|
||||||
calcPosition: function (x, y, w, h) {
|
|
||||||
const colWidth = this.calcColWidth()
|
|
||||||
// add rtl support
|
|
||||||
let out
|
|
||||||
if (this.renderRtl) {
|
|
||||||
out = {
|
|
||||||
right: Math.round(colWidth * x + (x + 1) * this.margin[0]),
|
|
||||||
top: Math.round(this.rowHeight * y + (y + 1) * this.margin[1]),
|
|
||||||
// 0 * Infinity === NaN, which causes problems with resize constriants;
|
|
||||||
// Fix this if it occurs.
|
|
||||||
// Note we do it here rather than later because Math.round(Infinity) causes deopt
|
|
||||||
width: w === Infinity ? w : Math.round(colWidth * w + Math.max(0, w - 1) * this.margin[0]),
|
|
||||||
height: h === Infinity ? h : Math.round(this.rowHeight * h + Math.max(0, h - 1) * this.margin[1])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
out = {
|
|
||||||
left: Math.round(colWidth * x + (x + 1) * this.margin[0]),
|
|
||||||
top: Math.round(this.rowHeight * y + (y + 1) * this.margin[1]),
|
|
||||||
// 0 * Infinity === NaN, which causes problems with resize constriants;
|
|
||||||
// Fix this if it occurs.
|
|
||||||
// Note we do it here rather than later because Math.round(Infinity) causes deopt
|
|
||||||
width: w === Infinity ? w : Math.round(colWidth * w + Math.max(0, w - 1) * this.margin[0]),
|
|
||||||
height: h === Infinity ? h : Math.round(this.rowHeight * h + Math.max(0, h - 1) * this.margin[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Translate x and y coordinates from pixels to grid units.
|
|
||||||
* @param {Number} top Top position (relative to parent) in pixels.
|
|
||||||
* @param {Number} left Left position (relative to parent) in pixels.
|
|
||||||
* @return {Object} x and y in grid units.
|
|
||||||
*/
|
|
||||||
// TODO check if this function needs change in order to support rtl.
|
|
||||||
calcXY (top, left) {
|
|
||||||
const colWidth = this.calcColWidth()
|
|
||||||
|
|
||||||
// left = colWidth * x + margin * (x + 1)
|
|
||||||
// l = cx + m(x+1)
|
|
||||||
// l = cx + mx + m
|
|
||||||
// l - m = cx + mx
|
|
||||||
// l - m = x(c + m)
|
|
||||||
// (l - m) / (c + m) = x
|
|
||||||
// x = (left - margin) / (coldWidth + margin)
|
|
||||||
let x = Math.round((left - this.margin[0]) / (colWidth + this.margin[0]))
|
|
||||||
let y = Math.round((top - this.margin[1]) / (this.rowHeight + this.margin[1]))
|
|
||||||
|
|
||||||
// Capping
|
|
||||||
x = Math.max(Math.min(x, this.cols - this.innerW), 0)
|
|
||||||
y = Math.max(Math.min(y, this.maxRows - this.innerH), 0)
|
|
||||||
|
|
||||||
return { x, y }
|
|
||||||
},
|
|
||||||
// Helper for generating column width
|
|
||||||
calcColWidth () {
|
|
||||||
const colWidth = (this.containerWidth - (this.margin[0] * (this.cols + 1))) / this.cols
|
|
||||||
// console.log("### COLS=" + this.cols + " COL WIDTH=" + colWidth + " MARGIN " + this.margin[0]);
|
|
||||||
return colWidth
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a height and width in pixel values, calculate grid units.
|
|
||||||
* @param {Number} height Height in pixels.
|
|
||||||
* @param {Number} width Width in pixels.
|
|
||||||
* @return {Object} w, h as grid units.
|
|
||||||
*/
|
|
||||||
calcWH (height, width) {
|
|
||||||
const colWidth = this.calcColWidth()
|
|
||||||
|
|
||||||
// width = colWidth * w - (margin * (w - 1))
|
|
||||||
// ...
|
|
||||||
// w = (width + margin) / (colWidth + margin)
|
|
||||||
let w = Math.round((width + this.margin[0]) / (colWidth + this.margin[0]))
|
|
||||||
let h = Math.round((height + this.margin[1]) / (this.rowHeight + this.margin[1]))
|
|
||||||
console.log(w, h, '1231213123')
|
|
||||||
// Capping
|
|
||||||
w = Math.max(Math.min(w, this.cols - this.innerX), 0)
|
|
||||||
h = Math.max(Math.min(h, this.maxRows - this.innerY), 0)
|
|
||||||
console.log(w, h, '1231213123')
|
|
||||||
return { w, h }
|
|
||||||
},
|
|
||||||
updateWidth: function (width, colNum) {
|
|
||||||
this.containerWidth = width
|
|
||||||
if (colNum !== undefined && colNum !== null) {
|
|
||||||
this.cols = colNum
|
|
||||||
}
|
|
||||||
},
|
|
||||||
compact: function () {
|
|
||||||
this.createStyle()
|
|
||||||
},
|
|
||||||
tryMakeDraggable: function () {
|
|
||||||
const self = this
|
|
||||||
if (this.interactObj === null || this.interactObj === undefined) {
|
|
||||||
this.interactObj = interact(this.$refs.item)
|
|
||||||
}
|
|
||||||
if (this.draggable && !this.static) {
|
|
||||||
const opts = {
|
|
||||||
ignoreFrom: this.dragIgnoreFrom,
|
|
||||||
allowFrom: this.dragAllowFrom
|
|
||||||
}
|
|
||||||
this.interactObj.draggable(opts)
|
|
||||||
/* this.interactObj.draggable({allowFrom: '.vue-draggable-handle'}); */
|
|
||||||
if (!this.dragEventSet) {
|
|
||||||
this.dragEventSet = true
|
|
||||||
this.interactObj.on('dragstart dragmove dragend', function (event) {
|
|
||||||
self.handleDrag(event)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.interactObj.draggable({
|
|
||||||
enabled: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tryMakeResizable: function () {
|
|
||||||
const self = this
|
|
||||||
if (this.interactObj === null || this.interactObj === undefined) {
|
|
||||||
this.interactObj = interact(this.$refs.item)
|
|
||||||
}
|
|
||||||
if (this.resizable && !this.static) {
|
|
||||||
const maximum = this.calcPosition(0, 0, this.maxW, this.maxH)
|
|
||||||
const minimum = this.calcPosition(0, 0, this.minW, this.minH)
|
|
||||||
|
|
||||||
// console.log("### MAX " + JSON.stringify(maximum));
|
|
||||||
// console.log("### MIN " + JSON.stringify(minimum));
|
|
||||||
|
|
||||||
const opts = {
|
|
||||||
preserveAspectRatio: true,
|
|
||||||
// allowFrom: "." + this.resizableHandleClass,
|
|
||||||
edges: {
|
|
||||||
left: false,
|
|
||||||
right: '.' + this.resizableHandleClass,
|
|
||||||
bottom: '.' + this.resizableHandleClass,
|
|
||||||
top: false
|
|
||||||
},
|
|
||||||
ignoreFrom: this.resizeIgnoreFrom,
|
|
||||||
restrictSize: {
|
|
||||||
min: {
|
|
||||||
height: minimum.height,
|
|
||||||
width: minimum.width
|
|
||||||
},
|
|
||||||
max: {
|
|
||||||
height: maximum.height,
|
|
||||||
width: maximum.width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.interactObj.resizable(opts)
|
|
||||||
if (!this.resizeEventSet) {
|
|
||||||
this.resizeEventSet = true
|
|
||||||
this.interactObj
|
|
||||||
.on('resizestart resizemove resizeend', function (event) {
|
|
||||||
self.handleResize(event)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.interactObj.resizable({
|
|
||||||
enabled: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
autoSize: function () {
|
|
||||||
// ok here we want to calculate if a resize is needed
|
|
||||||
this.previousW = this.innerW
|
|
||||||
this.previousH = this.innerH
|
|
||||||
|
|
||||||
const newSize = this.$slots.default[0].elm.getBoundingClientRect()
|
|
||||||
const pos = this.calcWH(newSize.height, newSize.width)
|
|
||||||
if (pos.w < this.minW) {
|
|
||||||
pos.w = this.minW
|
|
||||||
}
|
|
||||||
if (pos.w > this.maxW) {
|
|
||||||
pos.w = this.maxW
|
|
||||||
}
|
|
||||||
if (pos.h < this.minH) {
|
|
||||||
pos.h = this.minH
|
|
||||||
}
|
|
||||||
if (pos.h > this.maxH) {
|
|
||||||
pos.h = this.maxH
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (pos.h < 1) {
|
|
||||||
// pos.h = 1;
|
|
||||||
// }
|
|
||||||
// if (pos.w < 1) {
|
|
||||||
// pos.w = 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this.lastW = x; // basically, this is copied from resizehandler, but shouldn't be needed
|
|
||||||
// this.lastH = y;
|
|
||||||
|
|
||||||
if (this.innerW !== pos.w || this.innerH !== pos.h) {
|
|
||||||
this.$emit('resize', this.i, pos.h, pos.w, newSize.height, newSize.width)
|
|
||||||
}
|
|
||||||
if (this.previousW !== pos.w || this.previousH !== pos.h) {
|
|
||||||
this.$emit('resized', this.i, pos.h, pos.w, newSize.height, newSize.width)
|
|
||||||
this.eventBus.$emit('resizeEvent', 'resizeend', this.i, this.innerX, this.innerY, pos.h, pos.w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,439 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="item" class="vue-grid-layout" :style="mergedStyle">
|
|
||||||
<slot></slot>
|
|
||||||
<grid-item class="vue-grid-placeholder"
|
|
||||||
v-show="isDragging"
|
|
||||||
:x="placeholder.x"
|
|
||||||
:y="placeholder.y"
|
|
||||||
:w="placeholder.w"
|
|
||||||
:h="placeholder.h"
|
|
||||||
:i="placeholder.i"></grid-item>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<style>
|
|
||||||
.vue-grid-layout {
|
|
||||||
position: relative;
|
|
||||||
transition: height 200ms ease;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
import Vue from 'vue'
|
|
||||||
|
|
||||||
import { bottom, compact, getLayoutItem, moveElement, validateLayout, cloneLayout, getAllCollisions } from './gridItemUtils'
|
|
||||||
import { getBreakpointFromWidth, getColsFromBreakpoint, findOrGenerateResponsiveLayout } from './responsiveUtils'
|
|
||||||
// var eventBus = require('./eventBus');
|
|
||||||
|
|
||||||
import GridItem from './GridItem.vue'
|
|
||||||
import { addWindowEventListener, removeWindowEventListener } from './gridItemDOM'
|
|
||||||
const elementResizeDetectorMaker = require('element-resize-detector')
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'GridLayout',
|
|
||||||
provide () {
|
|
||||||
return {
|
|
||||||
eventBus: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
GridItem
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
// If true, the container height swells and contracts to fit contents
|
|
||||||
autoSize: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
colNum: {
|
|
||||||
type: Number,
|
|
||||||
default: 12
|
|
||||||
},
|
|
||||||
rowHeight: {
|
|
||||||
type: Number,
|
|
||||||
default: 150
|
|
||||||
},
|
|
||||||
maxRows: {
|
|
||||||
type: Number,
|
|
||||||
default: Infinity
|
|
||||||
},
|
|
||||||
margin: {
|
|
||||||
type: Array,
|
|
||||||
default: function () {
|
|
||||||
return [10, 10]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isDraggable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
isResizable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
isMirrored: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
useCssTransforms: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
verticalCompact: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
type: Array,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
responsive: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
breakpoints: {
|
|
||||||
type: Object,
|
|
||||||
default: function () { return { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 } }
|
|
||||||
},
|
|
||||||
cols: {
|
|
||||||
type: Object,
|
|
||||||
default: function () { return { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 } }
|
|
||||||
},
|
|
||||||
preventCollision: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
width: null,
|
|
||||||
mergedStyle: {},
|
|
||||||
lastLayoutLength: 0,
|
|
||||||
isDragging: false,
|
|
||||||
placeholder: {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
w: 0,
|
|
||||||
h: 0,
|
|
||||||
i: -1
|
|
||||||
},
|
|
||||||
layouts: {}, // array to store all layouts from different breakpoints
|
|
||||||
lastBreakpoint: null, // store last active breakpoint
|
|
||||||
originalLayout: null // store original Layout
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
const self = this
|
|
||||||
|
|
||||||
// Accessible refernces of functions for removing in beforeDestroy
|
|
||||||
self.resizeEventHandler = function (eventType, i, x, y, h, w) {
|
|
||||||
self.resizeEvent(eventType, i, x, y, h, w)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.dragEventHandler = function (eventType, i, x, y, h, w) {
|
|
||||||
console.log(eventType, i, x, y, h, w,'dragFlag')
|
|
||||||
self.dragEvent(eventType, i, x, y, h, w)
|
|
||||||
}
|
|
||||||
|
|
||||||
self._provided.eventBus = new Vue()
|
|
||||||
self.eventBus = self._provided.eventBus
|
|
||||||
self.eventBus.$on('resizeEvent', self.resizeEventHandler)
|
|
||||||
self.eventBus.$on('dragEvent', self.dragEventHandler)
|
|
||||||
self.$emit('layout-created', self.layout)
|
|
||||||
},
|
|
||||||
beforeDestroy: function () {
|
|
||||||
// Remove listeners
|
|
||||||
this.eventBus.$off('resizeEvent', this.resizeEventHandler)
|
|
||||||
this.eventBus.$off('dragEvent', this.dragEventHandler)
|
|
||||||
this.eventBus.$destroy()
|
|
||||||
removeWindowEventListener('resize', this.onWindowResize)
|
|
||||||
this.erd.uninstall(this.$refs.item)
|
|
||||||
},
|
|
||||||
beforeMount: function () {
|
|
||||||
this.$emit('layout-before-mount', this.layout)
|
|
||||||
},
|
|
||||||
mounted: function () {
|
|
||||||
this.$emit('layout-mounted', this.layout)
|
|
||||||
this.$nextTick(function () {
|
|
||||||
validateLayout(this.layout)
|
|
||||||
|
|
||||||
this.originalLayout = this.layout
|
|
||||||
const self = this
|
|
||||||
this.$nextTick(function () {
|
|
||||||
self.onWindowResize()
|
|
||||||
|
|
||||||
self.initResponsiveFeatures()
|
|
||||||
|
|
||||||
// self.width = self.$el.offsetWidth;
|
|
||||||
addWindowEventListener('resize', self.onWindowResize)
|
|
||||||
|
|
||||||
compact(self.layout, self.verticalCompact)
|
|
||||||
|
|
||||||
self.updateHeight()
|
|
||||||
self.$nextTick(function () {
|
|
||||||
this.erd = elementResizeDetectorMaker({
|
|
||||||
strategy: 'scroll', // <- For ultra performance.
|
|
||||||
// See https://github.com/wnr/element-resize-detector/issues/110 about callOnAdd.
|
|
||||||
callOnAdd: false
|
|
||||||
})
|
|
||||||
this.erd.listenTo(self.$refs.item, function () {
|
|
||||||
self.onWindowResize()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
width: function (newval, oldval) {
|
|
||||||
const self = this
|
|
||||||
this.$nextTick(function () {
|
|
||||||
// this.$broadcast("updateWidth", this.width);
|
|
||||||
this.eventBus.$emit('updateWidth', this.width)
|
|
||||||
if (oldval === null) {
|
|
||||||
/*
|
|
||||||
If oldval == null is when the width has never been
|
|
||||||
set before. That only occurs when mouting is
|
|
||||||
finished, and onWindowResize has been called and
|
|
||||||
this.width has been changed the first time after it
|
|
||||||
got set to null in the constructor. It is now time
|
|
||||||
to issue layout-ready events as the GridItems have
|
|
||||||
their sizes configured properly.
|
|
||||||
|
|
||||||
The reason for emitting the layout-ready events on
|
|
||||||
the next tick is to allow for the newly-emitted
|
|
||||||
updateWidth event (above) to have reached the
|
|
||||||
children GridItem-s and had their effect, so we're
|
|
||||||
sure that they have the final size before we emit
|
|
||||||
layout-ready (for this GridLayout) and
|
|
||||||
item-layout-ready (for the GridItem-s).
|
|
||||||
|
|
||||||
This way any client event handlers can reliably
|
|
||||||
invistigate stable sizes of GridItem-s.
|
|
||||||
*/
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$emit('layout-ready', self.layout)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.updateHeight()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
layout: function () {
|
|
||||||
this.layoutUpdate()
|
|
||||||
},
|
|
||||||
colNum: function (val) {
|
|
||||||
this.eventBus.$emit('setColNum', val)
|
|
||||||
},
|
|
||||||
rowHeight: function () {
|
|
||||||
this.eventBus.$emit('setRowHeight', this.rowHeight)
|
|
||||||
},
|
|
||||||
isDraggable: function () {
|
|
||||||
this.eventBus.$emit('setDraggable', this.isDraggable)
|
|
||||||
},
|
|
||||||
isResizable: function () {
|
|
||||||
this.eventBus.$emit('setResizable', this.isResizable)
|
|
||||||
},
|
|
||||||
responsive () {
|
|
||||||
if (!this.responsive) {
|
|
||||||
this.$emit('update:layout', this.originalLayout)
|
|
||||||
this.eventBus.$emit('setColNum', this.colNum)
|
|
||||||
}
|
|
||||||
this.onWindowResize()
|
|
||||||
},
|
|
||||||
maxRows: function () {
|
|
||||||
this.eventBus.$emit('setMaxRows', this.maxRows)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
layoutUpdate () {
|
|
||||||
if (this.layout !== undefined && this.originalLayout !== null) {
|
|
||||||
if (this.layout.length !== this.originalLayout.length) {
|
|
||||||
// console.log("### LAYOUT UPDATE!", this.layout.length, this.originalLayout.length);
|
|
||||||
|
|
||||||
const diff = this.findDifference(this.layout, this.originalLayout)
|
|
||||||
if (diff.length > 0) {
|
|
||||||
// console.log(diff);
|
|
||||||
if (this.layout.length > this.originalLayout.length) {
|
|
||||||
this.originalLayout = this.originalLayout.concat(diff)
|
|
||||||
} else {
|
|
||||||
this.originalLayout = this.originalLayout.filter(obj => {
|
|
||||||
return !diff.some(obj2 => {
|
|
||||||
return obj.i === obj2.i
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.lastLayoutLength = this.layout.length
|
|
||||||
this.initResponsiveFeatures()
|
|
||||||
}
|
|
||||||
|
|
||||||
compact(this.layout, this.verticalCompact)
|
|
||||||
this.eventBus.$emit('updateWidth', this.width)
|
|
||||||
this.updateHeight()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateHeight: function () {
|
|
||||||
this.mergedStyle = {
|
|
||||||
height: this.containerHeight()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onWindowResize: function () {
|
|
||||||
if (this.$refs !== null && this.$refs.item !== null && this.$refs.item !== undefined) {
|
|
||||||
this.width = this.$refs.item.offsetWidth
|
|
||||||
}
|
|
||||||
this.eventBus.$emit('resizeEvent')
|
|
||||||
},
|
|
||||||
containerHeight: function () {
|
|
||||||
if (!this.autoSize) return
|
|
||||||
return bottom(this.layout) * (this.rowHeight + this.margin[1]) + this.margin[1] + 'px'
|
|
||||||
},
|
|
||||||
dragEvent: function (eventName, id, x, y, h, w) {
|
|
||||||
// console.log(eventName + " id=" + id + ", x=" + x + ", y=" + y);
|
|
||||||
let l = getLayoutItem(this.layout, id)
|
|
||||||
// GetLayoutItem sometimes returns null object
|
|
||||||
if (l === undefined || l === null) {
|
|
||||||
l = { x: 0, y: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventName === 'dragmove' || eventName === 'dragstart') {
|
|
||||||
this.placeholder.i = id
|
|
||||||
this.placeholder.x = l.x
|
|
||||||
this.placeholder.y = l.y
|
|
||||||
console.log(l.y)
|
|
||||||
this.placeholder.w = w
|
|
||||||
this.placeholder.h = h
|
|
||||||
this.$nextTick(function () {
|
|
||||||
this.isDragging = true
|
|
||||||
})
|
|
||||||
// this.$broadcast("updateWidth", this.width);
|
|
||||||
this.eventBus.$emit('updateWidth', this.width)
|
|
||||||
} else {
|
|
||||||
this.$nextTick(function () {
|
|
||||||
this.isDragging = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the element to the dragged location.
|
|
||||||
this.layout = moveElement(this.layout, l, x, y, true, this.preventCollision)
|
|
||||||
compact(this.layout, this.verticalCompact)
|
|
||||||
// needed because vue can't detect changes on array element properties
|
|
||||||
this.eventBus.$emit('compact')
|
|
||||||
this.updateHeight()
|
|
||||||
if (eventName === 'dragend') this.$emit('layout-updated', this.layout)
|
|
||||||
},
|
|
||||||
resizeEvent: function (eventName, id, x, y, h, w) {
|
|
||||||
let l = getLayoutItem(this.layout, id)
|
|
||||||
// GetLayoutItem sometimes return null object
|
|
||||||
if (l === undefined || l === null) {
|
|
||||||
l = { h: 0, w: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
let hasCollisions
|
|
||||||
if (this.preventCollision) {
|
|
||||||
const collisions = getAllCollisions(this.layout, { ...l, w, h }).filter(
|
|
||||||
layoutItem => layoutItem.i !== l.i
|
|
||||||
)
|
|
||||||
hasCollisions = collisions.length > 0
|
|
||||||
|
|
||||||
// If we're colliding, we need adjust the placeholder.
|
|
||||||
if (hasCollisions) {
|
|
||||||
// adjust w && h to maximum allowed space
|
|
||||||
let leastX = Infinity
|
|
||||||
let leastY = Infinity
|
|
||||||
collisions.forEach(layoutItem => {
|
|
||||||
if (layoutItem.x > l.x) leastX = Math.min(leastX, layoutItem.x)
|
|
||||||
if (layoutItem.y > l.y) leastY = Math.min(leastY, layoutItem.y)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (Number.isFinite(leastX)) l.w = leastX - l.x
|
|
||||||
if (Number.isFinite(leastY)) l.h = leastY - l.y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasCollisions) {
|
|
||||||
// Set new width and height.
|
|
||||||
l.w = w
|
|
||||||
l.h = h
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventName === 'resizestart' || eventName === 'resizemove') {
|
|
||||||
this.placeholder.i = id
|
|
||||||
this.placeholder.x = x
|
|
||||||
this.placeholder.y = y
|
|
||||||
this.placeholder.w = l.w
|
|
||||||
this.placeholder.h = l.h
|
|
||||||
this.$nextTick(function () {
|
|
||||||
this.isDragging = true
|
|
||||||
})
|
|
||||||
// this.$broadcast("updateWidth", this.width);
|
|
||||||
this.eventBus.$emit('updateWidth', this.width)
|
|
||||||
} else {
|
|
||||||
this.$nextTick(function () {
|
|
||||||
this.isDragging = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.responsive) this.responsiveGridLayout()
|
|
||||||
|
|
||||||
compact(this.layout, this.verticalCompact)
|
|
||||||
this.eventBus.$emit('compact')
|
|
||||||
this.updateHeight()
|
|
||||||
|
|
||||||
if (eventName === 'resizeend') this.$emit('layout-updated', this.layout)
|
|
||||||
},
|
|
||||||
|
|
||||||
// finds or generates new layouts for set breakpoints
|
|
||||||
responsiveGridLayout () {
|
|
||||||
const newBreakpoint = getBreakpointFromWidth(this.breakpoints, this.width)
|
|
||||||
const newCols = getColsFromBreakpoint(newBreakpoint, this.cols)
|
|
||||||
|
|
||||||
// save actual layout in layouts
|
|
||||||
if (this.lastBreakpoint != null && !this.layouts[this.lastBreakpoint]) { this.layouts[this.lastBreakpoint] = cloneLayout(this.layout) }
|
|
||||||
|
|
||||||
// Find or generate a new layout.
|
|
||||||
const layout = findOrGenerateResponsiveLayout(
|
|
||||||
this.originalLayout,
|
|
||||||
this.layouts,
|
|
||||||
this.breakpoints,
|
|
||||||
newBreakpoint,
|
|
||||||
this.lastBreakpoint,
|
|
||||||
newCols,
|
|
||||||
this.verticalCompact
|
|
||||||
)
|
|
||||||
|
|
||||||
// Store the new layout.
|
|
||||||
this.layouts[newBreakpoint] = layout
|
|
||||||
|
|
||||||
// new prop sync
|
|
||||||
this.$emit('update:layout', layout)
|
|
||||||
|
|
||||||
this.lastBreakpoint = newBreakpoint
|
|
||||||
this.eventBus.$emit('setColNum', getColsFromBreakpoint(newBreakpoint, this.cols))
|
|
||||||
},
|
|
||||||
|
|
||||||
// clear all responsive layouts
|
|
||||||
initResponsiveFeatures () {
|
|
||||||
// clear layouts
|
|
||||||
this.layouts = {}
|
|
||||||
},
|
|
||||||
|
|
||||||
// find difference in layouts
|
|
||||||
findDifference (layout, originalLayout) {
|
|
||||||
// Find values that are in result1 but not in result2
|
|
||||||
const uniqueResultOne = layout.filter(function (obj) {
|
|
||||||
return !originalLayout.some(function (obj2) {
|
|
||||||
return obj.i === obj2.i
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Find values that are in result2 but not in result1
|
|
||||||
const uniqueResultTwo = originalLayout.filter(function (obj) {
|
|
||||||
return !layout.some(function (obj2) {
|
|
||||||
return obj.i === obj2.i
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Combine the two arrays of unique entries#
|
|
||||||
return uniqueResultOne.concat(uniqueResultTwo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -83,6 +83,14 @@
|
|||||||
:is-fullscreen="isFullscreen"
|
:is-fullscreen="isFullscreen"
|
||||||
:chart-option="chartOption"
|
:chart-option="chartOption"
|
||||||
></chart-diagram>
|
></chart-diagram>
|
||||||
|
<chartAutoCarousel
|
||||||
|
:ref="'chart' + chartInfo.id"
|
||||||
|
v-if="isAutoCarousel(chartInfo.type)"
|
||||||
|
:chart-data="chartData"
|
||||||
|
:chart-info="chartInfo"
|
||||||
|
:chart-option="chartOption"
|
||||||
|
:is-fullscreen="isFullscreen"
|
||||||
|
></chartAutoCarousel>
|
||||||
<chart-group
|
<chart-group
|
||||||
:ref="'chart' + chartInfo.id"
|
:ref="'chart' + chartInfo.id"
|
||||||
v-if="isGroup(chartInfo.type)"
|
v-if="isGroup(chartInfo.type)"
|
||||||
@@ -92,14 +100,6 @@
|
|||||||
:is-fullscreen="isFullscreen"
|
:is-fullscreen="isFullscreen"
|
||||||
:chart-option="chartOption"
|
:chart-option="chartOption"
|
||||||
></chart-group>
|
></chart-group>
|
||||||
<chartAutoCarousel
|
|
||||||
:ref="'chart' + chartInfo.id"
|
|
||||||
v-if="isAutoCarousel(chartInfo.type)"
|
|
||||||
:chart-data="chartData"
|
|
||||||
:chart-info="chartInfo"
|
|
||||||
:chart-option="chartOption"
|
|
||||||
:is-fullscreen="isFullscreen"
|
|
||||||
></chartAutoCarousel>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,10 +1,101 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div v-loading="topologyLoading" class="overview">
|
||||||
|
<transition name = "el-zoom-in-center">
|
||||||
|
<div v-if="allProject&&allProject.length>0" style="width: 100%;height: 100%;position: relative">
|
||||||
|
<el-carousel :interval="5000" :trigger="'click'" arrow="hover">
|
||||||
|
<el-carousel-item v-for="(item,index) in allProject" :key="index">
|
||||||
|
<div class="maskLayer" @click="toProject(item)"></div>
|
||||||
|
<span class="project-name">{{item.name}}</span>
|
||||||
|
<topology
|
||||||
|
:fromOverView="true"
|
||||||
|
:obj="item"
|
||||||
|
:ref="'topology' + index"
|
||||||
|
:topologyIndexF="index"
|
||||||
|
/>
|
||||||
|
</el-carousel-item>
|
||||||
|
</el-carousel>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
<div v-if="allProject.length===0" class="chart-no-data">No Data</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import axios from 'axios'
|
||||||
|
import topology from '@/components/common/project/topologyL5'
|
||||||
|
import chartMixin from '@/components/chart/chartMixin'
|
||||||
|
import bus from '@/libs/bus'
|
||||||
export default {
|
export default {
|
||||||
name: 'chartAutoCarousel'
|
name: 'chartAutoCarousel',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
topologyLoading: false,
|
||||||
|
allProject: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mixins: [chartMixin],
|
||||||
|
components: {
|
||||||
|
topology
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
queryAllProjectData () {
|
||||||
|
this.$get('monitor/project', { pageSize: -1 }).then(res => {
|
||||||
|
this.topologyLoading = true
|
||||||
|
const axiosAll = []
|
||||||
|
const temp = []
|
||||||
|
if (res.data.list.length === 0) {
|
||||||
|
this.topologyLoading = false
|
||||||
|
}
|
||||||
|
res.data.list.forEach((item) => {
|
||||||
|
axiosAll.push(axios.get(`monitor/project/topo?projectId=${item.id}`))
|
||||||
|
})
|
||||||
|
axios.all(axiosAll).then(res2 => {
|
||||||
|
res2 = res2.map((item, index) => {
|
||||||
|
return { ...item.data.data, ...res.data.list[index] }
|
||||||
|
})
|
||||||
|
res2 = res2.filter((item) => item.topo && item.topo.pens && item.topo.pens.length)
|
||||||
|
if (res2.length == 0) {
|
||||||
|
this.topologyLoading = false
|
||||||
|
}
|
||||||
|
res2.forEach(item => {
|
||||||
|
temp.push(item)
|
||||||
|
})
|
||||||
|
this.allProject = temp
|
||||||
|
this.topologyLoading = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toProject (projectInfo) { // 跳转对应project页面
|
||||||
|
this.$store.commit('currentProjectChange', projectInfo)
|
||||||
|
this.jumpTo('project')
|
||||||
|
},
|
||||||
|
jumpTo (data, id) {
|
||||||
|
if (data == 'asset') {
|
||||||
|
bus.$emit('clear-asset-filter') // 清除leftMenu左侧菜单过滤条件
|
||||||
|
// if(this.$store.getters.getIdcArr.length===0){return}//如果不存在idc 则不跳转
|
||||||
|
}
|
||||||
|
if (data === 'project' || data === 'module' || data === 'endpoint') {
|
||||||
|
data = 'monitor/' + data
|
||||||
|
}
|
||||||
|
if (data === 'alertList') {
|
||||||
|
data = 'alertMessage'
|
||||||
|
}
|
||||||
|
this.$router.push({
|
||||||
|
path: '/' + data,
|
||||||
|
query: {
|
||||||
|
t: +new Date()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
resize () {
|
||||||
|
this.allProject.forEach((item, index) => {
|
||||||
|
this.$refs['topology' + index][0] && this.$refs['topology' + index][0].winResize()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.queryAllProjectData()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const chartTreemapOption = {
|
|||||||
visibleMin: 40,
|
visibleMin: 40,
|
||||||
childrenVisibleMin: 40,
|
childrenVisibleMin: 40,
|
||||||
nodeClick: false,
|
nodeClick: false,
|
||||||
|
roam: false,
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
position: 'inside',
|
position: 'inside',
|
||||||
|
|||||||
@@ -80,8 +80,6 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import VueGridLayout from 'vue-grid-layout'
|
import VueGridLayout from 'vue-grid-layout'
|
||||||
import gridItem from './GridItem'
|
|
||||||
// import GridLayout from './GridLayout'
|
|
||||||
import { fromRoute } from '@/components/common/js/constants'
|
import { fromRoute } from '@/components/common/js/constants'
|
||||||
import { getGroupHeight } from './chart/tools'
|
import { getGroupHeight } from './chart/tools'
|
||||||
import panelChart from '@/components/chart/panelChart'
|
import panelChart from '@/components/chart/panelChart'
|
||||||
@@ -103,7 +101,7 @@ export default {
|
|||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
GridLayout: VueGridLayout.GridLayout,
|
GridLayout: VueGridLayout.GridLayout,
|
||||||
GridItem: gridItem,
|
GridItem: VueGridLayout.GridItem,
|
||||||
panelChart
|
panelChart
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -203,7 +201,7 @@ export default {
|
|||||||
// console.log(this.$refs.layout)
|
// console.log(this.$refs.layout)
|
||||||
const groupFind = this.copyDataList.find(item => item.id == group.id)
|
const groupFind = this.copyDataList.find(item => item.id == group.id)
|
||||||
console.log(groupFind)
|
console.log(groupFind)
|
||||||
if (group) {
|
if (group && groupFind) {
|
||||||
groupFind.height = groupFind.h = height + this.headerHPadding
|
groupFind.height = groupFind.h = height + this.headerHPadding
|
||||||
groupFind.children = copyList
|
groupFind.children = copyList
|
||||||
this.copyDataList = [...this.copyDataList]
|
this.copyDataList = [...this.copyDataList]
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
const currentDir = 'auto'
|
|
||||||
function hasDocument () {
|
|
||||||
return (typeof document !== 'undefined')
|
|
||||||
}
|
|
||||||
function hasWindow () {
|
|
||||||
return (typeof window !== 'undefined')
|
|
||||||
}
|
|
||||||
export function getDocumentDir () {
|
|
||||||
if (!hasDocument()) {
|
|
||||||
return currentDir
|
|
||||||
}
|
|
||||||
const direction = (typeof document.dir !== 'undefined')
|
|
||||||
? document.dir
|
|
||||||
: document.getElementsByTagName('html')[0].getAttribute('dir')
|
|
||||||
return direction
|
|
||||||
}
|
|
||||||
export function addWindowEventListener (event, callback) {
|
|
||||||
if (!hasWindow) {
|
|
||||||
callback()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
window.addEventListener(event, callback)
|
|
||||||
}
|
|
||||||
export function removeWindowEventListener (event, callback) {
|
|
||||||
if (!hasWindow) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
window.removeEventListener(event, callback)
|
|
||||||
}
|
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
export function setTopLeft (top, left, width, height) {
|
|
||||||
return {
|
|
||||||
top: top + 'px',
|
|
||||||
left: left + 'px',
|
|
||||||
width: width + 'px',
|
|
||||||
height: height + 'px',
|
|
||||||
position: 'absolute'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function setTopRight (top, right, width, height) {
|
|
||||||
return {
|
|
||||||
top: top + 'px',
|
|
||||||
right: right + 'px',
|
|
||||||
width: width + 'px',
|
|
||||||
height: height + 'px',
|
|
||||||
position: 'absolute'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function setTransformRtl (top, right, width, height) {
|
|
||||||
// Replace unitless items with px
|
|
||||||
const translate = 'translate3d(' + right * -1 + 'px,' + top + 'px, 0)'
|
|
||||||
return {
|
|
||||||
transform: translate,
|
|
||||||
WebkitTransform: translate,
|
|
||||||
MozTransform: translate,
|
|
||||||
msTransform: translate,
|
|
||||||
OTransform: translate,
|
|
||||||
width: width + 'px',
|
|
||||||
height: height + 'px',
|
|
||||||
position: 'absolute'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function setTransform (top, left, width, height) {
|
|
||||||
// Replace unitless items with px
|
|
||||||
const translate = 'translate3d(' + left + 'px,' + top + 'px, 0)'
|
|
||||||
return {
|
|
||||||
transform: translate,
|
|
||||||
WebkitTransform: translate,
|
|
||||||
MozTransform: translate,
|
|
||||||
msTransform: translate,
|
|
||||||
OTransform: translate,
|
|
||||||
width: width + 'px',
|
|
||||||
height: height + 'px',
|
|
||||||
position: 'absolute'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function bottom (layout) {
|
|
||||||
let max = 0; let bottomY
|
|
||||||
for (let i = 0, len = layout.length; i < len; i++) {
|
|
||||||
bottomY = layout[i].y + layout[i].h
|
|
||||||
if (bottomY > max) max = bottomY
|
|
||||||
}
|
|
||||||
return max
|
|
||||||
}
|
|
||||||
export function compact (layout, verticalCompact) {
|
|
||||||
// Statics go in the compareWith array right away so items flow around them.
|
|
||||||
const compareWith = getStatics(layout)
|
|
||||||
// We go through the items by row and column.
|
|
||||||
const sorted = sortLayoutItemsByRowCol(layout)
|
|
||||||
// Holding for new items.
|
|
||||||
const out = Array(layout.length)
|
|
||||||
|
|
||||||
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
||||||
let l = sorted[i]
|
|
||||||
|
|
||||||
// Don't move static elements
|
|
||||||
if (!l.static) {
|
|
||||||
l = compactItem(compareWith, l, verticalCompact)
|
|
||||||
|
|
||||||
// Add to comparison array. We only collide with items before this one.
|
|
||||||
// Statics are already in this array.
|
|
||||||
compareWith.push(l)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to output array to make sure they still come out in the right order.
|
|
||||||
out[layout.indexOf(l)] = l
|
|
||||||
|
|
||||||
// Clear moved flag, if it exists.
|
|
||||||
l.moved = false
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
export function getLayoutItem (layout, id) {
|
|
||||||
for (let i = 0, len = layout.length; i < len; i++) {
|
|
||||||
if (layout[i].i === id) return layout[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function moveElement (layout, l, x, y, isUserAction, preventCollision) {
|
|
||||||
if (l.static) return layout
|
|
||||||
|
|
||||||
// Short-circuit if nothing to do.
|
|
||||||
// if (l.y === y && l.x === x) return layout;
|
|
||||||
|
|
||||||
const oldX = l.x
|
|
||||||
const oldY = l.y
|
|
||||||
|
|
||||||
const movingUp = y && l.y > y
|
|
||||||
// This is quite a bit faster than extending the object
|
|
||||||
if (typeof x === 'number') l.x = x
|
|
||||||
if (typeof y === 'number') l.y = y
|
|
||||||
l.moved = true
|
|
||||||
|
|
||||||
// If this collides with anything, move it.
|
|
||||||
// When doing this comparison, we have to sort the items we compare with
|
|
||||||
// to ensure, in the case of multiple collisions, that we're getting the
|
|
||||||
// nearest collision.
|
|
||||||
let sorted = sortLayoutItemsByRowCol(layout)
|
|
||||||
if (movingUp) sorted = sorted.reverse()
|
|
||||||
const collisions = getAllCollisions(sorted, l)
|
|
||||||
|
|
||||||
if (preventCollision && collisions.length) {
|
|
||||||
l.x = oldX
|
|
||||||
l.y = oldY
|
|
||||||
l.moved = false
|
|
||||||
return layout
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move each item that collides away from this element.
|
|
||||||
for (let i = 0, len = collisions.length; i < len; i++) {
|
|
||||||
const collision = collisions[i]
|
|
||||||
// console.log('resolving collision between', l.i, 'at', l.y, 'and', collision.i, 'at', collision.y);
|
|
||||||
|
|
||||||
// Short circuit so we can't infinite loop
|
|
||||||
if (collision.moved) continue
|
|
||||||
|
|
||||||
// This makes it feel a bit more precise by waiting to swap for just a bit when moving up.
|
|
||||||
if (l.y > collision.y && l.y - collision.y > collision.h / 4) continue
|
|
||||||
|
|
||||||
// Don't move static items - we have to move *this* element away
|
|
||||||
if (collision.static) {
|
|
||||||
layout = moveElementAwayFromCollision(layout, collision, l, isUserAction)
|
|
||||||
} else {
|
|
||||||
layout = moveElementAwayFromCollision(layout, l, collision, isUserAction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return layout
|
|
||||||
}
|
|
||||||
export function validateLayout (layout, contextName) {
|
|
||||||
contextName = contextName || 'Layout'
|
|
||||||
const subProps = ['x', 'y', 'w', 'h']
|
|
||||||
if (!Array.isArray(layout)) throw new Error(contextName + ' must be an array!')
|
|
||||||
for (let i = 0, len = layout.length; i < len; i++) {
|
|
||||||
const item = layout[i]
|
|
||||||
for (let j = 0; j < subProps.length; j++) {
|
|
||||||
if (typeof item[subProps[j]] !== 'number') {
|
|
||||||
throw new Error('VueGridLayout: ' + contextName + '[' + i + '].' + subProps[j] + ' must be a number!')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (item.i && typeof item.i !== 'string') {
|
|
||||||
// number is also ok, so comment the error
|
|
||||||
// TODO confirm if commenting the line below doesn't cause unexpected problems
|
|
||||||
// throw new Error('VueGridLayout: ' + contextName + '[' + i + '].i must be a string!');
|
|
||||||
}
|
|
||||||
if (item.static !== undefined && typeof item.static !== 'boolean') {
|
|
||||||
throw new Error('VueGridLayout: ' + contextName + '[' + i + '].static must be a boolean!')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function cloneLayout (layout) {
|
|
||||||
const newLayout = Array(layout.length)
|
|
||||||
for (let i = 0, len = layout.length; i < len; i++) {
|
|
||||||
newLayout[i] = cloneLayoutItem(layout[i])
|
|
||||||
}
|
|
||||||
return newLayout
|
|
||||||
}
|
|
||||||
export function getAllCollisions (layout, layoutItem) {
|
|
||||||
return layout.filter((l) => collides(l, layoutItem))
|
|
||||||
}
|
|
||||||
export function cloneLayoutItem (layoutItem) {
|
|
||||||
/* return {
|
|
||||||
w: layoutItem.w, h: layoutItem.h, x: layoutItem.x, y: layoutItem.y, i: layoutItem.i,
|
|
||||||
minW: layoutItem.minW, maxW: layoutItem.maxW, minH: layoutItem.minH, maxH: layoutItem.maxH,
|
|
||||||
moved: Boolean(layoutItem.moved), static: Boolean(layoutItem.static),
|
|
||||||
// These can be null
|
|
||||||
isDraggable: layoutItem.isDraggable, isResizable: layoutItem.isResizable
|
|
||||||
}; */
|
|
||||||
return JSON.parse(JSON.stringify(layoutItem))
|
|
||||||
}
|
|
||||||
export function collides (l1, l2) {
|
|
||||||
if (l1 === l2) return false // same element
|
|
||||||
if (l1.x + l1.w <= l2.x) return false // l1 is left of l2
|
|
||||||
if (l1.x >= l2.x + l2.w) return false // l1 is right of l2
|
|
||||||
if (l1.y + l1.h <= l2.y) return false // l1 is above l2
|
|
||||||
if (l1.y >= l2.y + l2.h) return false // l1 is below l2
|
|
||||||
return true // boxes overlap
|
|
||||||
}
|
|
||||||
export function compactItem (compareWith, l, verticalCompact) {
|
|
||||||
if (verticalCompact) {
|
|
||||||
// Move the element up as far as it can go without colliding.
|
|
||||||
while (l.y > 0 && !getFirstCollision(compareWith, l)) {
|
|
||||||
l.y--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move it down, and keep moving it down if it's colliding.
|
|
||||||
let collides
|
|
||||||
while ((collides = getFirstCollision(compareWith, l))) {
|
|
||||||
l.y = collides.y + collides.h
|
|
||||||
}
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
export function getFirstCollision (layout, layoutItem) {
|
|
||||||
for (let i = 0, len = layout.length; i < len; i++) {
|
|
||||||
if (collides(layout[i], layoutItem)) return layout[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function getStatics (layout) {
|
|
||||||
// return [];
|
|
||||||
return layout.filter((l) => l.static)
|
|
||||||
}
|
|
||||||
export function moveElementAwayFromCollision (layout, collidesWith, itemToMove, isUserAction) {
|
|
||||||
const preventCollision = false // we're already colliding
|
|
||||||
// If there is enough space above the collision to put this element, move it there.
|
|
||||||
// We only do this on the main collision as this can get funky in cascades and cause
|
|
||||||
// unwanted swapping behavior.
|
|
||||||
if (isUserAction) {
|
|
||||||
// Make a mock item so we don't modify the item here, only modify in moveElement.
|
|
||||||
const fakeItem = {
|
|
||||||
x: itemToMove.x,
|
|
||||||
y: itemToMove.y,
|
|
||||||
w: itemToMove.w,
|
|
||||||
h: itemToMove.h,
|
|
||||||
i: '-1'
|
|
||||||
}
|
|
||||||
fakeItem.y = Math.max(collidesWith.y - itemToMove.h, 0)
|
|
||||||
if (!getFirstCollision(layout, fakeItem)) {
|
|
||||||
return moveElement(layout, itemToMove, undefined, fakeItem.y, preventCollision)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Previously this was optimized to move below the collision directly, but this can cause problems
|
|
||||||
// with cascading moves, as an item may actually leapflog a collision and cause a reversal in order.
|
|
||||||
return moveElement(layout, itemToMove, undefined, itemToMove.y + 1, preventCollision)
|
|
||||||
}
|
|
||||||
export function sortLayoutItemsByRowCol (layout) {
|
|
||||||
return [].concat(layout).sort(function (a, b) {
|
|
||||||
if (a.y > b.y || (a.y === b.y && a.x > b.x)) {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function correctBounds (layout, bounds) {
|
|
||||||
const collidesWith = getStatics(layout)
|
|
||||||
for (let i = 0, len = layout.length; i < len; i++) {
|
|
||||||
const l = layout[i]
|
|
||||||
// Overflows right
|
|
||||||
if (l.x + l.w > bounds.cols) l.x = bounds.cols - l.w
|
|
||||||
// Overflows left
|
|
||||||
if (l.x < 0) {
|
|
||||||
l.x = 0
|
|
||||||
l.w = bounds.cols
|
|
||||||
}
|
|
||||||
if (!l.static) collidesWith.push(l)
|
|
||||||
else {
|
|
||||||
// If this is static and collides with other statics, we must move it down.
|
|
||||||
// We have to do something nicer than just letting them overlap.
|
|
||||||
while (getFirstCollision(collidesWith, l)) {
|
|
||||||
l.y++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return layout
|
|
||||||
}
|
|
||||||
@@ -153,12 +153,19 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (this.chartInfo.type === 'diagram') {
|
if (this.chartInfo.type === 'diagram') {
|
||||||
this.chartData = [this.chartInfo.param.topo]
|
if (!this.chartInfo.param.topo || !this.chartInfo.param.topo.pens.length){
|
||||||
|
this.chartData = []
|
||||||
|
} else {
|
||||||
|
this.chartData = [this.chartInfo.param.topo]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.chartInfo.type === 'group') {
|
if (this.chartInfo.type === 'group') {
|
||||||
this.groupInit()
|
this.groupInit()
|
||||||
this.chartData = [...this.chartInfo.children]
|
this.chartData = [...this.chartInfo.children]
|
||||||
}
|
}
|
||||||
|
if (this.chartInfo.type === 'carousel') {
|
||||||
|
this.chartData = ['carousel']
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
import { compact, cloneLayout, correctBounds } from './gridItemUtils'
|
|
||||||
export function getBreakpointFromWidth (breakpoints, width) {
|
|
||||||
const sorted = sortBreakpoints(breakpoints)
|
|
||||||
let matching = sorted[0]
|
|
||||||
for (let i = 1, len = sorted.length; i < len; i++) {
|
|
||||||
const breakpointName = sorted[i]
|
|
||||||
if (width > breakpoints[breakpointName]) matching = breakpointName
|
|
||||||
}
|
|
||||||
return matching
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a breakpoint, get the # of cols set for it.
|
|
||||||
* @param {String} breakpoint Breakpoint name.
|
|
||||||
* @param {Object} cols Map of breakpoints to cols.
|
|
||||||
* @return {Number} Number of cols.
|
|
||||||
*/
|
|
||||||
export function getColsFromBreakpoint (breakpoint, cols) {
|
|
||||||
if (!cols[breakpoint]) {
|
|
||||||
throw new Error('ResponsiveGridLayout: `cols` entry for breakpoint ' + breakpoint + ' is missing!')
|
|
||||||
}
|
|
||||||
return cols[breakpoint]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given existing layouts and a new breakpoint, find or generate a new layout.
|
|
||||||
*
|
|
||||||
* This finds the layout above the new one and generates from it, if it exists.
|
|
||||||
*
|
|
||||||
* @param {Array} orgLayout Original layout.
|
|
||||||
* @param {Object} layouts Existing layouts.
|
|
||||||
* @param {Array} breakpoints All breakpoints.
|
|
||||||
* @param {String} breakpoint New breakpoint.
|
|
||||||
* @param {String} breakpoint Last breakpoint (for fallback).
|
|
||||||
* @param {Number} cols Column count at new breakpoint.
|
|
||||||
* @param {Boolean} verticalCompact Whether or not to compact the layout
|
|
||||||
* vertically.
|
|
||||||
* @return {Array} New layout.
|
|
||||||
*/
|
|
||||||
export function findOrGenerateResponsiveLayout (orgLayout, layouts, breakpoints, breakpoint, lastBreakpoint, cols, verticalCompact) {
|
|
||||||
// If it already exists, just return it.
|
|
||||||
if (layouts[breakpoint]) return cloneLayout(layouts[breakpoint])
|
|
||||||
// Find or generate the next layout
|
|
||||||
let layout = orgLayout
|
|
||||||
|
|
||||||
const breakpointsSorted = sortBreakpoints(breakpoints)
|
|
||||||
const breakpointsAbove = breakpointsSorted.slice(breakpointsSorted.indexOf(breakpoint))
|
|
||||||
for (let i = 0, len = breakpointsAbove.length; i < len; i++) {
|
|
||||||
const b = breakpointsAbove[i]
|
|
||||||
if (layouts[b]) {
|
|
||||||
layout = layouts[b]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
layout = cloneLayout(layout || []) // clone layout so we don't modify existing items
|
|
||||||
return compact(correctBounds(layout, { cols: cols }), verticalCompact)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateResponsiveLayout (layout, breakpoints, breakpoint, lastBreakpoint, cols, verticalCompact) {
|
|
||||||
// If it already exists, just return it.
|
|
||||||
/* if (layouts[breakpoint]) return cloneLayout(layouts[breakpoint]);
|
|
||||||
// Find or generate the next layout
|
|
||||||
let layout = layouts[lastBreakpoint]; */
|
|
||||||
/* const breakpointsSorted = sortBreakpoints(breakpoints);
|
|
||||||
const breakpointsAbove = breakpointsSorted.slice(breakpointsSorted.indexOf(breakpoint));
|
|
||||||
for (let i = 0, len = breakpointsAbove.length; i < len; i++) {
|
|
||||||
const b = breakpointsAbove[i];
|
|
||||||
if (layouts[b]) {
|
|
||||||
layout = layouts[b];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
layout = cloneLayout(layout || []) // clone layout so we don't modify existing items
|
|
||||||
return compact(correctBounds(layout, { cols: cols }), verticalCompact)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given breakpoints, return an array of breakpoints sorted by width. This is usually
|
|
||||||
* e.g. ['xxs', 'xs', 'sm', ...]
|
|
||||||
*
|
|
||||||
* @param {Object} breakpoints Key/value pair of breakpoint names to widths.
|
|
||||||
* @return {Array} Sorted breakpoints.
|
|
||||||
*/
|
|
||||||
export function sortBreakpoints (breakpoints) {
|
|
||||||
const keys = Object.keys(breakpoints)
|
|
||||||
return keys.sort(function (a, b) {
|
|
||||||
return breakpoints[a] - breakpoints[b]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -518,7 +518,6 @@ export default {
|
|||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
topologyIndexF: {
|
topologyIndexF: {
|
||||||
type: Number,
|
|
||||||
default: 0
|
default: 0
|
||||||
},
|
},
|
||||||
obj: {},
|
obj: {},
|
||||||
@@ -2129,6 +2128,7 @@ export default {
|
|||||||
flag = true
|
flag = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
getTopology(this.topologyIndex).resize()
|
||||||
getTopology(this.topologyIndex).centerView()
|
getTopology(this.topologyIndex).centerView()
|
||||||
this.getNodesArr()
|
this.getNodesArr()
|
||||||
}, 500)
|
}, 500)
|
||||||
|
|||||||
Reference in New Issue
Block a user