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

简介: 【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="dragging" :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',
            },
        }
    },
    methods: {
        dragging({ style }) {
            this.style = style;
        },
    },
};
</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>


相关文章
|
7月前
|
前端开发 算法 JavaScript
从基础到进阶:实现div控件的拖拽和缩放功能
从基础到进阶:实现div控件的拖拽和缩放功能
115 0
|
4月前
|
前端开发 图形学
小功能⭐️3DCanvas交互方法、Unity自动调整文本框大小、改变文字大小和颜色
小功能⭐️3DCanvas交互方法、Unity自动调整文本框大小、改变文字大小和颜色
|
5月前
|
JavaScript
vue 指定区域可拖拽的限定拖拽区域的div(如仅弹窗标题可拖拽的弹窗)
vue 指定区域可拖拽的限定拖拽区域的div(如仅弹窗标题可拖拽的弹窗)
235 0
|
5月前
Element UI 自定义/修改下拉弹窗的样式(如级联选择器的下拉弹窗样式)
Element UI 自定义/修改下拉弹窗的样式(如级联选择器的下拉弹窗样式)
510 0
|
7月前
|
JavaScript
vue给li标签设置鼠标覆盖阴影样式
vue给li标签设置鼠标覆盖阴影样式
|
7月前
简单讲述ondragstart、drag、ondragend、ondragenter、ondragover、ondrop、ondragleave七个与拖拽相关的监听事件,并运用实现拖拽过程放置样式变化
简单讲述ondragstart、drag、ondragend、ondragenter、ondragover、ondrop、ondragleave七个与拖拽相关的监听事件,并运用实现拖拽过程放置样式变化
|
7月前
|
JavaScript 前端开发 API
【每周一个小技巧】如何自定义客服、生活号组件的样式
【每周一个小技巧】如何自定义客服、生活号组件的样式
79 8
|
7月前
【sgDragMove】自定义组件:自定义拖拽组件,仅支持拖拽、设置吸附屏幕边界距离。
【sgDragMove】自定义组件:自定义拖拽组件,仅支持拖拽、设置吸附屏幕边界距离。
|
容器
uniapp滚动页面改变背景颜色
uniapp滚动页面改变背景颜色
403 0
|
JavaScript 定位技术
vue 里怎么使用 echarts 实现地图自动轮播功能、自定义 tooltip 悬浮位置提示、自定义 label 标签位置样式?
vue 里怎么使用 echarts 实现地图自动轮播功能、自定义 tooltip 悬浮位置提示、自定义 label 标签位置样式?
1038 0
vue 里怎么使用 echarts 实现地图自动轮播功能、自定义 tooltip 悬浮位置提示、自定义 label 标签位置样式?
下一篇
DataWorks