我写了一个闭包,将可拖动元素添加到地图。我希望外壳能保留值。没有。为什么不呢?

问题描述 投票:0回答:1

我想使用香草javascript注释地图上的路线。为此,我有一个canvas元素,一个将div“连接”到地图上的点的绘制例程,一个用于构建小div的闭包以及另一个使div可拖动的闭包,因此可以更方便地将它们放置在地图上。在两个闭包中,我都遇到了同样的问题。

js和HTML,以显示使可拖动闭包makeDraggable出现的问题,如下所示。最外部的函数声明一个变量dragThis。 dragstart处理程序为其分配值。 onDragOveronDrop使用它。调试器说dragThis在每次使用时都处于相同的makeDraggable闭包中。我希望这种方法可以简化代码的整体结构和效率。

问题:当拖放处理程序触发时,dragThis没有在dragStart中分配的值。为什么?(???)(实际上,拖放处理程序中的值似乎是在第一次通过测试对makedraggable进行的调用中该元素的ID。)

相关问题:

  • 我使用dataTransfer对象的setData / getData方法。对于我的一生,我不了解这些功能的第一个论点“格式”。它似乎与“格式”没有任何关系(只是在内部将“文本”更改为“文本/纯文本”),而与标识数据无关。 'format'的值几乎可以是任何字符串。从W3:* API 不强制执行使用MIME类型;也可以使用其他值。*'name'似乎是一个更合适的名称。我想念什么吗?鸭子不应该被称为鸭子吗?这似乎几乎不值得一个单独的问题,但我很好奇,不知道该怎么问。

  • MDN表示事件对象的pageX,pageY“ ...包括当前不可见的页面的任何部分。”它们似乎不包括滚动元素的不可见部分,因此这似乎是错误的。我想念什么? (并且我的pageXY函数是否正确计算了does正确考虑了那些不可见位的位置?这似乎有用,但是我的示例可能太简单了。)

  • Firefox和小提琴似乎对我的代码感到满意。但是,Chrome在placeEl中的放置时间认为'el.style.left = ...'中的'el'为空:TypeError:无法读取null的属性'style'...。尽管如此,它还是对下一行感到满意,并且神奇地继续正确地定位了div。

我将代码放在https://jsfiddle.net/HerbX/g7zv1ok2/1/,也许还在那里。我已经将说明性的div硬编码到html中。

显然已经引用了小提琴,我也需要将代码放在这里:

