【sgDragSize】自定义拖拽修改DIV尺寸组件,适用于窗体大小调整

核心原理就是在四条边、四个顶点加上透明的div,给不同方向提供按下移动鼠标监听 ,对应计算宽度高度、坐标变化 

特性:

  1. 支持设置拖拽的最小宽度、最小高度、最大宽度、最大高度
  2. 可以双击某一条边,最大化对应方向的尺寸;再一次双击,则会恢复到原始大小

sgDragSize源码

<template>
    <div :class="$options.name" :disabled="disabled" draggable="false">
        <div :class="`resize-handle resize-${a}`" draggable="false" @mousedown.stop="clickResizeHandle(a)"
            @dblclick="dblclickResizeHandle(a, $event)" v-for="(a, i) in sizeIndexs" :key="i"></div>
    </div>
</template>
<script>
export default {
    name: 'sgDragSize',
    data() {
        return {
            tbHeight: 0,
            dragSizeIndex: '',
            originRect: {},
            dblclickOriginRect: {},
            sizeIndexs: [
                'top',
                'right',
                'bottom',
                'left',
                'top-left',
                'top-right',
                'bottom-left',
                'bottom-right',
            ],
        }
    },
    props: [
        "disabled",//屏蔽
        "taskbarHeight",//任务栏高度
        "minWidth",//拖拽的最小宽度
        "minHeight",//拖拽的最小高度
        "maxWidth",//拖拽的最大宽度
        "maxHeight",//拖拽的最大高度
    ],
    watch: {
        disabled: {
            handler(newValue, oldValue) {
                newValue && this.__removeWindowEvents();
            }, deep: true, immediate: true,
        },
        taskbarHeight: {
            handler(d) {
                this.tbHeight = d || 0;
            }, deep: true, immediate: true,
        },
    },
    destroyed() {
        this.__removeWindowEvents();
    },
    methods: {
        view_innerHeight() {
            return innerHeight - this.tbHeight;
        },
        clickResizeHandle(d) {
            this.dragSizeIndex = d;
            this.mousedown(d);
        },
        dblclickResizeHandle(d, $event) {
            let rect = this.$el.getBoundingClientRect();
            rect.width < innerWidth && rect.height < this.view_innerHeight() && (this.dblclickOriginRect = rect);
            this.dblResize(d, rect, $event);
        },
        __addWindowEvents() {
            this.__removeWindowEvents();
            addEventListener('mousemove', this.mousemove_window);
            addEventListener('mouseup', this.mouseup_window);
        },
        __removeWindowEvents() {
            removeEventListener('mousemove', this.mousemove_window);
            removeEventListener('mouseup', this.mouseup_window);
        },
        mousedown(e) {
            this.originRect = this.$el.getBoundingClientRect();
            this.originRect.bottomRightX = this.originRect.x + this.originRect.width;//右下角坐标.x
            this.originRect.bottomRightY = this.originRect.y + this.originRect.height;//右下角坐标.y
            this.$emit('dragStart', e);
            this.__addWindowEvents();
        },
        mousemove_window(e) {
            let { x, y } = e;
            let minWidth = this.minWidth || 50, minHeight = this.minHeight || 50, maxWidth = this.maxWidth || innerWidth, maxHeight = this.maxHeight || innerHeight;
            x < 0 && (x = 0), y < 0 && (y = 0), x > innerWidth && (x = innerWidth), y > this.view_innerHeight() && (y = this.view_innerHeight());
            let style = {};
            switch (this.dragSizeIndex) {
                case 'top-left':
                    style.left = x;
                    style.top = y;
                    style.width = this.originRect.bottomRightX - x;
                    style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.bottomRightX - minWidth);
                    style.height = this.originRect.bottomRightY - y;
                    style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.bottomRightY - minHeight);
                    break;
                case 'top':
                    style.left = this.originRect.x;
                    style.top = y;
                    style.width = this.originRect.width;
                    style.height = this.originRect.bottomRightY - y;
                    style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.bottomRightY - minHeight);
                    break;
                case 'top-right':
                    style.left = this.originRect.x;
                    style.top = y;
                    style.width = x - this.originRect.x;
                    style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.x);
                    style.height = this.originRect.bottomRightY - y;
                    style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.bottomRightY - minHeight);
                    break;
                case 'left':
                    style.left = x;
                    style.top = this.originRect.y;
                    style.width = this.originRect.bottomRightX - x;
                    style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.bottomRightX - minWidth);
                    style.height = this.originRect.height;
                    break;
                case 'right':
                    style.left = this.originRect.x;
                    style.top = this.originRect.y;
                    style.width = x - this.originRect.x;
                    style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.x);
                    style.height = this.originRect.height;
                    break;
                case 'bottom-left':
                    style.left = x;
                    style.top = this.originRect.y;
                    style.width = this.originRect.bottomRightX - x;
                    style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.bottomRightX - minWidth);
                    style.height = y - this.originRect.y;
                    style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.y);
                    break;
                case 'bottom':
                    style.left = this.originRect.x;
                    style.top = this.originRect.y;
                    style.width = this.originRect.width;
                    style.height = y - this.originRect.y;
                    style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.y);
                    break;
                case 'bottom-right':
                    style.left = this.originRect.x;
                    style.top = this.originRect.y;
                    style.width = x - this.originRect.x;
                    style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.x);
                    style.height = y - this.originRect.y;
                    style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.y);
                    break;
                default:
            }
            style.width > maxWidth && (style.width = maxWidth);
            style.height > maxHeight && (style.height = maxHeight);
            Object.keys(style).forEach(k => style[k] = `${style[k]}px`);
            style['transition-property'] = 'width,height';
            style['transition-duration'] = '0,0';
            this.$emit('dragging', { e, style });
        },
        dblResize(d, rect, e) {
            let style = {};
            switch (d) {
                case 'top-left':
                    break;
                case 'top':
                case 'bottom':
                    style.left = this.originRect.x;
                    style.top = rect.height >= this.view_innerHeight() ? this.dblclickOriginRect.y : 0;
                    style.width = this.originRect.width;
                    style.height = rect.height >= this.view_innerHeight() ? this.dblclickOriginRect.height : this.view_innerHeight();
                    break;
                case 'top-right':
                    break;
                case 'left':
                case 'right':
                    style.left = rect.width >= innerWidth ? this.dblclickOriginRect.x : 0;
                    style.top = this.originRect.y;
                    style.width = rect.width >= innerWidth ? this.dblclickOriginRect.width : innerWidth;
                    style.height = this.originRect.height;
                    break;
                case 'bottom-left':
                    break;
                case 'bottom-right':
                    break;
                default:
            }
            Object.keys(style).forEach(k => style[k] = `${style[k]}px`);
            style['transition-property'] = 'width,height';
            style['transition-duration'] = '0.1s,0.1s';
            this.$emit('dragging', { e, style });
        },
        mouseup_window(e) {
            this.$emit('dragEnd', e);
            this.__removeWindowEvents();
        },
    }
};
</script> 
<style lang="scss">
.sgDragSize {
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    pointer-events: none;

    .resize-handle {
        position: absolute;
        z-index: 100;
        display: block;
        pointer-events: auto;
    }

    &[disabled] {
        .resize-handle {
            pointer-events: none;
        }
    }

    .resize-top {
        cursor: n-resize;
        top: -3px;
        left: 0px;
        height: 7px;
        width: 100%;
    }

    .resize-right {
        cursor: e-resize;
        right: -3px;
        top: 0px;
        width: 7px;
        height: 100%;
    }

    .resize-bottom {
        cursor: s-resize;
        bottom: -3px;
        left: 0px;
        height: 7px;
        width: 100%;
    }

    .resize-left {
        cursor: w-resize;
        left: -3px;
        top: 0px;
        width: 7px;
        height: 100%;
    }

    .resize-top-right {
        cursor: ne-resize;
        width: 16px;
        height: 16px;
        right: -8px;
        top: -8px;
    }

    .resize-bottom-right {
        cursor: se-resize;
        width: 20px;
        height: 20px;
        right: -8px;
        bottom: -8px;
        background: url('/static/img/desktop/Windows7/sgDragSize/resize_corner.png') no-repeat;
    }

    .resize-bottom-left {
        cursor: sw-resize;
        width: 16px;
        height: 16px;
        left: -8px;
        bottom: -8px;
    }

    .resize-top-left {
        cursor: nw-resize;
        width: 16px;
        height: 16px;
        left: -8px;
        top: -8px;
    }
}
</style>

应用

<template>
    <div>
        <div class="box" :style="style">
            <label>最小尺寸:宽度400px,高度200px</label>
            <sgDragSize @dragging="d => style = d" :minWidth="400" :minHeight="200" />
        </div>
    </div>
</template>
<script>
import sgDragSize from "@/vue/components/admin/sgDragSize";
export default {
    components: {
        sgDragSize,
    },
    data() {
        return {
            style: {
                height: '500px',
                width: '800px',
                left: '100px',
                top: '100px',
            },
        }
    },
};
</script>
<style lang="scss" scoped>
.box {
    position: absolute;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #409EFF55;
    box-sizing: border-box;
    border: 1px solid #409EFF;

    label {
        user-select: none;
        color: #409EFF;
    }
}
</style>

猜你喜欢

转载自blog.csdn.net/qq_37860634/article/details/132347222