javascript - 被拖拽的物体逃跑

标签 javascript jquery asynchronous svg draggable

好吧,我想要实现的是一个 SVG,里面有一个可以移动的 foreighObjects

我已经可以移动(可拖动),并且碰撞计算看起来没问题。只有1个问题。当我移动物体时,它只是间隔。它刚刚跑出了屏幕。

这是一些 HTML

<div id="canvas">
    <svg id="bewaar_holder" xmlns="http://www.w3.org/2000/svg" width="800" height="500" ></svg>
</div>

这是 JS:

var kist_width = 60;
var kist_width_real = 62; // Dat is met alle margin's en borders erbij op

var kist_height = 60;
var kist_height_real = 62; // Dat is met alle margin's en border erbij op

var row_counter = 1;


function makeNew(){
    var direction = $('input[name=direction]:checked').val();
    var name = $("#input_row_name").val();
    var length = $("#input_row_length").val();
    var height = $("#input_row_high").val();

    switch(direction){
        case 'lr':
            var leHTML = '<foreignObject id="foreign_row_' + row_counter + '" class="node obstacle foreign_drag" x="' + (10) + '" y="' + (10 ) + '" width="' + (( kist_width_real * length ) + kist_width_real ) + '" height="' + (kist_height + 2) + '"><body xmlns="http://www.w3.org/1999/xhtml">';
            leHTML += '<div class="row_holder_lr draggable_row" id="row_' + row_counter + '" ><div class="name_holder" >' + name + '</div>';
            leHTML += makeLR(length, height);
            break;
        default:
            alert("Er is een fout opgetreden waardoor de actie niet kon worden voltooid.");
            break;
    }

    leHTML += '</div></body></foreignObject>';
    document.getElementById('bewaar_holder').appendChild(parseSVG(leHTML));
    makeDraggable(row_counter);
    row_counter++;
}

function makeLR(length, height){
    var add = "";
    var counter = 1;
    while(counter <= length){
        add += '<div class="kist">';
        add += '<sup>' + counter + '</sup>';
        add += '<span>' + height + '</span>';
        add += '</div>';
        counter++;
    }

    return add;
}

/*
 * 
 * Alle drag acties:
 *
 */

$('body').on('drag', '.draggable_row', function() {
    var elem_row = this;
    var id = $(elem_row).attr('id');
    id = id.replace("row_", "");

    log("dragging row " + id);

    var move_left = $(elem_row).css('left').replace(/[^-\d\.]/g, '');
    var move_top = $(elem_row).css('top').replace(/[^-\d\.]/g, '');

    if(parseInt(move_left) > 0 || parseInt(move_top) > 0){
        var elem_foreign = $("#foreign_row_" + id);

        var x1_cur = parseInt($(elem_foreign).attr('x')) + parseInt(move_left);
        var x2_cur = (x1_cur + (parseInt($(elem_foreign).attr("width"))));
        var y1_cur = parseInt($(elem_foreign).attr('y')) + parseInt(move_top);
        var y2_cur = (y1_cur + (parseInt($(elem_foreign).attr("height"))));

        $(elem_row).css('left', "0");
        $(elem_row).css('top', "0");

        if(!mayMove(id, x1_cur, x2_cur, y1_cur, y2_cur)){
            log("may not move object...");
            return false;
        }

        $(elem_foreign).attr('x', x1_cur);
        $(elem_foreign).attr('y', y1_cur);
        log("we just moved");
        // return false;
    }

});

function mayMove(id_cur, x1_cur, x2_cur, y1_cur, y2_cur){
    var returnVal = true;
    $('.obstacle').each(function(i, obj) {      // Loop trough all objects
        if($(obj).attr("id") != "foreign_row_" + id_cur){   // Ignore the dragging ( own ) object
            var x1_obj = parseInt($(obj).attr('x'));
            var x2_obj = (x1_obj + (parseInt($(obj).attr("width"))));
            var y1_obj = parseInt($(obj).attr('y'));
            var y2_obj = (y1_obj + (parseInt($(obj).attr("height"))));

            var minX1 = Math.min(x1_obj, x1_cur);
            var maxX1 = Math.max(x1_obj, x1_cur);
            var minX2 = Math.min(x2_obj, x2_cur);
            var maxX2 = Math.max(x2_obj, x2_cur); 

            if( maxX2 <= minX1 || minX2 >= maxX1 ){
                log("overlapping with row_" + id_cur);
                returnVal = false;
            }
        }
    });
    return returnVal;
}

function makeDraggable(id){
    $("#row_" + id).draggable({ 
        // grid: [ 40, 40 ]
    });
}

function parseSVG(s) {
    var div= document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
    div.innerHTML= '<svg xmlns="http://www.w3.org/2000/svg">'+s+'</svg>';
    var frag= document.createDocumentFragment();
    while (div.firstChild.firstChild)
        frag.appendChild(div.firstChild.firstChild);
    return frag;
}

这是一个zip file以及所有需要的文件。我尝试用它制作一个 JSFiddle,但不知怎的,这不起作用。

所以基本上发生的事情是用户单击按钮并调用函数 makeNew 。这会创建一个新的 svg 元素并将其放入 svg 中。然后在 div 上有一个 draggable 调用(它在 svg 上不起作用)。

每次拖动 div 时,我们都可以使用边距将其添加到 foreignObject x 和 y 坐标,并再次清空 div 的左侧和顶部。

问题是你移动得越多,它就会跑得越快(我不粘鼠标)。

那么有人能看出这段代码中的错误吗?我已经用头撞墙几个小时了......

编辑 1

经过大量调试后,我意识到 $('body').on('drag' 会在每次移动时执行(女巫很好)。并且foreignObject 已更新为“正确”。只是元素的 css(left 和 top 值)未更新。当我手动执行命令时($(elem_row).css('left', "0px");) 值已更新。这就是问题所在。

所以它看起来像是某种 async “bug”(不是真正的 bug,但这段代码的设置使它看起来像是一个 bug),CSS 没有更新适本地。

现在唯一的问题...我不知道如何解决这个问题。大家有什么想法吗?

编辑2

我已将代码放在我的主机上,这样你们就可以看到它,而无需下载所有内容。 The website

最佳答案

因此,在审查了您所拥有的内容后,我开始进行相当多的更改。

我已经用 CHANGE: 记录了这些变化在此 jsfiddle 的各个 Pane 中发表评论.

最大的问题源于这样一个事实:您通过 jquery 使对象可拖动,然后在此基础上执行一些您自己的计算。这会对小部件造成一些不利影响。

我删除了那段代码并利用了 jQuery 的 droppable小部件。有了这个你就可以告诉obstacles触发 drop如果有任何东西接触到它,就会发生事件,导致它恢复到原来的位置。

这很大程度上忽略了 foreignObject您创建的元素并专注于浏览器通常使用的实际 html 元素。

关于javascript - 被拖拽的物体逃跑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24247477/

相关文章:

javascript - 如何捕获AJAX的结果

javascript - 使用 jQuery 在 HTML 中选择下拉列表中的选项更改时隐藏 div

jquery - 具有静态内容的砌体和加载更多按钮

javascript - 是否可以在 JavaScript 中对声音进行分层?

javascript添加onclick不成功

javascript - 使用 RegEx 创建带有类名的 div

javascript - 包含异步 javascript 文件有什么区别?

javascript - 为隐藏的文本区域赋值 onSubmit

javascript - 回调函数中的 for 循环中的回调函数

javascript - node async 仅在 node-lambda 内部调用第一个函数