2012-03-27 17 views
31

Tôi đang gặp sự cố khi hiểu các sự kiện D3 và chức năng gửi đi. Tôi có một ví dụ biểu đồ mà tôi đã làm việc trên gọi là: "Vertical Bar Charts With Legends."Cách thêm và sử dụng các sự kiện D3 đúng cách?

Vẽ biểu đồ và truyền thuyết đủ dễ dàng nhưng tôi muốn thêm khả năng đánh dấu mỗi thanh khi tôi di chuột qua chú giải văn bản tương ứng của nó, nằm ở bên phải biểu đồ.

Tôi đã đọc qua tất cả tài liệu sự kiện và thậm chí xem xét một số ví dụ, hầu hết trong số đó là khá phức tạp, nhưng dường như tôi đang thiếu điều gì đó. Có ai biết làm thế nào để thực hiện tốt nhất chức năng di chuyển chú giải văn bản gửi đi các sự kiện để tự động thay đổi màu sắc của các thanh dọc tương ứng?

Trả lời

60

Câu hỏi này tương tự như one you posted trong Nhóm Google d3-js. Nếu không sao chép những gì tôi đã viết ở đó, tôi sẽ nhắc lại rằng bạn có thể không muốn d3.dispatch; đó là dành cho abstractions sự kiện tùy chỉnh (chẳng hạn như bàn chải và hành vi). Việc sử dụng sự kiện gốc sẽ đơn giản hơn.

Nếu bạn muốn huyền thoại của bạn để thay đổi màu sắc của thanh tương ứng khi rê chuột, sau đó sự cố các vấn đề thành bước sau:

  1. Detect mouseover trên truyền thuyết.
  2. Chọn thanh tương ứng.
  3. Thay đổi màu tô của thanh.

Trước tiên, hãy sử dụng selection.on để nghe các sự kiện "di chuột" trên phần tử chú giải. Hàm listener của bạn sẽ được gọi khi chuột di chuyển qua phần tử chú giải và sẽ được gọi với hai đối số: dữ liệu (d) và chỉ mục (i). Bạn có thể sử dụng thông tin này để chọn thanh tương ứng qua d3.select. Cuối cùng, sử dụng selection.style để thay đổi kiểu "lấp đầy" bằng màu mới.

Nếu bạn không chắc chắn cách chọn thanh tương ứng trên di chuột chú giải, thường có một số tùy chọn. Cách đơn giản nhất là chọn theo chỉ mục, giả định rằng số lượng phần tử chú giải và số lượng các phần tử trực tiếp giống nhau, và chúng theo cùng thứ tự. Trong trường hợp đó, nếu một biến địa phương rect chứa các yếu tố rect, bạn có thể nói:

function mouseover(d, i) { 
    d3.select(rect[0][i]).style("fill", "red"); 
} 

Nếu bạn không muốn phải dựa vào chỉ số, tùy chọn khác là để quét cho thanh phù hợp dựa trên dữ liệu giống hệt nhau. Điều này sử dụng selection.filter:

function mouseover(d, i) { 
    rect.filter(function(p) { return d === p; }).style("fill", "red"); 
} 

Một tùy chọn khác là cung cấp cho mỗi rect một ID duy nhất, sau đó chọn theo id. Ví dụ, trên khởi tạo, bạn có thể nói:

rect.attr("id", function(d, i) { return "rect-" + i; }); 

Sau đó, bạn có thể chọn các rect bởi id trên mouseover:

function mouseover(d, i) { 
    d3.select("#rect-" + i).style("fill", "red"); 
} 

Ví dụ trên được trù định kể từ khi tôi sử dụng các chỉ số để tạo ra id thuộc tính (trong trường hợp này, nó đơn giản và nhanh hơn để sử dụng kỹ thuật đầu tiên chọn theo chỉ mục). Một ví dụ thực tế hơn sẽ là nếu dữ liệu của bạn có thuộc tính tên; sau đó bạn có thể sử dụng d.name để tạo thuộc tính id và tương tự chọn theo id. Bạn cũng có thể chọn bởi các thuộc tính hoặc lớp khác, nếu bạn không muốn tạo một id duy nhất.

+0

Hi Mike, cảm ơn vì tất cả sự giúp đỡ của bạn trên công cụ này. D3 là một công nghệ tuyệt vời và tôi đang tận hưởng thời gian của mình để học nó. - Frank –

+0

FWIW ví dụ này có thể được triển khai chỉ bằng cách thêm một quy tắc CSS: hover vào các phần tử SVG được đề cập. –

+1

@HerbCaudill A: quy tắc di chuột quá giới hạn trong trường hợp này: ví dụ này minh họa cách sửa đổi các phần tử khác với yếu tố được di chuột qua (ví dụ: chú giải tới thanh). Đ: quy tắc di chuột chỉ hoạt động nếu các yếu tố bạn muốn sửa đổi là các yếu tố tương tự được di chuột qua (ví dụ: chú giải). Xem câu trả lời khác của tôi về [chọn và sửa đổi các phần tử liên quan] (http://stackoverflow.com/questions/11206015/clicking-a-node-in-d3-from-a-button-outside-the-svg/11211391). – mbostock

6

Câu trả lời của Mike rất tuyệt.

tôi đã sử dụng nó đưa ra với điều này để lựa chọn một ô trong một mạng lưới tôi đã vẽ:

.on('click', (d, i) -> 
     console.log("X:" + d.x, "Y:" + d.y) #displays the cell x y location 
     d3.select(this).style("fill", "red"); 

Vì vậy, khi tôi đang nhập dữ liệu trong tôi thêm người nghe sự kiện và sử dụng d3.select (this) .

Xem mã trong bối cảnh dưới đây:

vis.selectAll("rect") 
    .data(singleArray) 
    .enter().append("svg:rect") 
    .attr("stroke", "none") 
    .attr("fill", (d) -> 
     if d.lifeForm 
     return "green" 
     else 
     return "white") 
    .attr("x", (d) -> xs(d.x)) 
    .attr("y", (d) -> ys(d.y)) 
    .attr("width", cellWidth) 
    .attr("height", cellHeight) 
    .on('click', (d, i) -> 
     console.log("X:" + d.x, "Y:" + d.y) 
     d3.select(this).style("fill", "red"); 
     return 
    ) 
Các vấn đề liên quan