使用模块模式的变体来附加 javascript 事件

Issue attaching javascript events using variation on module pattern

我正在尝试使用 "module pattern" 中的代码将 Javascript 事件附加到 SVG 元素。我是 Javascript 的新手,我相信下面的代码会证明这一点。我试图使用我实际使用的代码的更简单版本来重现这种情况。具有讽刺意味的是,我实际上离让它与这个例子一起工作还很遥远,但我的大脑因为试图让它工作和研究这个网站的其他地方而受到伤害。所以,我正在联系所有聪明的人,看看他们是否能提供帮助。我遇到的问题(当我让它工作时!)是 Javascript 事件似乎没有绑定到 DOM 元素并且只是在页面加载时触发。当我再次触发事件时(通过移动鼠标),我收到由 D3 库引起的 Javascript 错误:

"Uncaught TypeError: n.apply is not a function"

如果有人能够克服重新创建模块模式的匆忙努力并让这个示例工作 - 希望我能够将它合并到我的实际代码中(示例和实际代码之间唯一真正的区别是有一堆 "extender" 模块,而不是所有东西都在一个里。

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
    <div id="box1"></div>
    <div id="box2"></div>

    <script>

        function mouseOver(i) {
            return this.targets[i].select("#" + this.targets[i].container).select("circle").attr("fill", "blue");
        }

        function mouseOut(i) {
            return this.targets[i].select("#" + this.targets[i].container).select("circle").attr("fill", "green");
        }

        var example = (function () {

            return {

                addRect: function addRect(container) {
                    this.box = d3.select("#" + container).append("svg");

                    this.rect = this.box.append("rect")
                        .attr({
                            "fill": "red",
                            "width": 50,
                            "height": 50,
                        });

                },

                addCircle: function addControl(targets) {
                    this.targets = targets

                    for (target in this.targets) {
                        tt = this.targets[target]

                        tt.circle = tt.box.append("circle")
                            .attr({
                                "fill": "green",
                                "cx": -10,
                                "cy":-10,
                                "r": 10,
                                "transform": "translate(30,30)"
                            })
                    };
                },

                addControl: function addControl(targets) {
                    this.targets = targets

                    for (target in this.targets) {
                        tt = this.targets[target]

                        tt.control = tt.box.append("rect")
                            .attr({
                                "fill": "none",
                                "width": 50,
                                "height": 50,
                            })
                            .on("mouseover", mouseOver(target))
                            .on("mouseout", mouseOut(target))
                    };  

                },

            };
        })();


        var first = new example.addRect("box1");
        var second = new example.addRect("box2");

        var circs = new example.addCircle([first, second]);
        var controls = new example.addControl([first, second]);


    </script>
</body>
</html>

问题1: 页面加载时触发事件

原因:

你正在做

.on("mouseover", mouseOver(target)) //this is wrong the second parameter should have been a function.

像这样

.on("mouseover", function(){mouseOver(target)})

问题 2:

tt.control = tt.box.append("rect")
                            .attr({
                                "fill": "none",//this should not be none else mouse over will not work as you expect
                                "width": 50,
                                "height": 50,
                            })
                            .on("mouseover", mouseOver(target))
                            .on("mouseout", mouseOut(target))

它应该用不透明度 0 来完成,这样它就看不见了

for (target in this.targets) {
            tt = this.targets[target]
            tt.control = tt.box.append("rect")
              .attr({
                "fill": "blue",
                "width": 50,
                "height": 50,
                "opacity": 0
              })

问题 3:

您可以将参数设置为 DOM 而不是在函数中传递它。 像这样

  for (target in this.targets) {
    tt = this.targets[target]
    tt.control = tt.box.append("rect")
      .attr({
        "fill": "blue",
        "width": 50,
        "height": 50,
        "opacity": 0
      })

      .on("mouseover", function() {
        mouseOver(tt)
      })
      .on("mouseout", function() {
        mouseOut(tt)
      });
      tt.control.node().dataset = tt;//binding the data to the dom
  };

然后在鼠标事件中像这样获取绑定对象:

function mouseOver(target) {
      //gettting the data from the dom
      event.target.dataset.circle.attr("fill", "blue");
    }

    function mouseOut(target) {
      event.target.dataset.circle.attr("fill", "green");
    }

工作代码here.