2012-11-22 29 views
10

Tôi đang sử dụng d3j để hiển thị đại diện thời gian thực cho lượt xem trang web. Đối với điều này, tôi sử dụng bố cục ngăn xếp và tôi cập nhật tập dữ liệu của mình bằng JSON tại thời điểm này.Chỉ hiển thị toàn bộ giá trị dọc theo trục y trong d3.js khi phạm vi là 0-1 hoặc 0-2

Khi chỉ có 1 hoặc 2 chế độ xem được hiển thị trên trục y, động liên quan đến số lượt xem trong biểu đồ, nhãn trục là: 1 =>0, 0.2, 0.4, 0.6, 0.8, 1, nhãn trục là: 2 =>0, 0.5, 1, 1.5, 2 Điều này không có ý nghĩa đối với tập dữ liệu của tôi vì số liệu này hiển thị lượt xem trang và bạn không thể có một nửa lượt xem.

Tôi có một quy mô tuyến tính trong d3js tôi căn trục y của tôi trên

var y_inverted = d3.scale.linear().domain([0, 1]).rangeRound([0, height]); 

Theo the documentation of rangeRound() tôi chỉ sẽ nhận được toàn bộ giá trị ra khỏi quy mô này. Đối với bản vẽ trục của tôi, tôi sử dụng:

var y_axis = svg.append("g") 
    .attr("class", "y axis") 
    .attr("transform", "translate(0,0)") 
    .call(y_inverted.axis = d3.svg.axis() 
     .scale(y_inverted) 
     .orient("left") 
     .ticks(5)); 

Bởi vì nó là một ứng dụng thời gian thực để cập nhật này mỗi giây bằng cách gọi:

function update(){ 
    y_inverted.domain([yStackMax, 0]); 
    y_axis.transition() 
     .duration(interval) 
     .ease("linear") 
     .call(y_inverted.axis); 
} 

yStackMax được tính từ một stacklayout, như xa như tôi biết các dữ liệu sử dụng cho các giá trị y chỉ chứa số nguyên.

var yStackMax = d3.max(layers, function(layer) { 
    return d3.max(layer, function(d) { 
     return d.y0 + d.y; 
    }); 
}); 

Tôi đã thử một vài cách để có được giá trị thích hợp cho trục y của tôi.

d3.svg.axis() 
    .scale(y_inverted) 
    .orient("left") 
    .ticks(5).tickFormat(d3.format(",.0f")) 

Got me gần nhất sofar, nhưng nó vẫn hiển thị 0, 0, 0, 1, 1, 1

Về cơ bản những gì tôi muốn là chỉ có 1 đánh dấu khi yStackMax là 1, 2 ve khi đã ghi bàn 2, nhưng nó cũng sẽ làm việc nếu yStackMax là 12 hoặc 1.000.000

+0

btw, nếu bạn đang hạnh phúc với một trong những câu trả lời, xin vui lòng chấp nhận nó. – Juve

Trả lời

10

Câu trả lời ngắn: Bạn có thể tự động đặt số lượng bọ ve. Đặt nó vào 1 để chỉ hiển thị hai nhãn đánh dấu:

var maxTicks = 5, minTicks = 1; 
if (yStackMax < maxTicks) { 
    y_axis.ticks(minTicks) 
} 
else { 
    y_axis.ticks(maxTicks) 
} 

dài trả lời (đi một chút off topic): Trong khi chơi với ví dụ của bạn tôi đã đưa ra một "giải pháp hoàn chỉnh" chứ không phải cho tất cả các định dạng của bạn các vấn đề. Hãy sử dụng nó :)

var svg = d3.select("#svg") 
var width = svg.attr("width") 
var height = svg.attr("height") 
var yStackMax = 100000 
var interval = 500 
var maxTicks = 5 
var minTicks = 1 

var y_inverted = d3.scale.linear().domain([0, 1]).rangeRound([0, height]) 
var defaultFormat = d3.format(",.0f") 

var format = defaultFormat 

var y_axis = d3.svg.axis() 
    .scale(y_inverted) 
    .orient("left") 
    .ticks(minTicks) 
    .tickFormat(doFormat) 

var y_axis_root; 
var decimals = 0; 

function countDecimals(v){ 
    var test = v, count = 0; 
    while(test > 10) { 
     test /= 10 
     count++; 
    } 
    return count; 
} 

