2013-02-04 12 views
10

Tôi có một ô phân tán được tạo bằng D3. Điểm (vòng tròn SVG) trên ô có thể được chọn bằng cách nhấp vào chúng và các vùng có thể được chọn bằng cách sử dụng bàn chải D3.Xử lý sự kiện hạt mịn với cọ D3

Để đảm bảo vòng kết nối nhận được sự kiện nhấp, tôi cần tạo bàn chải trước để các vòng tròn ở trên đó. Thật không may điều này có nghĩa là tôi không thể kéo để tạo ra mức độ cọ vẽ khi con trỏ của tôi vượt quá một điểm trong cốt truyện.

Có cách nào để chuyển các sự kiện di chuột và nhấp vào vòng kết nối hay không nhưng xử lý các sự kiện liên quan đến kéo bằng cọ vẽ?

Trả lời

13

Nó có thể được thực hiện nhưng với use of the D3 brush API (Xem lưu ý dưới đây).

Đây là một ví dụ http://bl.ocks.org/4747894 nơi:

  1. Yếu tố brushđằng sau các vòng tròn
  2. Các vòng tròn đáp ứng với sự kiện mousedown. (Có thể trả lời các sự kiện khác.)
  3. Phần tử brush được xử lý tốt ngay cả khi kéo bắt đầu từ bên trong một trong các vòng kết nối.

Một số tracing và nhìn vào D3 source code gợi ý rằng extent không được thiết lập lại đúng khi một sự kiện mousemove được bắn từ một yếu tố circle trên đỉnh bàn chải. Điều đó có thể được cố định bằng cách đặt lại extent cho bàn chải trong mousedown listener cho circle yếu tố:

 circles.on("mousedown", function (d, i) { 
      // _svg_ is the node on which the brush has been created 
      // x is the x-scale, y is the y-scale 
      var xy = d3.mouse(svg.node()), 
       xInv = x.invert(xy[0]), 
       yInv = y.invert(xy[1]); 

      // Reset brush's extent 
      brush.extent([[xInv, yInv], [xInv, yInv]]); 

      // Do other stuff which we wanted to do in this listener 
     }); 

Lưu ý:As per the API, lựa chọn của bàn chải sẽ không được làm mới tự động trên gọi .extent(values). Chỉ cần nhấp vào một vòng kết nối sẽ đặt lại số extent nhưng sẽ không vẽ lại lựa chọn được thực hiện. Lựa chọn sẽ chỉ bị hủy khi một lựa chọn khác được bắt đầu bên trong circle hoặc bằng cách nhấp vào bên ngoài vòng kết nối và lựa chọn hiện tại. Đây là hành vi mong muốn, như tôi đã hiểu từ câu hỏi. Tuy nhiên, điều này có thể phá vỡ mã được viết với giả định rằng bất cứ điều gì là extent của bàn chải sẽ là lựa chọn hiển thị trên biểu đồ.

+0

Điều này rất gần. Lý tưởng nhất, tôi muốn có thể kéo bàn chải xung quanh sau khi nó được tạo ra, ngay cả khi tôi bắt đầu trên một vòng tròn, nhưng nó là một bước tiến lớn về cách nó làm việc ngay bây giờ! – RichH

+0

Thật vậy, tôi thấy rằng việc kéo lựa chọn từ bên trong một '' vẫn không thể thực hiện được. Tôi sẽ suy nghĩ về làm thế nào để làm sạch nó, mặc dù tôi nghi ngờ rằng làm một sự kiện sạch sẽ đi qua sẽ liên quan đến một bản vá cho d3. –

5

Sử dụng selection.on: http://jsfiddle.net/NH6zD/1

var target, 
    dimensions = {width: 200, height: 200}, 
    svg = d3.select("body").append("svg").attr(dimensions), 
    rect = svg.append("rect").attr(dimensions); // Must be beneath circles 
svg 
    .on("mousedown", function() { 
     target = d3.event.target || d3.event.srcElement; 
     if (target === rect.node()) { 
      /* Brush */ 
     } else { 
      /* Circle */ 
     } 
    }) 
    .on("mousemove", function() { 
     if (!target) return; 
     if (target === svg.rect()) { 
      /* Brush */ 
     } else { 
      var mouse = d3.mouse(svg.node()); 
      target.attr({x: mouse[0], y: mouse[1]}); 
     } 
    }); 
(function(exit) { 
    for (var i in exit) svg.on(exit[i], function() { target = undefined; }); 
})(["mouseout", "mouseup"]);