javascript - 如何使用 d3.js 沿着弧内的 textPath 居中(水平和垂直)文本?

标签 javascript text svg path d3.js

在玩了一段时间 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/ :

enter image description here

但还是存在一些问题:

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

最佳答案

垂直对齐

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

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

水平对齐

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

Demo .

这是一种比手动计算 dxdy 更可靠的方法。

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

关于javascript - 如何使用 d3.js 沿着弧内的 textPath 居中(水平和垂直)文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20447106/

相关文章:

javascript - Angular 6 - 如何定义不止一种类型的返回值类型

c++ - C++中的文本输入

javascript - vue 中的 EventBus 不工作

java - 在 Android 中生成带有自定义文本的图像

html - 将文本放入 div 中心的问题

javascript - 通过颜色选择器更改 svg 填充颜色

css - 如何在 SVG 中为特定部分制作透明颜色代码

Javascript 加载功能只有一半的时间有效 (Firefox)

javascript - 为什么没有javascript引擎支持尾调用优化?

javascript - jquery 调用导致服务器出现问题