3

我正在使用 d3js 拖动行为。这是演示。当我单击元素时,会触发“拖动”和“拖动”事件。即使我不尝试拖动它们,事件仍然会触发。我想在单击项目时调用其他一些函数。只有当我拖动项目时才应该触发拖动事件。那么如何在这里分离出拖动事件和点击事件。

function onDragDrop(dragHandler, dropHandler) {
    var drag = d3.behavior.drag();

drag.on("drag", dragHandler)
.on("dragend", dropHandler);
return drag;
}

  var d = [{ x: 20, y: 20 }];

    var g = d3.select("body").select("svg").data(d).append("g").attr("transform", function (d) { return        "translate(" + d.x + "," + d.y + ")"; })
     .call(onDragDrop(dragmove, dropHandler));

g.append("rect")
.attr("width", 40)
.attr("height", 40)
.attr("stroke", "red")
.attr("fill","transparent")
.attr("x", "20" )
.attr("y", "20")

g.append("text")
.text("Any Text")
.attr("x", "20" )
.attr("y", "20")

function dropHandler(d) {
    alert('dropped');
}

function dragmove(d) {
  alert('dragged');
  d.x += d3.event.dx;
  d.y += d3.event.dy;
  d3.select(this).attr("transform", "translate(" + d.x + "," + d.y + ")");
 }
4

2 回答 2

2

EDIT 3

This is in response to your alternate answer post. The fiddle you posted there does not accurately reflect the solution I was trying to describe. I updated it. The fiddle below should be an example of the correct way to differentiate click and "true" dragend events. Note that we are not using a "click" handler.

http://jsfiddle.net/V92CF/

EDIT 2

Ok, I posted this question on the d3 google group and got an answer from Jason Davies. The behavior we're seeing is the intended behavior, it's not a bug. A "click" is simply considered a trival (0 pixels moved) drag, but it is still a drag. Mike, the creator of d3, explains the reasoning here:

https://github.com/mbostock/d3/pull/368

Hence the correct solution to your problem is the one I described as a hack before: You need to detect if a movement has actually been made inside your dragend handler, and then only trigger your logic if it has.

EDIT

Please note my original answer below is wrong. I had misunderstood the problem. The comments below and my edit to the OP should clarify

Original Post Below

The only problem here is using alert. I changed all the alerts to console.logs and it works fine:

http://jsfiddle.net/TrWw3/

I think it's getting confused with the alerts because as soon as you start dragging, it fires the alert box, which requires you to close it. But then by the time you've closed it the mouse has jumped, and something about the process is messing things up.

Anyway, console.log with chrome or firefox js console open will fix you up nice.

于 2013-04-17T22:49:01.463 回答
1

由于我没有得到预期的答案,所以我提供了一个替代方案来实现这一点。希望有人对此有一些答案。再次感谢@jonah。如果您发现这方面的任何更新,请告诉我。这是执行此操作的替代方法

  var d = [{ x: 20, y: 20 }];
  var flag = false;

  var g = d3.select("svg").data(d).append("rect")
    .attr("width", 40)
    .attr("height", 40)
    .attr("stroke", "red")
    .attr("fill","transparent")
    .attr("x", "20" )
    .attr("y", "20")
    .on("click", function(){ console.log('clicked');})
   .call(d3.behavior.drag().on("drag", dragHandler).on("dragend", dropHandler))

 function dropHandler(d) {
       if(flag){
            console.log('dropped');
            flag = false;
        }}

 function dragHandler(d) {
        flag = true;
        console.log('dragged');
        d.x += d3.event.dx;
        d.y += d3.event.dy;
        d3.select(this).attr("transform", "translate(" + d.x + "," + d.y + ")");
    }
于 2013-04-19T06:46:47.180 回答