【问题标题】:Reduce number of ticks for log-scale in nvd3 line chart减少 nvd3 折线图中对数刻度的刻度数
【发布时间】:2017-05-20 09:02:59
【问题描述】:

我正在使用nvd3 来生成折线图。我想要 y 轴的 log-scale。 为此,我使用以下代码:

const chart = nv.models.lineChart()
    .x(function (d) { return d[0] })
    .y(function (d) { return d[1] })
    .margin({ left: 100 })  
    .useInteractiveGuideline(true)
    .showLegend(true)       
    .showYAxis(true)        
    .showXAxis(true);

chart.xAxis.tickFormat(d3.format(',r'));
chart.yAxis.tickFormat(d3.format('.02f'));
chart.yScale(d3.scale.log());

我得到的结果如下:

有没有办法减少 y 轴的刻度数,使它们不重叠?或者有没有我可以用来合理地生成刻度的库?我想避免手动设置tickValues

【问题讨论】:

    标签: javascript d3.js data-visualization nvd3.js


    【解决方案1】:

    有一种简单的方法可以使用 .ticks() 方法指定显示的刻度数。 D3.js v3 API documentation for axis.ticks() 状态:

    合适的参数取决于相关的比例:对于线性比例,您可以指定一个滴答计数,例如axis.ticks(20);对于对数刻度,您可以同时指定计数和刻度格式;...

    这似乎适用于 D3.js 中的对数刻度,

    var nTicks = 10;
    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom")
        .ticks(nTicks, d3.format('.02f'))
        .tickSize(6, 0);
    

    但不在 NVD3.js 中

    在此处查看 D3.js Log Axis example 的工作修改 sn-p:

    var margin = {top: 210, right: 20, bottom: 220, left: 20},
        width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;
    
    var x = d3.scale.log()
        .domain([.0124123, 1230.4])
        .range([0, width]);
    
    var nTicks = 10;
    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom")
        .ticks(nTicks, d3.format('.02f'))
        .tickSize(6, 0);
        
    var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.right + margin.bottom)
      .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
    svg.append("g")
        .attr("class", "x axis")
        .call(xAxis);
    .axis text {
      font: 10px sans-serif;
    }
    
    .axis path,
    .axis line {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }
    <script src="//d3js.org/d3.v3.min.js"></script>

    我在 NVD3.js 中对它进行了一些修改,但没有运气:

    const chart = nv.models.lineChart()
        .margin({ left: 150 })  
        .useInteractiveGuideline(true)
        .showLegend(true)       
        .showYAxis(true)        
        .showXAxis(true);
    
    var logScale = d3.scale.log();
    chart.yScale(logScale);
    chart.xAxis.tickFormat(d3.format(',r'));
    var nTicks = 6;
    chart.yAxis.ticks(nTicks);
    //chart.yAxis.tickFormat(d3.format('.02f'));
    
    var myData = generateValues();
    d3.select('.chart')
          .datum(myData) 
          .call(chart);   
    
    function generateValues() {
      var valuesGenerated = []
      valuesGenerated.push({ x: 0, y: 1 });
      for (var i = 1; i < 100; i++) {
        valuesGenerated.push({ x: i, y: Math.random() * 10 + 10*i });
      }
      valuesGenerated.push({ x: 100, y: 1100 });
    
      return [
        {
          values: valuesGenerated,
          key: 'series1',
          color: '#ff7f0e'
        },
      ];
    }
    .chart {
      height: 300px !important;
      width: 80%;
    }
    <svg class="chart"></svg>
    
    <script src="//d3js.org/d3.v3.min.js"></script>
    <script src="https://cdn.rawgit.com/novus/nvd3/v1.8.1/build/nv.d3.js"></script>

    我知道您不想使用 .tickValues() 手动指定值,但它可以通过一个简单的函数来维护,给定域范围,这似乎是一个胜利情况。

    还有一个解决方法found here,即

    • 在显示之前修改 Y 值
    • 并手动格式化刻度,

    但控制显示哪些值更难,因为它取决于 D3.js 。但是这样 .ticks() 方法在 NVD3.js 中工作

    const chart = nv.models.lineChart()
        .margin({ left: 150 })  
        .useInteractiveGuideline(true)
        .showLegend(true)       
        .showYAxis(true)        
        .showXAxis(true);
    
    var logScale = d3.scale.log();
    chart.yScale(logScale);
    chart.xAxis.tickFormat(d3.format(',r'));
    chart.yAxis.ticks(6);
    chart.yAxis.tickFormat(d3.format('.02f'));
    
    chart.y(function(d) { return d.y>0?Math.log10(d.y+1):0 });
    chart.yAxis.ticks(10);
    chart.yAxis.tickFormat(function(d){return (Math.pow(10,d)-1).toFixed(2)});
    
    var myData = generateValues();
    d3.select('.chart')
          .datum(myData) 
          .call(chart);   
    
    function generateValues() {
      var valuesGenerated = []
      valuesGenerated.push({ x: 0, y: 1 });
      for (var i = 1; i < 100; i++) {
        valuesGenerated.push({ x: i, y: Math.random() * 10 + 10*i });
      }
      valuesGenerated.push({ x: 100, y: 1100 });
    
      return [
        {
          values: valuesGenerated,
          key: 'series1',
          color: '#ff7f0e'
        },
      ];
    }
    .chart {
      height: 300px !important;
      width: 80%;
    }
    <svg class="chart"></svg>
    
    <script src="//d3js.org/d3.v3.min.js"></script>
    <script src="https://cdn.rawgit.com/novus/nvd3/v1.8.1/build/nv.d3.js"></script>

    【讨论】:

    • @darkpatronuslinkx re first sn-p - 是否可以在 d3v5 的对数刻度上仅显示第一个和最后一个刻度?我正在尝试相同的设置,但它在 d3v5 中不起作用
    猜你喜欢
    • 2015-03-24
    • 2014-12-24
    • 2011-10-04
    • 2014-06-21
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    相关资源
    最近更新 更多