d3轴标注

问题描述 投票:0回答:8

如何向 d3 中的轴添加文本标签?

例如,我有一个带有 x 轴和 y 轴的简单折线图。

在我的 x 轴上,我有从 1 到 10 的刻度。我希望“天”一词出现在其下方,以便人们知道 x 轴正在计算天数。

同样,在 y 轴上,我将数字 1-10 作为勾号,并且我希望“吃三明治”一词出现在侧面。

有没有简单的方法可以做到这一点?

javascript d3.js axis-labels
8个回答
208
投票

轴标签未内置于 D3 的 axis 组件,但您只需添加 SVG

text
元素即可自行添加标签。一个很好的例子是我对 Gapminder 的动画气泡图的重新制作,国家的财富与健康。 x 轴标签如下所示:

svg.append("text")
    .attr("class", "x label")
    .attr("text-anchor", "end")
    .attr("x", width)
    .attr("y", height - 6)
    .text("income per capita, inflation-adjusted (dollars)");

y 轴标签如下:

svg.append("text")
    .attr("class", "y label")
    .attr("text-anchor", "end")
    .attr("y", 6)
    .attr("dy", ".75em")
    .attr("transform", "rotate(-90)")
    .text("life expectancy (years)");

您还可以使用样式表根据需要设置这些标签的样式,可以一起 (

.label
) 或单独 (
.x.label
.y.label
)。


37
投票

在新的 D3js 版本(版本 3 及以上)中,当您通过

d3.svg.axis()
函数创建图表轴时,您可以访问两个名为
tickValues
tickFormat
的方法,它们内置在函数内部,以便您可以指定您需要勾选哪些值以及您希望文本以什么格式显示:

var formatAxis = d3.format("  0");
var axis = d3.svg.axis()
        .scale(xScale)
        .tickFormat(formatAxis)
        .ticks(3)
        .tickValues([100, 200, 300]) //specify an array here for values
        .orient("bottom");

18
投票

如果你想像我一样将 y 轴标签放在 y 轴中间:

  1. 使用文本锚中心将文本旋转 90 度
  2. 按中点翻译文本
    • x 位置:防止 y 轴刻度标签重叠 (
      -50
      )
    • y 位置:匹配 y 轴的中点 (
      chartHeight / 2
      )

代码示例:

var axisLabelX = -50;
var axisLabelY = chartHeight / 2;

chartArea
    .append('g')
    .attr('transform', 'translate(' + axisLabelX + ', ' + axisLabelY + ')')
    .append('text')
    .attr('text-anchor', 'middle')
    .attr('transform', 'rotate(-90)')
    .text('Y Axis Label')
    ;

这可以防止旋转整个坐标系,如上面 lubar 提到的。


3
投票

如果您按照建议使用 d3.v4,您可以使用此实例来提供您需要的一切。

您可能只想用“天”替换 X 轴数据,但请记住正确解析字符串值而不是应用连接。

parseTime 也可以用日期格式来缩放天数?

d3.json("data.json", function(error, data) {
if (error) throw error;

data.forEach(function(d) {
  d.year = parseTime(d.year);
  d.value = +d.value;
});

x.domain(d3.extent(data, function(d) { return d.year; }));
y.domain([d3.min(data, function(d) { return d.value; }) / 1.005, d3.max(data, function(d) { return d.value; }) * 1.005]);

g.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x));


g.append("g")
    .attr("class", "axis axis--y")
    .call(d3.axisLeft(y).ticks(6).tickFormat(function(d) { return parseInt(d / 1000) + "k"; }))
  .append("text")
    .attr("class", "axis-title")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .attr("fill", "#5D6971")
    .text("Population)");

摆弄全局 css / js


1
投票

D3 提供了一组相当低级的组件,可用于组装图表。您将获得构建块、轴组件、数据连接、选择和 SVG。你的工作就是将它们组合在一起形成图表!

如果您想要一个传统的图表,即一对轴、轴标签、图表标题和绘图区域,为什么不看看d3fc?它是一组更高级的 D3 组件的开源集。它包括您可能需要的笛卡尔图表组件:

var chart = fc.chartSvgCartesian(
    d3.scaleLinear(),
    d3.scaleLinear()
  )
  .xLabel('Value')
  .yLabel('Sine / Cosine')
  .chartLabel('Sine and Cosine')
  .yDomain(yExtent(data))
  .xDomain(xExtent(data))
  .plotArea(multi);