var MYSTUFF = {
    makeDraggable:function(el, elChart) {
      var dragThis = el;
        var ops = {capture:true, useCapture:true};
        el.draggable = true;
        el.addEventListener('dragstart', onDragStart, ops);
        console.log("dragstart listener added to " + el.id);
        if (elChart.dataset.dragover === undefined) {
            elChart.addEventListener('dragover', onDragOver, ops);
            elChart.addEventListener('drop', onDrop, ops);
            elChart.dataset.dragover = 'dragover';
            console.log("dragover listener added to " + elChart.id);
        }
        return el;

        function onDragStart(ev) {
            var clickXY;
            dragThis = ev.target;
            clickXY = MYSTUFF.pageXY(ev);
            ev.dataTransfer.clearData();
            ev.dataTransfer.setData('text/plain',toStr(ev.target.id, ev.target.offsetLeft, ev.target.offsetTop, clickXY.x, clickXY.y));
            ev.dataTransfer.setData('foo', ev.target.id);
            console.log("dragStart: dragThis.id is " + dragThis.id + ", dT = " + ev.dataTransfer.getData('text/plain'));
            }

        function onDragOver(ev){
            var pos;                // new (style.top, style.left)
            var canvasid;           // canvas, if px, py exist
            var params, el;
            var foo;
            ev.preventDefault();
            params = ev.dataTransfer.getData('text/plain').split(';')
            foo = ev.dataTransfer.getData('foo');
            el = document.getElementById(params[0]);
            pos = placeEl(ev, el);  // Reposition el by delta(mouse)
            console.log("onDragOver: dragThis.id = " + dragThis.id + '; foo = ' + foo);
        }

        function onDrop(ev) {
            var canvasTemp, canvasid, ctx;
            var dT, params;
            var el, els;
            ev.preventDefault();
            dT = ev.dataTransfer.getData('text/plain');
            params = dT.split(';');
            console.log("onDrop event: dragThis.id is " + dragThis.id + ", dT is " + dT);
            el = document.getElementById(params[0]);
            placeEl(ev,el);                                   //Reposition el, ignore return.
        }

        function toStr() {
//  arguments => ;-delimited string.  Args must be scalar numbers.              
            var delim='';
            var s = "";
            for (var i = 0; i < arguments.length; i++) {
                if (isNaN(arguments[i])) {
                    s += delim + arguments[i];
                } else {
                    s += delim + arguments[i].toFixed(1);
                }
                delim = ";";
            }
            return s;
        }

        function placeEl(ev,el) {
/*  Re-position el by delta(mouse position)             */
            var params;
            var dx, dy;
            var pos;
            var cursorXY;
            params = ev.dataTransfer.getData('text/plain').split(';');
            cursorXY = MYSTUFF.pageXY(ev);
            dx = cursorXY.x - parseFloat(params[3]);
            dy = cursorXY.y - parseFloat(params[4]);
            pos = {x:parseFloat(params[1]) + dx, y:parseFloat(params[2]) + dy};
            el.style.left = pos.x + 'px';
          el.style.top =  pos.y + 'px';
            return pos;
        }
    },

    reportXY: function(ev) {
        let x, y, abs, sAbs;
        let msg = document.getElementById('msg');
        let el = ev.srcElement;
        let id = el.id;
        if (id === "") id = el.tagName;
        x = event.pageX.toFixed(0);
        y = event.pageY.toFixed(0);
        abs = MYSTUFF.pageXY(ev);
        sAbs = "(" + abs.x + "," + abs.y + ")";
        msg.innerText = "In " + id + ", cursor @ Page XY: (" + x + "," + y +").  Including scrolls, cursor @ " + sAbs;
    },

    pageXY:function(ev) {
        let x = ev.pageX;
        let y = ev.pageY;
        let scrollX, scrollY, tagName, el;

        el = ev.srcElement;
        tagName = el.tagName;
        scrollX = el.scrollLeft;
        scrollY = el.scrollTop;
        while (tagName !== 'HTML') {
            el = el.parentElement;
            tagName = el.tagName;
            scrollX += el.scrollLeft;
            scrollY += el.scrollTop;
        }
        return {x:x+scrollX, y:y+scrollY}
    }
}
/* test1() only tests makeDraggable.  It uses elements hardwired into the HTML.*/
function test1() {
    var elChart = document.getElementById('chartPosRef');
    var div = document.getElementById('div-0');
    MYSTUFF.makeDraggable(div, elChart);

    div = document.getElementById('div-1');
    MYSTUFF.makeDraggable(div,elChart);

    div = document.getElementById('div-2');
    MYSTUFF.makeDraggable(div,elChart); 

    div = document.getElementById('div-3');
    MYSTUFF.makeDraggable(div,elChart);
}
window.addEventListener('DOMContentLoaded', (event) => {
      window.addEventListener('mousemove', MYSTUFF.reportXY);
    test1();
});

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <title>connected</title>
        <style>     
        .small {
            position:absolute;
            width:7em;
            background-color:#e6ffe6;
            }
        .red {
            background-color:red;
            }
        </style>
        <script src="js/Q1.js"></script>
    </head>
<body>
<div id="chartCtnr"  style="text-align:center;">
    <div id="chartResz" class="resizeable" style="width:500px;height:500px;display:inline-block">
      <div id="chartScroll" style="overflow:auto;height:100%;width:100%;display:inline-block;">
        <div id="chartPosRef" class="freezer" style="position:relative">

                    <canvas id="connectedCanvas"  class="red" width="3718" height="2614" title="Track">This to draw the connected track</canvas>
                  <div id='div-0' class='small' style='top:100px;left:100px;'>this is div-0</div>
                  <div id='div-1' class='small' style='top:120px;left:080px;'>this is div-1</div>
                  <div id='div-2' class='small' style='top:140px;left:100px;'>this is div-2</div>
                  <div id='div-3' class='small' style='top:160px;left:080px;'>this is div-3</div>
        </div>
            </div>
        </div>
    </div>
<div id='msg'>this is a message</div>
</body>
</html>
javascript html drag-and-drop closures
1个回答
0
投票

问题是“关闭”不是关闭。现在,在更仔细地阅读https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures之后,此方法起作用了。请注意,dragStart(和其他几个变量)定义在“ draagger”的顶部(实际上,它们是makeDraggable,onDragStart等。)