function doFormat(d,i){ 
    return format(d,i) 
} 

function init(){ 
    y_axis_root = svg.append("g") 
     .attr("class", "y axis") 
     // I modified your example to move the axis to a visible part of the screen 
     .attr("transform", "translate(150,0)") 
     .call(y_axis) 
} 

// custom formatting functions: 
function toTerra(d) { return (Math.round(d/10000000000)/100) + "T" } 
function toGiga(d) { return (Math.round(d/10000000)/100) + "G" } 
function toMega(d) { return (Math.round(d/10000)/100) + "M" } 
function toKilo(d) { return (Math.round(d/10)/100) + "k" } 

// the factor is just for testing and not needed if based on real world data 
function update(factor){ 
    factor = (factor) || 0.1; 
    yStackMax*=factor 
    decimals = countDecimals(yStackMax) 
    console.log("yStackMax decimals:",decimals, factor) 
    if  (yStackMax < maxTicks) { 
     format = defaultFormat 
     y_axis.ticks(minTicks) 
    } 
    else { 
     y_axis.ticks(maxTicks) 
     if  (decimals < 3) format = defaultFormat 
     else if(decimals < 6) format = toKilo 
     else if(decimals < 9) format = toMega 
     else if(decimals < 12) format = toGiga 
     else     format = toTerra 
    } 

    y_inverted.domain([yStackMax, 0]); 
    y_axis_root.transition() 
     .duration(interval) 
     .ease("linear") 
     .call(y_axis); 
} 

init() 
setTimeout(update, 200) 
setTimeout(update, 400) 
setTimeout(update, 600) 

Bạn có thể thử nó cùng với đoạn mã html này:

<!DOCTYPE html> 
<html> 
    <head> 
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
     <script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.js"></script> 
    </head> 

    <body> 
     <div><svg id="svg" width="200" height="300"></svg></div> 
     <script src="axis.js"></script> 
     <button id="button1" onclick="update(10)">+</button> 
     <button id="button2" onclick="update(0.1)">-</button> 
    </body> 
</html> 

Tôi biết nó là một chút off topic nhưng tôi thường muốn cung cấp chạy ví dụ/giải pháp. Xem xét các công cụ định dạng bổ sung làm tiền thưởng cho vấn đề thực tế.

5

Nếu bạn yêu cầu một số lượng bọ ve nhất định (qua trục.ticks()) thì d3 sẽ cố gắng cung cấp cho bạn nhiều dấu tích - nhưng sẽ cố gắng sử dụng các giá trị đẹp. Nó không liên quan gì đến dữ liệu của bạn.

Giải pháp của bạn là sử dụng tickFormat, để làm tròn tất cả các giá trị thành giá trị nguyên, chỉ yêu cầu một đánh dấu là Juve trả lời hoặc đặt giá trị đánh dấu bằng cách sử dụng axis.tickValues([...]). d3.range

phạm viRound sẽ không giúp ích trong trường hợp này vì nó liên quan đến phạm vi đầu ra của thang đo, trong trường hợp này là độ lệch pixel đối với lô tại: giữa 0 và chiều cao.

4

Tắt câu trả lời của Superboggly, đây là những gì phù hợp với tôi. Trước tiên tôi nhận được tối đa số (lớn nhất) từ miền y sử dụng y.domain().slice(-1)[0] và sau đó tôi đã xây dựng một loạt các giá trị đánh dấu từ đó sử dụng d3.range() ...

var y_max = y.domain().slice(-1)[0] 
    var yAxis = d3.svg.axis() 
     .scale(y) 
     .tickValues(d3.range(y_max+1)) 
     .tickFormat(d3.format(",.0f")) 
3

Hoặc chỉ cần để cho các ve như họ đang có và "ẩn" số thập phân

d3.svg.axis() 
    .scale(y_inverted) 
    .orient("left") 
    .ticks(5).tickFormat(function(d) { 
       if (d % 1 == 0) { 
       return d3.format('.f')(d) 
       } else { 
       return "" 
       } 
      }); 
1

đây là mã:.

var yAxis = d3.svg.axis() 
    .scale(y) 
    .orient("left") 
    .tickFormat(d3.format(".2s")); 
Các vấn đề liên quan