// render
d3.select('#sine')
  .datum(data)
  .call(chart);

您可以在此处查看更完整的示例:https://d3fc.io/examples/simple/index.html


0
投票
chart.xAxis.axisLabel('Label here');

xAxis: {
   axisLabel: 'Label here'
},

0
投票

在 D3.js 中自定义轴
https://ghenshaw-work.medium.com/customizing-axes-in-d3-js-99d58863738b

let xAxisGenerator = d3.axisBottom(xScale);
let tickLabels = ['A','B','C'];
xAxisGenerator.tickFormat((d,i) => tickLabels[i]);

0
投票

const svg = d3.select('#diagram');
const blockRadius = 30;
const ports = [
    { name: 'Port 1', position: 'top', offset: 0, portShape: 'circle', radius: 3 },
    { name: 'Port 2', position: 'right', offset: 0, portShape: 'rect', width: 6, height: 6 },
    { name: 'Port 3', position: 'bottom', offset: 0, portShape: 'filled-circle', radius: 5 },
    { name: 'Port 4', position: 'left', offset: 0, portShape: 'oval', rx: 5, ry: 3 }
]; // Example list of ports with positions, offsets, and shapes

// Create the circular block
svg.append('circle')
    .attr('cx', 100)
    .attr('cy', 100)
    .attr('r', blockRadius)
    .classed('block', true);

// Bind data to ports and create SVG shapes based on data
const portShapes = svg.selectAll('.port')
    .data(ports)
    .enter()
    .append(d => {
        if (d.portShape === 'circle' || d.portShape === 'filled-circle') {
            return 'circle';
        } else if (d.portShape === 'rect') {
            return 'rect';
        } else if (d.portShape === 'oval') {
            return 'ellipse';
        }
    })
    .attr('cx', d => {
        let x;

        switch (d.position) {
            case 'top':
                x = 100;
                break;
            case 'right':
                x = 100 + blockRadius;
                break;
            case 'bottom':
                x = 100;
                break;
            case 'left':
                x = 100 - blockRadius;
                break;
            default:
                x = 100;
        }

        return x;
    })
    .attr('cy', d => {
        let y;

        switch (d.position) {
            case 'top':
                y = 100 - blockRadius;
                break;
            case 'right':
                y = 100;
                break;
            case 'bottom':
                y = 100 + blockRadius;
                break;
            case 'left':
                y = 100;
                break;
            default:
                y = 100;
        }

        return y;
    })
    .attr('r', d => (d.portShape === 'circle' || d.portShape === 'filled-circle') ? d.radius : 0) // Radius based on shape
    .attr('x', d => (d.portShape === 'rect') ? -d.width / 2 : d.position === 'right' ? blockRadius - d.width / 2 : d.position === 'left' ? -blockRadius - d.width / 2 : 0)
    .attr('y', d => (d.portShape === 'rect') ? -d.height / 2 : d.position === 'top' ? -blockRadius - d.height / 2 : d.position === 'bottom' ? blockRadius - d.height / 2 : 0)
    .attr('width', d => (d.portShape === 'rect') ? d.width : 0) // Width for rectangles
    .attr('height', d => (d.portShape === 'rect') ? d.height : 0) // Height for rectangles
    .classed('port', true);

// Add text labels for ports
svg.selectAll('.port-label')
    .data(ports)
    .enter()
    .append('text')
    .attr('x', d => {
        let x;

        switch (d.position) {
            case 'top':
                x = 100;
                break;
            case 'right':
                x = 100 + blockRadius + 10;
                break;
            case 'bottom':
                x = 100;
                break;
            case 'left':
                x = 100 - blockRadius - 10;
                break;
            default:
                x = 100;
        }

        return x;
    })
    .attr('y', d => {
        let y;

        switch (d.position) {
            case 'top':
                y = 100 - blockRadius - 10;
                break;
            case 'right':
                y = 100;
                break;
            case 'bottom':
                y = 100 + blockRadius + 10;
                break;
            case 'left':
                y = 100;
                break;
            default:
                y = 100;
        }

        return

© www.soinside.com 2019 - 2024. All rights reserved.