d3.event.x没有获得x光标的位置

时间:2015-04-16 22:42:21

标签: d3.js


当我使用d3.behavior.drag()时,我不明白为什么d3.event.x == NaN而不是x光标的位置。 我使用了d3.event.sourceEvent.offsetX,但它仅适用于Chrome(例如不适用于Firefox)。 副作用可以在这里看到: http://gloumouth1.free.fr/test/Nature 用户只能使用Chrome移动“频率游标” 有什么想法?
-G。

1 个答案:

答案 0 :(得分:9)

从我的观点来看,d3.js是一个可怕的文档库。抱歉Mike Bostock,但就我个人来说,有时候绝对不可能找到"为什么",而无需调试源和示例。

现在,答案是:

第一次

d3可以在任何浏览器中正确创建和识别d3.event.x等自己的事件,但是你应该绘制可拖动的界面元素 INSIDE <g></g>!您不应该在<svg></svg>中精确放置圆圈,矩形或其他任何内容。这没有记录。

示例:

<svg>
   <rect></rect>  // you can not use 'd3.event.x' or 'd3.event.y' for this element.
                  // for this element is possible to use 'd3.event.sourceEvent.x' in Chrome 
                  // and 'd3.event.sourceEvent.offsetX' in Firefox.
                  // d3.event.x === NaN, d3.event.y === NaN in any browser
   <g>
      <rect></rect> //  'd3.event.x' and 'd3.event.y' will work for this element
   </g>
<svg>

第二次

<g></g>包装器应存储data([{x:..., y:...}]),即使您不需要它。如果没有<g></g>中的数据,.origin()方法将无法正常工作,并且元素将在窗口上的光标下无法预测地跳转。

<强>最后

让我们在一个例子中结合所有关于拖动的知识:

    var draggable = d3.behavior.drag()
            .origin(Object) // the sequence function(d){return(d);} in not necessary 
            .on("drag", drg);

    var board = d3.select("body").append("svg:svg").attr({width: 500, height: 500});
    var wrap = board.append("svg:g")
            .data([{x: 100, y: 100}]); // this is the coordinates of draggable element
                                       // they should be stored in <g></g> wrapper as the data

// IMPORTANT! There is no wrap.data().enter() sequence
// You should not call .enter() method for <g></g> data,
// but nested elements will read the data() freely 

    var handle = wrap.append("svg:circle")
            .attr({
                cx: function(d){return(d.x);}, // position of circle will be stored in the data property of <g> element
                cy: function(d){return(d.x);}, 
                r: 30, 
                fill: "gray", 
                stroke: "black"
            }).call(draggable);

    function drg(d){
        // now d3.event returns not a mouse event, 
        // but Object {type: "drag", x: ..., y: ..., dx: ..., dy: ...}
        d3.select(this).attr({
            // reposition the circle and
            // update of d.x, d.y
            cx: d.x = Math.max(0, Math.min(500 - 60, d3.event.x)), // 500 - width of svg, 60 - width of circle  
            cy: d.y = Math.max(0, Math.min(500 - 60, d3.event.y))  // 500 - height of svg, 60 - height of circle
        });        
    }

DEMO:http://jsfiddle.net/c8e2Lj9d/4/