我正在使用d3js来显示网站视图的实时表示.为此,我使用堆栈布局,我现在更新我的数据集
JSON.
当在y轴上仅显示1或2个视图时,与图中的视图量相关,动态相关,轴标签为:1 => 0,0.2,0.4,0.6,0.8,1,轴标号是:2 => 0,0.5,1.5,2这对我的数据集是没有意义的,因为它显示页面的视图,你不能有一半的视图.
我在d3js中有一个线性刻度我基于我的y轴
var y_inverted = d3.scale.linear().domain([0,1]).rangeRound([0,height]);
根据the documentation of rangeRound(),我只能从这个规模中获得整体价值.为了绘制我的轴我使用:
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));
因为它是一个实时应用程序,我每秒通过调用更新:
function update(){ y_inverted.domain([yStackMax,0]); y_axis.transition() .duration(interval) .ease("linear") .call(y_inverted.axis); }
yStackMax是从stacklayout计算出来的,只要我知道用于y值的数据只包含整数.
var yStackMax = d3.max(layers,function(layer) { return d3.max(layer,function(d) { return d.y0 + d.y; }); });
我已经尝试了几件事来为我的y轴获得正确的值.
d3.svg.axis() .scale(y_inverted) .orient("left") .ticks(5).tickFormat(d3.format(",.0f"))
得到我最近的沙发,但它仍然显示0,1
基本上我想要的是,当yStackMax为1时,只有1个tick,当它为2时有2个tick,但是如果yStackMax是12或1,000,它也应该有效
解决方法
简短的答案:您可以动态设置滴答数.将其设置为1,仅显示两个刻度标签:
var maxTicks = 5,minTicks = 1; if (yStackMax < maxTicks) { y_axis.ticks(minTicks) } else { y_axis.ticks(maxTicks) }
长回答(稍微偏离主题):
在使用你的例子时,我想出了一个相当“完整的解决方案”的所有格式化问题.随意使用它:)
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,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)
您可以与此HTML代码片段一起尝试:
<!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>
我知道这是一个有点偏离的话题,但我通常喜欢提供运行的例子/解决方案.注意附加格式化的东西作为实际问题的奖金.