[下一步(不是在这里,因为我怀疑是否有人在乎...)是添加所需的变量,以绘制将div连接到地图上点的线(此处不存在)。大多数是闭包变量,对其进行设置将几乎不增加拖动操作的开销,这几乎是本练习的重点。

setData('foo',target.id)仍然存在,因为我仍然想知道为什么文档将第一个参数称为“格式”。


var MYSTUFF = {
    dragger: function() {
    var dragThis;           // element being dragged
        var clickXY;      // click-position relative to ULC of scrolled area
        var elStartXY;    // Initial position of dragThis rel to ULC of scrolled area.
        var canvas; 
        return makeDraggable;

        function makeDraggable (el, elChart) {
        var ops = {capture:true, useCapture:true};
        dragThis = el;
        el.draggable = true;
        el.addEventListener('dragstart', onDragStart, ops);
        if (elChart.dataset.dragover === undefined) {
            elChart.addEventListener('dragover', onDragOver, ops);
            elChart.addEventListener('drop', onDrop, ops);
            elChart.dataset.dragover = 'dragover';  
        }
        return el;
    }

        function onDragStart(ev) {
      dragThis = ev.target;
        clickXY = MYSTUFF.pageXY(ev);
        elStartXY = {x:ev.target.offsetLeft, y:ev.target.offsetTop};
        ev.dataTransfer.setData('foo', ev.target.id);
    }

        function onDragOver(ev){
        var pos;                // new (style.top, style.left)
        var canvasid;           // canvas, if px, py exist
        var params, el;
        var foo;
        ev.preventDefault();
        pos = placeEl(ev,dragThis);
    }

        function onDrop(ev) {
        var canvasTemp, canvasid, ctx;
        var dT, params;
        var el, els;
        ev.preventDefault();
        placeEl(ev,dragThis);
        }

        function toStr() {
//  arguments => ;-delimited string.  Args must be scalar numbers.              
        var delim='';
        var s = "";
        for (var i = 0; i < arguments.length; i++) {
            if (isNaN(arguments[i])) {
                s += delim + arguments[i];
            } else {
                s += delim + arguments[i].toFixed(1);
            }
            delim = ";";
        }
        return s;
    }

        function placeEl(ev,el) {
/*  Re-position el by delta(mouse position)             */
        var params;
        var dx, dy;
        var pos;
        var cursorXY;
        cursorXY = MYSTUFF.pageXY(ev);
        dx = cursorXY.x - clickXY.x;
        dy = cursorXY.y - clickXY.y;
        pos = {x:elStartXY.x + dx, y:elStartXY.y + dy};
        el.style.left = pos.x + 'px';
        el.style.top =  pos.y + 'px';
        return pos;
    }
}, // end 'dragger'

    reportXY: function(ev) {
        let x, y, abs, sAbs;
        let msg = document.getElementById('msg');
        let el = ev.srcElement;
        let id = el.id;
        if (id === "") id = el.tagName;
        x = event.pageX.toFixed(0);
        y = event.pageY.toFixed(0);
        abs = MYSTUFF.pageXY(ev);
        sAbs = "(" + abs.x + "," + abs.y + ")";
        msg.innerText = "In " + id + ", cursor @ Page XY: (" + x + "," + y +").  Including scrolls, cursor @ " + sAbs;
    },

    pageXY:function(ev) {
        let x = ev.pageX;
        let y = ev.pageY;
        let scrollX, scrollY, tagName, el;

        el = ev.srcElement;
        tagName = el.tagName;
        scrollX = el.scrollLeft;
        scrollY = el.scrollTop;
        while (tagName !== 'HTML') {
            el = el.parentElement;
            tagName = el.tagName;
            scrollX += el.scrollLeft;
            scrollY += el.scrollTop;
        }
        return {x:x+scrollX, y:y+scrollY}
    }
}
/* test1() only tests makeDraggable.  It uses elements hardwired into the HTML.*/
function test1() {
    md = MYSTUFF.dragger();
    var elChart = document.getElementById('chartPosRef');
    var div = document.getElementById('div-0');

  md(div, elChart);
    div = document.getElementById('div-1');

    md(div, elChart);
    div = document.getElementById('div-2');
  md(div, elChart);

    div = document.getElementById('div-3');
  md(div, elChart);
}
window.addEventListener('DOMContentLoaded', (event) => {
      window.addEventListener('mousemove', MYSTUFF.reportXY);
    test1();
});
© www.soinside.com 2019 - 2024. All rights reserved.