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

圖文並茂解釋下:

小結

關於這方面的文檔其實是比較少的,只能自己一邊研究一邊記錄,分享下來,希望能幫到同樣要用的人。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章