• 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
          }
        }
    

    图文并茂解释下:

    小结

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

  • 相关阅读:
    hibernateValidator 升级
    java异常
    reids过期键三种删除策略
    hashmap源码探究
    http知识梳理1
    GregorianCalendar类的使用
    计算机网络笔记
    List的toArray方法
    实习周记一
    vue指令详解
  • 原文地址:https://www.cnblogs.com/webhmy/p/13669041.html
Copyright © 2020-2023  润新知