• div拖拽缩放jquery插件编写——带8个控制点


    项目中需要对div进行拖拽缩放,需要有控制面板8个控制点的那种,原以为这么常见的效果应该能搜索到很多相关插件,然而可以完成拖拽的实繁,却找不到我想要的,还是自己动手丰衣足食吧
    效果预览(只支持pc端)

    思路

    一、舞台拖拽项定义

    拖拽以及缩放需要有一个范围,姑且管这个叫舞台(stage)。另外,在舞台范围内,如何以一种简单的方式定义拖拽项?可以通过给div增加一个拖拽class(例如:resize-item),拖拽项应该是absolute布局,舞台是relative/absolute布局

    所以拖拽类需要有如下两个参数

        /**
         * 默认参数
         */
        var defaultOpts = {
            stage: document, //舞台,默认为stage
            itemClass: 'resize-item', //可缩放的类名
        };
    
        /**
         * 定义类
         */
        var ZResize = function(options) {
            this.options = $.extend({}, defaultOpts, options);
            this.init();
        }
    

    二、生成控制面板

     
    控制面板
    1. 面板:为了尽可能少的影响到拖拽项,就不直接在拖拽项上生成控制点,而是为拖拽项增加一个半透明层作为控制面板,控制面板尺寸位置和拖拽项一致,将控制面板插入拖拽项(由于都是absolute布局,不影响原内容),可以更好的控制位置和一一对应
        var width = $(this).width();
        var height = $(this).height();
        var resizePanel = $('<div class"resize-panel"></div>');
        resizePanel.css({
             width,
            height: height,
            top: 0,
            left: 0,
            position: 'absolute',
            'background-color': 'rgba(0,0,0,0.5)',
            cursor: 'move',
            display: 'none'
        });
        self.appendHandler(resizePanel, $(this));
    
    1. 控制点:为控制面板增加东、南、西、北、东北、西北、西南、东南控制点,为每个控制点设置对应的cursor
        'cursor': 'n-resize' //北
        'cursor': 's-resize' //南
        'cursor': 'e-resize' //东
        'cursor': 'w-resize' //西
        'cursor': 'ne-resize' //东北
        'cursor': 'nw-resize' //西北
        'cursor': 'se-resize' //东南
        'cursor': 'sw-resize' //西南
    

    三、缩放

    1. 每个控制点影响的属性不一样
        北(上):
            高度(height) 
            位置y(拖拽上边,应该保持下边固定,所以高度变化之后位置也要变化)
        南(下):
            高度(height)
        东(右):
            宽度(width)
        西(左):
            宽度(width)
            位置x(拖拽左边,应该保持右边固定,所以宽度变化之后位置也要变化)
    
        东北、西北、东南、西南  以上两两结合
    
    1. 监听控制点mousedown,分别定义一个标志,并且记录下原始位置,如:
        //西
        var wmove = false;
        el.on('mousedown','.w', function(e) {
            ox = e.pageX;//原始x位置
            ow = el.width();
            oleft = parseInt(org.css('left').replace('px', ''));
            wmove = true;
        });
    
    1. 监听控制面板的mousedown,同样定义一个标志,用于拖动(drag)
    2. 监听舞台(stage)的mousemove(注意这里不是监听控制点的mousemove,因为控制点实在是太小,无法灵敏的拖动),判断各个控制点以及控制面板mousedown的标志分别对宽高和位置进行处理。处理的逻辑为:touchmove过程中的e.pageX/e.pageY - ox/oy(原始) = 偏移量,对于第一点中提到的每个控制点影响的属性,根据偏移量进行变化
     
    监听
    1. 监听舞台(stage)的mouseup事件(这里同样不能是控制点的mouseup),把所有的mousedown标志重置为false

    pc端的mouse事件不同于手机端的touch事件,touchstart->touchmove->touchend触发有顺序性,mouse事件没有顺序性,未触发mousedown也能触发mousemove,所以需要设置标志来判断

    四、控制面板的出现隐藏

    控制面板初始化的时候,应该是隐藏的,只有点击对应的拖拽项的时候才出现,并且点击舞台空白部分,需要隐藏控制面板(组织事件冒泡)

        /**
         +  点击item显示拖拽面板
         */
        bindTrigger: function(el) {
            var self = this;
            el.on('click', function(e) {
                //组织事件冒泡,不然会被舞台触发,舞台触发会把控制面板隐藏掉
                e.stopPropagation();
                self.triggerResize(el);
            });
        },
        /**
         +  点击舞台空闲区域 隐藏缩放面板
         */
        bindHidePanel: function(el) {
            var stage = this.options.stage;
            var itemClass = this.options.itemClass;
            $(stage).bind('click', function() {
                $('.' + itemClass).children('div').css({
                    display: 'none'
                });
            })
        }
    备注:
    相应的HTML内容:
    <!doctype html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title>jQuery拖拽放大缩小插件idrag</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <style type="text/css">
        .item1 {
             405px;
            height: 291px;
            cursor: move;
            position: absolute;
            top: 30px;
            left: 30px;
            background-color: #FFF;
            border: 1px solid #CCCCCC;
            -webkit-box-shadow: 10px 10px 25px #ccc;
            -moz-box-shadow: 10px 10px 25px #ccc;
            box-shadow: 10px 10px 25px #ccc;
        }
        
        .item2 {
             200px;
            height: 100px;
            cursor: move;
            position: absolute;
            top: 400px;
            left: 100px;
            background-color: #FFF;
            border: 1px solid #CCCCCC;
            -webkit-box-shadow: 10px 10px 25px #ccc;
            -moz-box-shadow: 10px 10px 25px #ccc;
            box-shadow: 10px 10px 25px #ccc;
            line-height: 100px;
            text-align: center;
        }
        
        body {
            background-color: #F3F3F3;
        }
        </style>
    </head>
    
    <body>
        <div class="resize-item item1">
            <img src="images/dog.png" width="100%" height="100%">
        </div>
    
        <div class="resize-item item2">
            你是我的小小狗
        </div>
        <script src="js/jquery.min.js"></script>
        <script type="text/javascript" src='js/jquery.ZResize.js'></script>
        <script type="text/javascript">
            new ZResize();
        </script>
    </body>
    
    </html>
    

      相应的js插件jquery.ZResize.js为:

    (function($) {
    
        /**
         * 默认参数
         */
        var defaultOpts = {
            stage: document, //舞台
            itemClass: 'resize-item', //可缩放的类名
        };
    
        /**
         * 定义类
         */
        var ZResize = function(options) {
            this.options = $.extend({}, defaultOpts, options);
            this.init();
        }
    
        ZResize.prototype = {
            init: function() {
                this.initResizeBox();
            },
            /**
             *  初始化拖拽item
             */
            initResizeBox: function() {
                var self = this;
                $('.' + self.options.itemClass).each(function() {
                    //创建面板
                    var width = $(this).width();
                    var height = $(this).height();
                    var resizePanel = $('<div class"resize-panel"></div>');
                    resizePanel.css({
                         width,
                        height: height,
                        top: 0,
                        left: 0,
                        position: 'absolute',
                        'background-color': 'rgba(0,0,0,0.5)',
                        cursor: 'move',
                        display: 'none'
                    });
                    self.appendHandler(resizePanel, $(this));
                    /**
                     * 创建控制点
                     */
                    var n = $('<div class="n"></div>');//北
                    var s = $('<div class="s"></div>');//南
                    var w = $('<div class="w"></div>');//西
                    var e = $('<div class="e"></div>');//东
                    var ne = $('<div class="ne"></div>');//东北
                    var nw = $('<div class="nw"></div>');//西北
                    var se = $('<div class="se"></div>');//东南
                    var sw = $('<div class="sw"></div>');//西南
    
                    //添加公共样式
                    self.addHandlerCss([n, s, w, e, ne, nw, se, sw]);
                    //添加各自样式
                    n.css({
                        'top': '-4px',
                        'margin-left': '-4px',
                        'left': '50%',
                        'cursor': 'n-resize'
                    });
                    s.css({
                        'bottom': '-4px',
                        'margin-left': '-4px',
                        'left': '50%',
                        'cursor': 's-resize'
                    });
                    e.css({
                        'top': '50%',
                        'margin-top': '-4px',
                        'right': '-4px',
                        'cursor': 'e-resize'
                    });
                    w.css({
                        'top': '50%',
                        'margin-top': '-4px',
                        'left': '-4px',
                        'cursor': 'w-resize'
                    });
                    ne.css({
                        'top': '-4px',
                        'right': '-4px',
                        'cursor': 'ne-resize'
                    });
                    nw.css({
                        top: '-4px',
                        'left': '-4px',
                        'cursor': 'nw-resize'
                    });
                    se.css({
                        'bottom': '-4px',
                        'right': '-4px',
                        'cursor': 'se-resize'
                    });
                    sw.css({
                        'bottom': '-4px',
                        'left': '-4px',
                        'cursor': 'sw-resize'
                    });
    
                    // 添加项目
                    self.appendHandler([n, s, w, e, ne, nw, se, sw], resizePanel);
                    
                    //绑定拖拽缩放事件
                    self.bindResizeEvent(resizePanel, $(this));
    
                    //绑定触发事件
                    self.bindTrigger($(this));
                });
                self.bindHidePanel();
            },
            //控制点公共样式
            addHandlerCss: function(els) {
                for(var i = 0; i < els.length; i++) {
                    el = els[i];
                    el.css({
                        position: 'absolute',
                         '8px',
                        height: '8px',
                        background: '#ff6600',
                        margin: '0',
                        'border-radius': '2px',
                        border: '1px solid #dd5500',
                    });
                }
            },
            /**
             *  插入容器
             */
            appendHandler: function(handlers, target) {
                for(var i = 0; i < handlers.length; i++) {
                    el = handlers[i];
                    target.append(el);
                }
            },
            /**
             *  显示拖拽面板
             */
            triggerResize: function(el) {
                var self = this;
                el.siblings('.' + self.options.itemClass).children('div').css({
                    display: 'none'
                });
                el.children('div').css({
                    display: 'block'
                });
            },
            /**
             * 拖拽事件控制 包含8个缩放点  和一个拖拽位置
             */
            bindResizeEvent: function(el) {
    
                var self = this;
                var ox = 0; //原始事件x位置
                var oy = 0; //原始事件y位置
                var ow = 0; //原始宽度
                var oh = 0; //原始高度
    
                var oleft = 0; //原始元素位置
                var otop = 0;
                var org = el.parent('div');
    
                //东
                var emove = false;
                el.on('mousedown','.e', function(e) {
                    ox = e.pageX;//原始x位置
                    ow = el.width();
                    emove = true;
                });
    
                //南
                var smove = false;
                el.on('mousedown','.s', function(e) {
                    oy = e.pageY;//原始x位置
                    oh = el.height();
                    smove = true;
                });
    
                //西
                var wmove = false;
                el.on('mousedown','.w', function(e) {
                    ox = e.pageX;//原始x位置
                    ow = el.width();
                    wmove = true;
                    oleft = parseInt(org.css('left').replace('px', ''));
                });
    
                //北
                var nmove = false;
                el.on('mousedown','.n', function(e) {
                    oy = e.pageY;//原始x位置
                    oh = el.height();
                    nmove = true;
                    otop = parseInt(org.css('top').replace('px', ''));
                });
    
                //东北
                var nemove = false;
                el.on('mousedown','.ne', function(e) {
                    ox = e.pageX;//原始x位置
                    oy = e.pageY;
                    ow = el.width();
                    oh = el.height();
                    nemove = true;
                    otop = parseInt(org.css('top').replace('px', ''));
                });
    
                //西北
                var nwmove = false;
                el.on('mousedown','.nw', function(e) {
                    ox = e.pageX;//原始x位置
                    oy = e.pageY;
                    ow = el.width();
                    oh = el.height();
                    otop = parseInt(org.css('top').replace('px', ''));
                    oleft = parseInt(org.css('left').replace('px', ''));
                    nwmove = true;
                });
    
                //东南
                var semove = false;
                el.on('mousedown','.se', function(e) {
                    ox = e.pageX;//原始x位置
                    oy = e.pageY;
                    ow = el.width();
                    oh = el.height();
                    semove = true;
                });
    
                //西南
                var swmove = false;
                el.on('mousedown','.sw', function(e) {
                    ox = e.pageX;//原始x位置
                    oy = e.pageY;
                    ow = el.width();
                    oh = el.height();
                    swmove = true;
                    oleft = parseInt(org.css('left').replace('px', ''));
                });
    
                //拖拽
                var drag = false;
                el.on('mousedown', function(e) {
                    ox = e.pageX;//原始x位置
                    oy = e.pageY;
                    otop = parseInt(org.css('top').replace('px', ''));
                    oleft = parseInt(org.css('left').replace('px', ''));
                    drag = true;
                });
    
                $(self.options.stage).on('mousemove', function(e) {
                    if(emove) {
                        var x = (e.pageX - ox);
                        el.css({
                             ow + x
                        });
                        org.css({
                             ow + x
                        });
                    } else if(smove) {
                        var y = (e.pageY - oy);
                        el.css({
                            height: oh + y
                        });
                        org.css({
                            height: oh + y
                        });
                    } else if(wmove) {
                        var x = (e.pageX - ox);
                        el.css({
                             ow - x,
                            // left: oleft + x
                        });
                        org.css({
                             ow - x,
                            left: oleft + x
                        });
                    } else if(nmove) {
                        var y = (e.pageY - oy);
                        el.css({
                            height: oh - y,
                            // top: otop + y
                        });
                        org.css({
                            height: oh - y,
                            top: otop + y
                        });
                    } else if(nemove) {
                        var x = e.pageX - ox;
                        var y = e.pageY - oy;
                        el.css({
                            height: oh - y,
                            // top: otop + y,
                             ow + x
                        });
                        org.css({
                            height: oh - y,
                            top: otop + y,
                             ow + x
                        });
                    } else if(nwmove) {
                        var x = e.pageX - ox;
                        var y = e.pageY - oy;
                        el.css({
                            height: oh - y,
                            // top: otop + y,
                             ow - x,
                            // left: oleft + x
                        });
                        org.css({
                            height: oh - y,
                            top: otop + y,
                             ow - x,
                            left: oleft + x
                        });
                    } else if(semove) {
                        var x = e.pageX - ox;
                        var y = e.pageY - oy;
                        el.css({
                             ow + x,
                            height: oh + y
                        });
                        org.css({
                             ow + x,
                            height: oh + y
                        });
                    } else if(swmove) {
                        var x = e.pageX - ox;
                        var y = e.pageY - oy;
                        el.css({
                             ow - x,
                            // left: oleft + x,
                            height: oh + y
                        });
                        org.css({
                             ow - x,
                            left: oleft + x,
                            height: oh + y
                        });
                    } else if(drag) {
                        var x = e.pageX - ox;
                        var y = e.pageY - oy;
                        org.css({
                            left: oleft + x,
                            top: otop + y
                        });
                    }
                }).on('mouseup', function(e) {
                   emove = false;
                   smove = false;
                   wmove = false;
                   nmove = false;
                   nemove = false;
                   nwmove = false;
                   swmove = false;
                   semove = false;
                   drag = false;
                });
            },
            /**
             *  点击item显示拖拽面板
             */
            bindTrigger: function(el) {
                var self = this;
                el.on('click', function(e) {
                    e.stopPropagation();
                    self.triggerResize(el);
                });
            },
            /**
             *  点击舞台空闲区域 隐藏缩放面板
             */
            bindHidePanel: function(el) {
                var stage = this.options.stage;
                var itemClass = this.options.itemClass;
                $(stage).bind('click', function() {
                    $('.' + itemClass).children('div').css({
                        display: 'none'
                    });
                })
            }
        }
    
        window.ZResize = ZResize;
    
    })(jQuery);
    

      


    源码链接:https://github.com/zengwenfu/z-resize
    作者:小虫巨蟹
    链接:https://www.jianshu.com/p/822afede7489
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    冲刺(六)
    冲刺(五)
    冲刺(四)
    团队产品开发
    冲刺(三)
    冲刺(二)
    冲刺(一)
    电梯演讲,模型展示
    校园健康行的NABCD分析
    团队博客
  • 原文地址:https://www.cnblogs.com/sweeeper/p/9035717.html
Copyright © 2020-2023  润新知