2012-11-13 21 views
14

Sử dụng thư viện đồ họa d3, tôi dường như không thể vẽ đường đi chậm để chúng có thể được nhìn thấy ngày càng tăng.Không thể làm cho các đường dẫn vẽ chậm dần với D3

This site có ví dụ hoàn hảo trong phần "Biểu đồ đường kẻ (Bỏ lưu trữ)", nhưng không có mã nào được cung cấp cho phần đó. Ai đó có thể giúp tôi với các dòng mã D3 mà có thể làm cho điều đó xảy ra?

Khi tôi thử thêm trễ() hoặc thời lượng() chẳng hạn như trong đoạn mã sau, đường dẫn vẫn vẽ ngay lập tức và tất cả mã SVG sau phân đoạn này không hiển thị.

var mpath = svg.append ('path'); 
     mpath.attr ('d', 'M35 48 L22 48 L22 35 L22 22 L35 22 L35 35 L48 35 L48 48') 
      .attr ('fill', 'none') 
      .attr ('stroke', 'blue') 
      .duration (1000); 
+2

Mã ví dụ mà : http://blog.visual.ly/wp-content/uploads/2012/06/transitions.html#13 ... nevermind, khi tôi chạy nó thông qua http://jsbeautifier.org/ tôi có thể thấy rằng việc triển khai là ngu ngốc – nrabinowitz

+0

Wow. Ba giải pháp khác nhau, nhưng chỉ có thể kiểm tra một giải pháp. Cảm ơn bạn nrabinowitz, Duopixel và btel! – tgoneil

Trả lời

17

Tôi tin rằng "Cách D3" để làm điều này là với chức năng tùy chỉnh tween. Bạn có thể thấy một thực hiện làm việc ở đây: http://jsfiddle.net/nrabinowitz/XytnD/

này giả định rằng bạn có một máy phát điện gọi là line thiết lập với d3.svg.line để tính toán đường dẫn:

// add element and transition in 
var path = svg.append('path') 
    .attr('class', 'line') 
    .attr('d', line(data[0])) 
    .transition() 
    .duration(1000) 
    .attrTween('d', pathTween); 

function pathTween() { 
    var interpolate = d3.scale.quantile() 
      .domain([0,1]) 
      .range(d3.range(1, data.length + 1)); 
    return function(t) { 
     return line(data.slice(0, interpolate(t))); 
    }; 
}​ 

Chức năng pathTween đây trả về một người xen vào mà phải mất một lát cho của dòng, được xác định bởi khoảng cách chúng ta đang trải qua quá trình chuyển đổi và cập nhật đường dẫn tương ứng. Tuy nhiên, điều đáng chú ý là tôi nghi ngờ bạn sẽ có hiệu suất tốt hơn và hoạt hình mượt mà hơn bằng cách lấy tuyến đường dễ dàng: đặt hình chữ nhật màu trắng (nếu nền của bạn đơn giản) hoặc clipPath (nếu nền của bạn phức tạp) trên đường dây, và chuyển nó sang bên phải để lộ dòng bên dưới.

+0

Điều này chắc chắn trông giống như cách d3, nhưng nếu bạn làm chậm hoạt ảnh thì đường dẫn sẽ được nối, không hoạt ảnh (ít nhất là trong Chrome). – Duopixel

+0

Cảm ơn bạn, tôi đánh giá cao điều đó! – tgoneil

+3

Có, làm động tác chỉnh sửa để phát hiện ra dòng có thể sẽ tốt hơn cho hiệu suất. Các đường dẫn clip đơn giản cũng sẽ cung cấp hiệu suất tốt trong hầu hết các trường hợp, không rõ ràng nếu nó sẽ tốt hơn việc tinh chỉnh đường dẫn (thử và xem, các triển khai có thể sẽ khác một chút về điều này). –

1

Dựa trên các bài đăng mà bạn liên kết đến, tôi đã đưa ra ví dụ sau:

var i = 0, 
    svg = d3.select("#main"); 

String.prototype.repeat = function(times) { 
    return (new Array(times + 1)).join(this); 
} 

segments = [{x:35, y: 48}, {x: 22, y: 48}, {x: 22, y: 35}, {x: 34, y:35}, {x: 34, y:60}]; 
line = "M"+segments[0].x + " " + segments[0].y 

new_line = line + (" L" + segments[0].x + " " + segments[0].y).repeat(segments.length); 
var mpath = svg.append ('path').attr ('d',new_line) 
      .attr ('fill', 'none') 
      .attr ('stroke', 'blue') 

for (i=0; i<segments.length; i++) 
    { 
    new_segment = " " + "L"+segments[i].x + " " + segments[i].y 
    new_line = line + new_segment.repeat(segments.length-i) 
    mpath.transition().attr('d',new_line).duration(1000).delay(i*1000); 
    line = line + new_segment 

    } 

Nó là một chút xấu xí, nhưng hoạt động. Bạn có thể thấy nó trên jsFiddle

+0

Cảm ơn bạn, tôi đánh giá cao điều đó! – tgoneil

46

Một mô hình phổ biến khi dòng hiệu ứng động trong svg là thiết lập một stroke-dasharray chiều dài của con đường và sau đó làm động stroke-dashoffset:

var totalLength = path.node().getTotalLength(); 

path 
    .attr("stroke-dasharray", totalLength + " " + totalLength) 
    .attr("stroke-dashoffset", totalLength) 
    .transition() 
    .duration(2000) 
    .ease("linear") 
    .attr("stroke-dashoffset", 0); 

Bạn có thể thấy một bản demo ở đây: http://bl.ocks.org/4063326

+3

Điều này có thể thực hiện với d3.svg.area không?Cho đến nay tôi đã không thành công – mike

+0

Lời khuyên: thay vì 'path.node.getTotalLength()' bạn nên có 'path.attr ('stroke-dashoffset', function() {return this.getTotalLength();})' Nếu không, nếu 'đường dẫn' được chọn qua nhiều điểm dữ liệu,' totalLength' sẽ chỉ là độ dài của 'đường dẫn' đầu tiên mà bạn đang vẽ. Tiếp theo 'path' sẽ sinh động rất lạ. –

+2

+1 Rất thích xem phiên bản cho 'd3.svg.area'. – Baz

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