简体   繁体   中英

D3 Logarithmic Tick Labels as Powers of 10

Using D3 I want to create an X Axis that looks like:

所需的日志刻度标签的图像

I've worked out how to do the axis and ticks, but not the labels using the following:

var svgWidth = 500;
var svgHeight = 500;
var svgAxisPadding = 20;

var xScale = d3.scale.log()
  .domain([Math.pow(10, 5), Math.pow(10, 7)])
  .range([svgAxisPadding, svgWidth - svgAxisPadding]);

var xAxis = d3.svg.axis()
  .scale(xScale)
  .orient('bottom')
  .ticks(0, "e");

var svg = d3.select('#diagram')
  .append('svg')
  .attr('width', svgWidth)
  .attr('height', svgHeight);

svg.append('g')
  .attr("class", "axis")
  .call(xAxis);

And here's a jsFiddle with the complete code.

You could use unicode:

var superscript = "⁰¹²³⁴⁵⁶⁷⁸⁹",
    formatPower = function(d) { return (d + "").split("").map(function(c) { return superscript[c]; }).join(""); },
    formatTick = function(d) { return 10 + formatPower(Math.round(Math.log(d) / Math.LN10)); };

For example, formatTick(1e5) returns "10⁵" . Example at bl.ocks.org/6738109 :

轴

The downside of this approach is that the vertical alignment of the superscript numerals seems inconsistent. So using post-selection (say, selecting the text elements and adding a tspan element for the superscript to each) might be better. Another example at bl.ocks.org/6738229 :

轴

There's a tickFormat function available on the axis. Unfortunately, it expects a String as a return value and plops that on the axis. This would be great if you wanted to display 10^6, but not as helpful when you want to use the superscript notation.

A workaround is to create 2 axes: one for displaying the 10 and another for displaying the exponent. Here's an example :

var svgWidth = 500;
var svgHeight = 500;
var svgAxisPadding = 20;

var xScale = d3.scale.log()
    .domain([Math.pow(10, 5), Math.pow(10, 7)])
    .range([svgAxisPadding, svgWidth - svgAxisPadding]);

var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient('bottom')
    .ticks(0, "e")
    .tickFormat(function (d) {
        var log = Math.log(d) / Math.LN10;
        return Math.abs(Math.round(log) - log) < 1e-6 ? 10 : '';
    });

var xAxis2 = d3.svg.axis()
    .scale(xScale)
    .orient('bottom')
    .ticks(0, "e")
    .tickFormat(function (d) {
        var log = Math.log(d) / Math.LN10;
        return Math.abs(Math.round(log) - log) < 1e-6 ? Math.round(log) : '';
    });

var svg = d3.select('#diagram')
    .append('svg')
    .attr('width', svgWidth)
    .attr('height', svgHeight);

svg.append('g')
    .attr("class", "axis")
    .call(xAxis);

svg.append('g')
    .attr("class", "axis")
    .attr("transform", "translate(12, -5)") //shifted up and to the right
    .style("font-size", "12px")
    .call(xAxis2);

It's not necessarily the most elegant solution, but it works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM