2013-08-19 38 views
9

Tôi khá mới với D3.js và tôi đã chơi xung quanh với bố cục lực. Một trong những điều tôi đã thử là đặt nhãn lên các liên kết.Bố cục lực lượng D3.js - vị trí nhãn cạnh/xoay

Một cách để thực hiện điều này là bằng cách thêm svg:text và tính theo cách thủ công translate & rotate, hoạt động tốt với đường thẳng. Tuy nhiên, trong trường hợp khi liên kết là svg:path (ví dụ: cung), điều này không hoạt động như mong đợi. Trong những trường hợp này, svg:textPath là giải pháp được đề xuất.

Trong this demo, bạn có thể thấy triển khai đơn giản thêm nhãn vào liên kết thông qua svg:textPath. Vấn đề duy nhất với nó là, trong trường hợp khi nguồn được đặt ở bên phải của mục tiêu, văn bản được trả về theo hướng ngược lại (từ quan điểm của chúng ta, nó vẫn đúng từ quan điểm của đường dẫn). Câu hỏi của tôi là, làm thế nào để đối phó với điều này?

Giải pháp "chỉ" Tôi đưa ra là, tự đổi nguồn và nhắm mục tiêu trong trường hợp được mô tả ở trên. Here, bạn có thể thấy rằng nó gần như hoạt động.

enter image description here

Trong trạng thái khi hoán đổi xảy ra, bạn cũng có thể thấy hồ quang lật sang một bên khác, mà không nhìn bên phải. :(

+0

Bạn không thể chỉ định hướng văn bản cho 'textPath' - văn bản luôn theo hướng của đường dẫn. Vì vậy, giải pháp bạn có là giải pháp khả thi duy nhất. –

Trả lời

8

@LarsKotthoff là chính xác rằng textPath phải tuân theo hướng của đường dẫn. Trong trường hợp này, hướng của đường dẫn xác định không chỉ hướng cung, mà là phần đính kèm của điểm đánh dấu mũi tên ở cuối - điều này làm cho nó khó khăn để trao đổi hướng trên bay, vì bạn phải di chuyển các điểm đánh dấu quá

Giải pháp đơn giản (mặc dù có thể không phải là tốt nhất nếu bạn có một số lượng lớn các liên kết) là "bóng" đường dẫn liên kết thực với đường dẫn vô hình được sử dụng chỉ cho văn bản:

var link = svg.append("svg:g").selectAll("g.link") 
    .data(force.links()) 
    .enter().append('g') 
    .attr('class', 'link'); 

var linkPath = link.append("svg:path") 
    .attr("class", function(d) { return "link " + d.type; }) 
    .attr("marker-end", function(d) { return "url(#" + d.type + ")"; }); 

var textPath = link.append("svg:path") 
    .attr("id", function(d) { return d.source.index + "_" + d.target.index; }) 
    .attr("class", "textpath"); 

Bây giờ bạn có một con đường riêng biệt bạn có thể thao tác đúng cách. oticed, có hai vấn đề - bạn phải thay đổi hướng đường dẫn, và bạn phải thay đổi hướng vòng cung. Có vẻ như bạn có thể làm điều này trong chuỗi lệnh đường dẫn bằng cách hoán đổi giá trị sweep-flag (see docs), vì vậy thay vì Arx,ry 0 0,1 bạn có Arx,ry 0 0,0. Bạn có thể giảm một số trùng lắp mã bằng cách có một chức năng để tạo ra chuỗi đường dẫn:

function arcPath(leftHand, d) { 
    var start = leftHand ? d.source : d.target, 
     end = leftHand ? d.target : d.source, 
     dx = end.x - start.x, 
     dy = end.y - start.y, 
     dr = Math.sqrt(dx * dx + dy * dy), 
     sweep = leftHand ? 0 : 1; 
    return "M" + start.x + "," + start.y + "A" + dr + "," + dr + 
     " 0 0," + sweep + " " + end.x + "," + end.y; 
} 

Sau đó, bạn có thể cập nhật các đường liên kết và đường dẫn văn bản riêng biệt:

linkPath.attr("d", function(d) { 
    return arcPath(false, d); 
}); 

textPath.attr("d", function(d) { 
    return arcPath(d.source.x < d.target.x, d); 
}); 

Xem mã làm việc: http://jsfiddle.net/nrabinowitz/VYaGg/2/

+0

Không nên tạo nhiều hơn một nút cho mỗi phần tử dữ liệu trong một kết nối dữ liệu. Nó sẽ dẫn đến hành vi không mong muốn nếu/khi bạn cập nhật dữ liệu và thực hiện kết nối lần thứ hai. Dưới đây là một số chi tiết khác về lý do: http://stackoverflow.com/questions/10808320/can-enter-selection-be-reused-after-append-insert –

+0

Điểm được thực hiện, nhưng hoàn toàn có thể chấp nhận được nếu bạn không lập kế hoạch tự động cập nhật dữ liệu sau này - thường là trường hợp với biểu đồ mạng và OP không đề cập đến các cập nhật. Tôi sẽ cập nhật câu trả lời của mình, nhưng tôi không nghĩ rằng cách tiếp cận ban đầu là không chính xác, và tôi nghĩ rằng đó là hình thức nghèo để downvote chỉ vì bạn không thích cách tiếp cận. – nrabinowitz

+0

Bạn không chắc chắn nếu nó có hình thức kém hay không. Tôi vẫn đang cố gắng để có được một cảm giác bỏ phiếu trong SO. Lý do của tôi ở đây là, trong khi bạn nói đúng rằng làm công việc này về mặt kỹ thuật trong một ví dụ hạn chế, nó khuyến khích một thực hành mã hóa sẽ không hoạt động nói chung. Kinh nghiệm của tôi là việc tham gia dữ liệu là một trong những phần bị hiểu lầm nhiều nhất của d3 bởi những người mới vào thư viện, vì vậy tôi cảm thấy rằng câu trả lời đặc biệt nghiêm ngặt về việc hiển thị dữ liệu tham gia các kỹ thuật khuyến khích và thúc đẩy sự hiểu biết chung về cơ chế cơ bản như vậy. Hiển nhiên đó chỉ là ý kiến ​​của tôi thôi. –

Các vấn đề liên quan