【问题标题】:Manipulating dynamically created SVG elements操作动态创建的 SVG 元素
【发布时间】:2012-07-31 05:10:51
【问题描述】:

我试图能够使用 AJAX 从数据库中“拖动”从数据库加载的 SVG 元素(使用 Raphael)。我可以很好地加载它们并从数据库中显示它们,但是当我想为每个单独的事件处理程序添加事件处理程序时,我似乎无法正确处理。

当 DOM 准备好时,我尝试在从数据库加载所有元素后使用 .on():

$('circle').on("mousedown", function(event) {
        ox = event.screenX;
        oy = event.screenY;
        event.target.attr({opacity: .5});
        dragging = true;
    });

但这似乎永远不会被调用。

我可以在创建圆圈的过程中添加事件,但只有最后添加的元素实际移动——但前提是鼠标位于其他已加载圆圈的 X、Y 范围内:

var data = $.ajax({
    type: "POST",
    url: "map.php",
    data: "loadMap=1",
    success: function(text) {
        var item = text.split(";");
        for (x in item)
        {
            if (item[x].length > 0)
            {
                var str = item[x].split(",");
                if (str[0] == "node")
                {
                    var c = svg.circle(str[1], str[2], 10);
                    c.attr("id", str[3]);
                    c.attr("fill", "black");
                    c.attr("stroke", "none");

                    c.mousedown(function(event) {
                        ox = event.screenX;
                        oy = event.screenY;
                        c.attr({opacity: .5});
                        dragging = true;
                    });

                    c.mousemove(function(event) {
                    if (dragging) {
                        c.translate(event.screenX - ox, event.screenY - oy);
                        ox = event.screenX;
                        oy = event.screenY;
                        }
                    });

                    c.mouseup(function(Event) {
                        dragging = false;
                        c.attr({opacity: 1});
                    });

                }
                else if (str[0] == "room")
                {
                }
            }
        }
    }
});

我做错了什么,或者更好的是,解决这个问题的最佳方法是什么?

【问题讨论】:

    标签: jquery ajax svg


    【解决方案1】:

    根据圆圈的数量,为每个圆圈添加事件侦听器可能不是一个好主意。更强大的解决方案是将事件添加到 svg 元素

    $("#svgelement").on("mousedown", "circle", function(event){
            target = this;
            ox = event.screenX;
            oy = event.screenY;
            target.setAttribute('opacity', 0.5)
            dragging = true;
    });
    
    $("#svgelement").on("mousemove", function(event){
      if (dragging) {
          if(target) target.setAttribute('transform', 'translate('+ event.screenX - ox +','+  event.screenY - oy +')');
          ox = event.screenX;
          oy = event.screenY;
      }
    });
    
    //attached to the window, otherwise you might drag
    //all the way out of the svg and release there.
    $(window).on("mouseup", function(Event) {
       dragging = false;
       target.setAttribute('opacity', 1)
       target = false;
    });
    

    另一个好处是您不需要在 ajax 成功时将其加载为回调,因此您可以丢弃同步问题。

    【讨论】:

    • 这似乎运行良好(CPU 使用率下降......),但我不能再移动对象了。 .translate 不是 event.target 的函数,它是 Raphael.element 函数。我怎样才能以这种形式投射/获得它? Paper.getElementByPoint() 是我现在要去的方向,但我正在计算所有需要的偏移量。
    • 哦,我忘了你用的是拉斐尔。我不知道如何从 Dom 元素中获取 Raphael 对象,但是在纯 javascript 中执行此操作非常简单,答案已更新。
    • 谢谢。转换属性似乎是票。
    【解决方案2】:

    我认为错误可能是您从要附加到圆圈的鼠标事件处理程序中引用 c

    然后每个事件处理程序引用c所引用的对象,即最后一个对象。 event 带有一个 target 成员,您应该使用它。

    我使用的是 jQuerySVG,我使用的 event 成员是 currentTarget,看看你是否可以使用(我想是的)

    【讨论】:

    • 这是一个问题,但似乎我不能 .transform() 或 .translate() 或更改属性并让它们实际移动对象。我认为问题在于将 event.target 转换为 Raphael SVG 元素(或 JS 中的任何内容)。
    猜你喜欢
    • 2015-07-09
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多