在缩放 div 上拖动元素

Dragging elements on a scaled div

我试过使用 jquery 的内置可拖动功能,我试过使用自定义拖动功能,但都无济于事。两者都有各自的问题,我会尽量强调它们。

基本上,我试图允许拖动缩放 div 容器上的元素。以下方法在小于 2 左右的缩放元素上 还可以 。但如果你再高一点,我们就会发现一些问题。

如有任何帮助,我们将不胜感激。谢谢你的时间。

HTML

<div id="container">
    <div id="dragme">Hi</div>
</div>

方法 1(Jquery 可拖动功能)

我已经尝试了 jquery 可拖动功能,如您在此 jsfiddle 示例中所见。

我在这个例子中发现的问题如下:


JS

var percent = 2.5;

$("#dragme").draggable({
    zIndex: 3000,
    appendTo: 'body',
    helper: function (e, ui) {
        var draggable_element = $(this),
            width = draggable_element.css('width'),
            height = draggable_element.css('height'),
            text = draggable_element.text(),
            fontsize = draggable_element.css('font-size'),
            textalign = draggable_element.css('font-size');
        return $('<div id="' + draggable_element.id + '" name="' + draggable_element.attr('name') + '" class="text">' + text + '</div>').css({
            'position': 'absolute',
                'text-align': textalign,
                'background-color': "red",
                'font-size': fontsize,
                'line-height': height,
                'width': width,
                'height': height,
                'transform': 'scale(' + percent + ')',
                '-moz-transform': 'scale(' + percent + ')',
                '-webkit-transform': 'scale(' + percent + ')',
                '-ms-transform': 'scale(' + percent + ')'
        });
    },
    start: function (e, ui) {
        $(this).hide();
    },
    stop: function (e, ui) {
        $(this).show();
    }
});

$("#container").droppable({
    drop: function (event, ui) {
        var formBg = $(this),
            x = ui.offset.left,
            y = ui.offset.top,
            drag_type = ui.draggable.attr('id');

        var element_top = (y - formBg.offset().top - $(ui.draggable).height() * (percent - 1) / 2) / percent,
            element_left = (x - formBg.offset().left - $(ui.draggable).width() * (percent - 1) / 2) / percent;

        $(ui.draggable).css({
            'top': element_top,
                'left': element_left
        });

    }
});

方法二-自定义拖动功能

我试过使用自定义拖动功能,但在大约 2 比例后无法使用。

JS

(function ($) {
    $.fn.drags = function (opt) {

        opt = $.extend({
            handle: "",
            cursor: "move"
        }, opt);

        if (opt.handle === "") {
            var $el = this;
        } else {
            var $parent = this;
            var $el = this.find(opt.handle);
        }

        return $el.css('cursor', opt.cursor).on("mousedown", function (e) {
            if (opt.handle === "") {
                var $drag = $(this).addClass('draggable');
            } else {
                $(this).addClass('active-handle')
                var $drag = $parent.addClass('draggable');
            }

            var
            drg_h = $drag.outerHeight(),
                drg_w = $drag.outerWidth(),
                pos_y = $drag.offset().top + drg_h - e.pageY,
                pos_x = $drag.offset().left + drg_w - e.pageX;

            follow = function (e) {
                $drag.offset({
                    top: e.pageY + pos_y - drg_h,
                    left: e.pageX + pos_x - drg_w
                })
            };

            $(window).on("mousemove", follow).on("mouseup", function () {
                $drag.removeClass('draggable');
                $(window).off("mousemove", follow);
            });

            e.preventDefault(); // disable selection

        }).on("mouseup", function () {
            if (opt.handle === "") {
                $(this).removeClass('draggable');
            } else {
                $(this).removeClass('active-handle');
                $parent.removeClass('draggable');
            }
        });

    }
})(jQuery);

$("#dragme").drags({}, function (e) {});

这里提到了类似的问题:jquery - css "transform:scale" affects '.offset()' of jquery

问题似乎是由于 jQuery 无法 return 缩放元素的精确大小,因此无法为元素设置正确的偏移值。

为了解决这个问题,他建议先将比例设置为 1 并设置偏移量,然后再次重置比例值。

但这并不能解决这里的问题。由于在缩放时会获取鼠标位置,因此位置值也应除以缩放值。

