当前位置:  开发笔记 > 编程语言 > 正文

显示D3链接文本正面朝上

如何解决《显示D3链接文本正面朝上》经验,为你挑选了1个好方法。

我已经在链接上构建了一个带有文本标签的D3力导向可视化.我遇到的一个问题是,当链接位于其源节点的左侧时,这些标签会颠倒显示.这里的例子:

在此输入图像描述

我定位路径和文本的代码如下所示:

var nodes = flatten(data);
var links = d3.layout.tree().links(nodes);

var path = vis.selectAll('path.link')
  .data(links, function(d) {
    return d.target.id;
  });

path.enter().insert('svg:path')
  .attr({
    class: 'link',
    id: function(d) {
      return 'text-path-' + d.target.id;
    },
    'marker-end': 'url(#end)'
  })
  .style('stroke', '#ccc');

var linkText = vis.selectAll('g.link-text').data(links);

linkText.enter()
  .append('text')
    .append('textPath')
      .attr('xlink:href', function(d) {
        return '#text-path-' + d.target.id;
      })
      .style('text-anchor', 'middle')
      .attr('startOffset', '50%')
      .text(function(d) {return d.target.customerId});

我知道我需要以某种方式确定每个路径的当前角度,然后相应地设置文本位置,但我不知道如何.

以下是基于此问题的块的链接:http://blockbuilder.org/MattDionis/5f966a5230079d9eb9f4

下面的答案让我大约90%的方式.以下是我的原始可视化效果,文本长度超过几位数:

在此输入图像描述

......以下是利用以下答案中的提示:

在此输入图像描述

因此,虽然文本现在是"正面向上",但它不再遵循弧形.



1> jrsala..:

您绘制的弧线使得它们在中间的切线正好是文本基线的方向,并且它也与用于分隔两个树节点的矢量共线.

我们可以用它来解决问题.

需要一点数学.首先,让我们定义一个函数,该函数返回向量v相对于水平轴的角度:

function xAngle(v) {
    return Math.atan(v.y/v.x) + (v.x < 0 ? Math.PI : 0);
}

然后,在每个刻度线处,让我们通过减去其基线的角度来旋转文本.首先,一些实用功能:

function isFiniteNumber(x) {
    return typeof x === 'number' && (Math.abs(x) < Infinity);
}

function isVector(v) {
    return isFiniteNumber(v.x) && isFiniteNumber(v.y);
}

然后,在你的tick函数中,添加

linkText.attr('transform', function (d) {
    // Checks just in case, especially useful at the start of the sim
    if (!(isVector(d.source) && isVector(d.target))) {
        return '';
    }

    // Get the geometric center of the text element
    var box = this.getBBox();
    var center = {
        x: box.x + box.width/2,
        y: box.y + box.height/2
    };

    // Get the tangent vector
    var delta = {
        x: d.target.x - d.source.x,
        y: d.target.y - d.source.y
    };

    // Rotate about the center
    return 'rotate('
        + (-180/Math.PI*xAngle(delta))
        + ' ' + center.x
        + ' ' + center.y
        + ')';
    });
});

编辑:添加图片:

示例结果

编辑2使用直线而不是弯曲的弧线(只是内部而不是内部),您可以替换与此相关的tick函数部分linkText:

linkText.attr('transform', function(d) {
    if (!(isVector(d.source) && isVector(d.target))) {
        return '';
    }

    // Get the geometric center of this element
    var box = this.getBBox();
    var center = {
        x: box.x + box.width / 2,
        y: box.y + box.height / 2
    };

    // Get the direction of the link along the X axis
    var dx = d.target.x - d.source.x;

    // Flip the text if the link goes towards the left
    return dx < 0
        ? ('rotate(180 '
            + center.x
            + ' ' + center.y
            + ')')
        : '';
});

这就是你得到的:

旋转文字

注意当链接从更多指向右边指向更多指向左边时,文本如何被翻转.

这个问题是文本最终在链接下面.这可以修复如下:

linkText.attr('transform', function(d) {
    if (!(isVector(d.source) && isVector(d.target))) {
        return '';
    }

    // Get the geometric center of this element
    var box = this.getBBox();
    var center = {
        x: box.x + box.width / 2,
        y: box.y + box.height / 2
    };

    // Get the vector of the link
    var delta = {
        x: d.target.x - d.source.x,
        y: d.target.y - d.source.y
    };

    // Get a unitary vector orthogonal to delta
    var norm = Math.sqrt(delta.x * delta.x + delta.y * delta.y);
    var orth = {
        x: delta.y/norm,
        y: -delta.x/norm
    };

    // Replace this with your ACTUAL font size
    var fontSize = 14;

    // Flip the text and translate it beyond the link line
    // if the link goes towards the left
    return delta.x < 0
        ? ('rotate(180 '
            + center.x
            + ' ' + center.y
            + ') translate('
            + (orth.x * fontSize) + ' '
            + (orth.y * fontSize) + ')')
        : '';
});

现在结果如下:

在此输入图像描述

正如您所看到的,即使链接指向左侧,文本也能很好地位于行顶部.

最后,为了解决问题,同时保持弧线并使文本右侧向上弯曲,我认为你需要构建两个元素.一个从去sourcetarget,一个是要以相反的方式.当链接向右(delta.x >= 0)时你会使用第一个,当链接向左()时你会使用第二个delta.x < 0,我认为结果看起来更好,代码不一定比原来复杂,只是添加了更多的逻辑.

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有