【问题标题】:Dragging and Dropping onto a scaled element拖放到缩放的元素上
【发布时间】:2015-03-18 23:44:39
【问题描述】:

我有一个 div 元素,我希望能够将它拖到缩放的元素上。但是,当我这样做时,div 元素不会转到元素的正确坐标,但是当我第二次拖动它时它会。

我还认为添加元素时它会扩大规模,我想尝试避免这种情况。

谁能帮我解决这个问题? (尤其是整个没有找对地方的事情)

我已经尝试过这样的事情来获取 div 的实际坐标,但我不确定如何将其转换为可拖动元素,因为mousemove 在我拖动某些东西时不起作用。

$("body").on("mousemove", ".formBackground", function(e){
    div_x = (e.offsetX != null) ? e.offsetX : e.originalEvent.layerX;
    div_y = (e.offsetY != null) ? e.offsetY : e.originalEvent.layerY; 

    console.log("x "+div_x+" y "+div_y); 
});

这是我的实际代码和我的JSFIDDLE的链接

HTML

<div id="drag1" class="drag" style="font-size:12px;background-color:#E2F4FE;width:220px;padding:10px;color:#000;font-weight:normal;">New box</div>
<br />
<br />
<div id="formBox">
    <div id="formScale">
        <div class="formContent">
            <div class="formBackground" style="background-image:url('http://i.imgur.com/roOQNaS.png');"></div>
        </div>
    </div>
</div>

JS

var percent = 1.5;

$("#formScale").css({
    'transform': 'scale(' + percent + ')',
        '-moz-transform': 'scale(' + percent + ')',
        '-webkit-transform': 'scale(' + percent + ')',
        '-ms-transform': 'scale(' + percent + ')'
});

var counter = 0;
//Make element draggable
$(".drag").draggable({
    helper: 'clone',
    containment: 'frame',
    //When first dragged
    stop: function (ev, ui) {
        var pos = $(ui.helper).offset();
        objName = "#clonediv" + counter
        $(objName).css({
            "left": pos.left,
                "top": pos.top
        });
        $(objName).removeClass("drag");
        //When an existiung object is dragged
        $(objName).draggable({
            containment: 'frame',
            stop: function (ev, ui) {
                var pos = $(ui.helper).offset();
                console.log($(this).attr("id"));
                console.log(pos.left)
                console.log(pos.top)
            }
        });
    }
});


$(".formBackground").droppable({
    drop: function (ev, ui) {
        if (ui.draggable.attr('id').search(/drag[0-9]/) != -1) {
            counter++;
            var element = $(ui.draggable).clone();
            element.addClass("tempclass");
            $(this).append(element);
            $(".tempclass").attr("id", "clonediv" + counter);
            $("#clonediv" + counter).removeClass("tempclass");
            //Get the dynamically item id
            draggedNumber = ui.draggable.attr('id').search(/drag([0-9])/)
            itemDragged = "dragged" + RegExp.$1
            console.log(itemDragged)
            $("#clonediv" + counter).addClass(itemDragged);
        }
    }
});

CSS

#formBox {
    position:relative;
}
#formScale {
    border:1px solid red;
    position:relative;
    width:350px;
    height:200px;
    margin:0;
    -webkit-transform-origin: 0 0;
    -moz-transform-origin: 0 0;
    transform-origin: 0 0;
    -ms-transform-origin: 0 0;
}
.formContent {
    position:absolute;
    width:100%;
    height:100%;
}
.formBackground {
    width:100%;
    height:100%;
    background-size:contain;
    background-position:center;
    background-repeat:no-repeat;
}

