Fork me on Bolg '◡'

svg / d3-force 中如何给link的label文字加底色

上篇介绍的使用滤镜给force中的节点文字加底色,但是同样的方法并不适合link上文字的底色。因为link是可以360度旋转的。而滤镜中的宽高一般是跟着文字的,svg中文字的宽高并没有伴随角度,(这里我没有找到给滤镜加角度的方法,如果有可以告诉我呀!)因此我使用了另外一种给文字加底色的方法,使用rect的方法,然后计算出文字旋转的角度,给rect加转动属性实现。【转载本文请说明出处,谢谢!】

效果演示


方法

// 1、添加一个rect
lines.call(links => {
          links.each(function (link) {
            if (link.relName) {
              d3.select(this).append('rect')
                .attr('class', 'link-line-rect')
                .attr('fill', '#fff')
                .attr('rx', '2')
                .attr('ry', '2')
            }
          })
        })
// 2、tick的时候随之转动
lines.selectAll('.link-line-rect')
            .attr('x', d => d.point.x)
            .attr('y', d => d.point.y)
            .attr('width', d => d.point.width)
            .attr('height', d => d.point.height)
            .attr('transform', d => {
              // 获取转动的角度,给加上rotate属性
              let { angle } = that.getAngel(d)
              return `rotate(${angle}, ${d.point.x}, ${d.point.y}) translate(-${d.point.width / 2}, -${d.point.height / 2})`
            })
  • d.point:指的是对应link的label文字的信息,获取方法如下:
      // 获取label相关信息
      let lineNode = d3.select(`#line${d.objPropId}${d.source.id}${d.target.id}`).node()
      if (lineNode) {
        // 获取中间点 
        d.point = lineNode.getPointAtLength(lineNode.getTotalLength() / 2);
      }

      let textNode = d3.select(`#lineText${d.objPropId}${d.source.id}${d.target.id}`).node()
      if (textNode) {
        d.point.width = textNode.getBoundingClientRect().width
        d.point.height = 15 // 高度不变,直接写可以
      }
  • getAngel:获取link转动的角度
// 获取角度等信息
    getAngel (d) {
      let dsx = d.source.x;
      let dsy = d.source.y;
      let tsx = d.target.x;
      let tsy = d.target.y;

      let disX = tsx - dsx;
      let disY = tsy - dsy;
      let disZ = Math.sqrt(Math.pow(disY, 2) + Math.pow(disX, 2));

      let sin = disY / disZ;
      let cos = disX / disZ;
      // 根据弧度算角度
      let angle = Math.asin(sin) * 180 / Math.PI

      if (tsx < dsx) {
        angle = -angle
      }
      return {
        sin,
        cos,
        angle
      }
    }

图文并茂解释下:

小结

关于这方面的文档其实是比较少的,只能自己一边研究一边记录,分享下来,希望能帮到同样要用的人。

posted @ 2020-09-14 20:10  webhmy  阅读(800)  评论(0编辑  收藏  举报