这是代码的编辑版本:

  var scl = 2.5;
  var
    drg_h = $drag.outerHeight(),
    drg_w = $drag.outerWidth(),
    pos_y = $drag.offset().top/scl + drg_h - e.pageY/scl,
    pos_x = $drag.offset().left/scl + drg_w - e.pageX/scl;

  follow = function(e) {
    var size = {
      top:e.pageY/scl + pos_y - drg_h+scl*2,
      left:e.pageX/scl + pos_x - drg_w+scl*2
    };
      $drag.parent().css("transform","scale(1)");
      $drag.offset(size);
      $drag.parent().css("transform","scale("+scl+")");
  };

注意: 我只替换了 transform 标签的比例值,因为我使用的是 chrome。您也可以替换所有实例,或者您可以使用具有 1 个比例值的不同 class。

JSFiddle 也是 here

这里是一个带有缩放的简单拖动示例,然而,在 prue dom。

<style>
#dragme {
    position:absolute;
    border:1px solid red;
    background:pink;
    left:10px;
    top:20px;
    width:100px;
    height:200px;
}
#container {
    transform: scale(2,2) translate(100px,100px);
    position:relative;
    border:1px solid green;
    background:grey;
    width:200px;
    height:300px;
}
</style>
<body>

<div id="container">
    <div id="dragme">Hi</div>
</div>


    <script>
    var dragme=document.getElementById("dragme");
    var container=document.getElementById("container");
    dragme.onmousedown=function Drag(e){
        this.ini_X = this.offsetLeft-e.clientX/2;
        this.ini_Y = this.offsetTop-e.clientY/2;
        container.onmousemove = move;
        container.onmouseup = release;
      return false;
    }
    function move(e){
        e.target.style.left = e.clientX/2 + e.target.ini_X + 'px';
        e.target.style.top = e.clientY/2 + e.target.ini_Y + 'px';
    }
    function release(){
        container.onmousemove=container.onmouseup=null;
}

    </script>
    </body>

以下是我的一些发现,以确保在缩放容器上拖动适用于方法一。唯一需要注意的是,在任何这些操作发生之前,请确保您已将 var percent 作为已声明的比例百分比。

首先,在 javascript 的顶部使用此代码。这将有助于确保可放置区域适用于 sacled 容器。

$.ui.ddmanager.prepareOffsets = function( t, event ) { var i, j, m = $.ui.ddmanager.droppables[ t.options.scope ] || [], type = event ? event.type : null, list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack(); droppablesLoop: for ( i = 0; i < m.length; i++ ) { if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) { continue; } for ( j = 0; j < list.length; j++ ) { if ( list[ j ] === m[ i ].element[ 0 ] ) { m[ i ].proportions().height = 0; continue droppablesLoop; }  } m[ i ].visible = m[ i ].element.css( "display" ) !== "none"; if ( !m[ i ].visible ) { continue; } if ( type === "mousedown" ) { m[ i ]._activate.call( m[ i ], event ); } m[ i ].offset = m[ i ].element.offset(); m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth * percent, height: m[ i ].element[ 0 ].offsetHeight * percent }); } };

这里有一些必要的函数来修复拖动,以便它在缩放的容器上工作。

function dragFix(event, ui) { var changeLeft = ui.position.left - ui.originalPosition.left, newLeft = ui.originalPosition.left + changeLeft / percent, changeTop = ui.position.top - ui.originalPosition.top, newTop = ui.originalPosition.top + changeTop / percent; ui.position.left = newLeft; ui.position.top = newTop; }

function startFix(event, ui) { ui.position.left = 0; ui.position.top = 0;  var element = $(this); }

如果你想让元素在缩放容器上可以调整大小,你会需要这个。

function resizeFix(event, ui) { var changeWidth = ui.size.width - ui.originalSize.width, newWidth = ui.originalSize.width + changeWidth / percent, changeHeight = ui.size.height - ui.originalSize.height, newHeight = ui.originalSize.height + changeHeight / percent;  ui.size.width = newWidth; ui.size.height = newHeight; }

为了使元素可拖动,我使用了以下函数。

$("ELEMENT").resizable({ minWidth: - ($(this).width()) * 10, minHeight: - ($(this).height()) * 10, resize: resizeFix, start: startFix });
$("ELEMENT").draggable({ cursor: "move", start: startFix, drag: dragFix }); }