【问题讨论】:

    标签: javascript jquery jquery-ui jquery-ui-draggable jquery-ui-droppable


    【解决方案1】:

    如果我正确理解了您的目标,那么您需要注意很多事情。

    1。相对位置

    当一个 HTML 元素的父元素发生变化(即元素被附加到某个其他元素)时,它在屏幕上的位置会发生变化,除非它的 position 属性为 fixed(这不是默认值)。
    因此,当您将 div 附加到 $('.formBackground')(我将其称为 formBackground)时,它的位置将相对于其先前的兄弟姐妹,或者,如果没有先前的兄弟姐妹,则相对于 formBackground 本身。 要解决此问题,您必须从可拖动对象的偏移量中减去 formBackground 的偏移量。
    此外,您需要将position 设置为absolute,因此可拖动对象总是相对于formBackground 而不是之前的可拖动对象呈现。

    The CSS position property is explained here.

    为此,请删除这段话(小提琴中的第 19-22 行):

    $(objName).css({
        "left": pos.left,
            "top": pos.top
    });
    

    而是在element.addClass("tempclass"); 之后添加以下段落(当前为第 43 行):

    element.css({
        "position": "absolute",
        "left": ui.offset.left - $(this).offset().left,
        "top": ui.offset.top - $(this).offset().top
    });
    

    接下来要注意的是:

    2。偏移缩放

    如果现在您要在第 1 行设置 var percent = 1.0;,则可拖动对象应该准确地停留在它所在的位置。
    然而,对于任何其他因素,它都不会,因为它的偏移量也会成倍增加。

    The CSS transform property and its scale() value are explained here,但是文档没有提到这也适用于对象的偏移量,似乎就是这样。

    您可以简单地编辑上面的 sn-p 以将 left 和 top 除以 percent:

    element.css({
        "position": "absolute",
        "left": (ui.offset.left - $(this).offset().left) / percent,
        "top": (ui.offset.top - $(this).offset().top) / percent
    });
    

    现在,无论percent 设置为什么,可拖动对象的左上角都应始终保持在您放置它的位置。

    我分叉并编辑了您的小提琴以反映这两个变化。由于我还没有 10 个声望,所以我不能发布超过 2 个链接,但无论如何都在这里:http://jsfiddle.net/n7yns9eq/2/

    3。 (可选)左上锚定变换

    我发现将元素的“参考点”设为中心而不是左上角对用户更友好。这对我来说似乎更直观。如果您也发现了这种情况,请按以下步骤操作:

    从left/top你必须减去一半的金额width/height会增加。在代码中:

    element.css({
        "position": "absolute",
        "left": (ui.offset.left - $(this).offset().left - $(ui.draggable).width() * (percent - 1) / 2) / percent,
        "top": (ui.offset.top - $(this).offset().top - $(ui.draggable).height() * (percent - 1) / 2) / percent
    });
    

    请注意,您不能使用element,而不是$(ui.draggable),因为此时尚未呈现element,并且没有为height设置显式值,@ 987654356@ 将返回0。

    小提琴:http://jsfiddle.net/9xbgqdeo/1/

    4。死区和非比例移动

    我注意到的另一个问题是,现在,如果您将可拖动对象放在formBackground 的最左三分之一的下方,则不会发生拖放。我不知道这是由浏览器引擎(未调整对象的功能区域大小)还是 jquery(忽略转换)引起的。
    我能想到的解决此问题的唯一方法是使body 可丢弃而不是formBackground,检查它是否在formBackground 的边界内,如果是,将其附加在那里,否则丢弃。
    请注意,如果您的页面没有填满整个浏览器窗口,要使此功能正常工作,您必须设置以下 CSS:

    html, body {
        width: 100%;
        height: 100%;
    }
    

    不要忘记将可放置函数中的每个this 替换为$('.formBackground')。

    此外,当从formBackground 抓取现有的可拖动对象并四处移动时,它会从光标上移开,我认为这是不需要的。为了防止这种情况发生,我建议将 div 移回其原始父级,并恢复在 formBackground 上删除时所做的偏移更改。

    老实说,我现在懒得为这两个更改提供小提琴(编辑:http://jsfiddle.net/gtc17z6b/1/),但我希望这能解决你的问题。

    【讨论】:

    • 非常感谢 Siguza!这非常有帮助并且解释了很多。我很难理解关于光标的最后一部分。我对最后一部分非常感兴趣。如果你能找到一些时间并且可以制作小提琴,那将对我有很大帮助,我会当场奖励你赏金。你付出的所有时间都值得拥有。
    • Here you go。仍然有一些调试代码,使用字符串不一致,使用 jquery 内部,但可以工作。如果它的中心在框内,则可拖动对象现在被视为“在框内”。如果您想更改,请参阅第 56 和 57 行。
    【解决方案2】:

    我想看看这个库:

    https://greensock.com/draggable

    它确实以正确的方式处理规模和转换:

    http://codepen.io/gavrochelegnou/pen/KpWVqo

    就像喝一杯水一样容易:

    Draggable.create(".box", {type:"x,y", edgeResistance:0.65, bounds:".container", throwProps:true});
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-20
      • 2015-08-28
      • 2020-08-05
      • 2018-09-29
      • 1970-01-01
      • 2011-03-01
      相关资源
      最近更新 更多