【问题标题】:How to center (horizontal and vertical) text along an textPath inside an arc using d3.js?如何使用 d3.js 在弧内沿 textPath 居中(水平和垂直)文本?
【发布时间】:2013-12-25 04:10:48
【问题描述】:

在玩了一段时间 d3.js 并查看了很多示例之后,我能够绘制多条弧线。每一个都以特定的度数和给定的半径开始和结束。

var dataset = {
    "2":[{"degree1":0,                 "degree2":1.5707963267949,
          "label":"Sample Text Test"},    
         {"degree1":1.5707963267949,   "degree2":3.1415926535898,
          "label":"Lorem ipsum sample text"},
         {"degree1":3.1415926535898,   "degree2":4.7123889803847,
          "label":"Sample Text Text"},
         {"degree1":4.7123889803847,   "degree2":6.2831853071796,
          "label":"Lorem ipsum"}],
    "1":[{"degree1":0,                 "degree2":3.1415926535898,
          "label":"Sample"},
         {"degree1":3.1415926535898,   "degree2":6.2831853071796,
          "label":"Text"}],
    "0":[{"degree1":0,                 "degree2":6.2831853071796,
          "label":""}]
    },
    width   = 450,
    height  = 450,
    radius  = 75;

// Helper methods
var innerRadius = function(d, i, j) {
    return 1 + radius * j;
};

var outerRadius = function(d, i, j) {
    return radius * (j + 1);
};

var startAngle = function(d, i, j) {
    return d.data.degree1;
};

var endAngle = function(d, i, j) {
    return d.data.degree2;
};

var pie = d3.layout.pie()
    .sort(null);

var arc = d3.svg.arc()
    .innerRadius(innerRadius)
    .outerRadius(outerRadius)
    .startAngle(startAngle)
    .endAngle(endAngle);

var svg = d3.select('body').append('svg')
    .attr('width', width)
    .attr('height', height)
    .append('g')
    .attr('transform', 'translate(' + (width >> 1) + ',' + (height >> 1) + ')');

var level = svg.selectAll('g')
    .data(function(d) {
        return d3.values(dataset);
    })
    .enter()
    .append('g');

var entry = level.selectAll('g')
    .data(function(d, i) {
        return pie(d);
    })
    .enter()
    .append('g');

entry.append('path')
    .attr('fill', '#aaa')
    .attr('d', arc)
    .attr('id', function(d, i, j) {
        return 'arc' + i + '-' + j;
    });

var label = entry.append('text')
    .style('font-size', '20px')
    .attr('dx', function(d, i, j) {
        return Math.round((d.data.degree2 - d.data.degree1) * 180 / Math.PI);
    })
    .attr('dy', function(d, i, j) {
        return ((radius * (j + 1)) - (1 + radius * j)) >> 1;
    });


label.append('textPath')
    .attr('xlink:href', function(d, i, j) {
        return '#arc' + i + '-' + j;
    })
    .style('fill', '#000')
    .text(function(d) {
        return d.data.label;
    });

http://jsfiddle.net/3FP6P/2/

但还是有一些问题:

  1. 如何在由 innerRadius、outerRadius、startAngle 和 endAngle 描述的弧内沿任意长度的文本路径居中(水平和垂直)文本?
  2. 文本有时会显示为粗体,有时不是。为什么?
  3. 字符间距似乎与写在 .有些字母像其他字母一样粘在一起。为什么?
  4. 字母不直接位于路径上。有些似乎有一点向上或向下滑动。为什么?

【问题讨论】:

    标签: javascript text svg path d3.js


    【解决方案1】:

    垂直对齐

    您可以使用另一个半径为(innerRadius + outerRadius) / 2 的弧并将其用作标签的textPath

    请注意,即使您设置了innerRadius == outerRadius,D3 也会绘制一条顺时针然后逆时针移动的路径,使其自身翻倍。这在试图找出路径的水平中心时变得很重要:它位于25%75% 点,而0%50% 点位于路径的两个尖端弧线。

    水平对齐

    在文本元素上使用text-anchor: middle,并在textPath 上将startOffset 设置为25%(或75%)。

    Demo.

    这比手动计算dxdy 更可靠。

    您应该尝试 Lars 的建议以进一步提高文本的质量和居中,例如您可能想将text-rendering 设置为optimizeLegibility 并稍微调整一下基线。

    【讨论】:

    【解决方案2】:

    问题 2-4 是因为字体渲染。在我的浏览器中,间距和字符大小等是一致的。您可以尝试使用text-rendering attribute 来改进。

    要使文本居中,您需要设置alignment-baseline 和/或dominant-baseline 属性。

    如果这仍然无法为您提供所需的结果,请尝试减小字体大小。这可能会有所帮助,因为角色的轻微旋转会不太明显。

    【讨论】:

    • 垂直对齐使用alignment-baseline 对我有用。
    猜你喜欢
    • 1970-01-01
    • 2011-08-07
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    相关资源
    最近更新 更多