前言:
在svg中,文字也是图像,<text>标签显示文字,默认的文字方向是水平方向的。当我们需要使文字跟随连线方向,需要额外的一些设定,目前自己查阅到两种解决方案,适用于两种情况。
建议去MDN或者别处先查阅一下svg<text>的基本属性,本文不再介绍,只说明情况以及解决方案。
情况一:
连线两端的节点不要求拖动,连线和节点都是固定死的,静态的。
情况二:
连线两端的节点要求拖动,连线和节点是动态的,可以拖拽。
方案一:
内嵌于<text>中的<textpath>元素,通过xlink:href属性指向一个<path>元素,可以将其内部字符的baseline设置成指定的path.
<textpath>还有一个[startOffset]属性,用来设置文字在路径上的起始位置(百分比)。
上代码:
let path = object.selectAll(".path").data(paths,function (d) {return d.linkKey;});
//清楚多余的dom element
path.exit().remove();
//每条连线的path和text存放在一个g里
let pathEnter = path.enter().append("g")
.attr("class", "path")
// 为每条连线创建text 和 textpath
pathEnter.append("text")
.attr("class","path-text")
.attr('text-anchor','start')
.style('font-size','12px')
.style('font-family','Si mSun')
.append("textPath")
.attr("class","textPath")
.attr("xlink:href", p => { //此行代码,将文字链接到对应的path
return "#textPath" + p.linkKey;
})
.attr('startOffset','70%')//此行代码,决定文字在路径上的起始位置
.text(p => {return p.linkName})//显示文字内容
方案二:
当面对节点和连线需要动态的时候,我们要根据拖拽的节点控制文字一直可以正常显示。
可以查阅到,<text>有一个x的属性,x指定文字最左侧坐标位置,我们根据计算设置x的值,控制文字最左侧的坐标。x的值就是沿路径方向的path路径的起点-->文字最左侧的距离。此时就无需设置<textPath>的[startOffset]属性。
上代码:
let path = object.selectAll(".path").data(paths,function (d) {return d.linkKey;});
//清楚多余的dom element
path.exit().remove();
//每条连线的path和text存放在一个g里
let pathEnter = path.enter().append("g")
.attr("class", "path")
// 为每条连线创建text 和 textpath
pathEnter.append("text")
.attr("class","path-text")
.style('font-size','12px')
.style('font-family','Si mSun')
.append("textPath")
.attr("class","textPath")
.attr("xlink:href", p => {
return "#textPath" + p.linkKey;
})
//合并第一次创建为更新
path = path.merge(pathEnter);
//此处更新的是textpath 的属性,使得文字依附在path上
path.select(".path-text")
.attr('x',curThis.$options.methods.handleTopologyLinkTextX)//x指定文字最左侧坐标位置,根据连线两端节点的坐标,勾股出连线的长度l,让文字最左侧位于连线的中间,就是让x = l/2;
.attr('text-anchor','center')
.attr('rotate',curThis.$options.methods.handleTopologyLinkRotate)
.select('.textPath')
.text(curThis.$options.methods.handleTopologyLinkTextDirection);
/**
* @Description :处理拓扑图中连接的文字方向的旋转
* @author : yjz
* @param :
* @return :
* @exception :
* @date : 2019/05/10
*/
handleTopologyLinkRotate(p) {
return p.sourceAxis[0] < p.targetAxis[0] ? 0 : 180
},
/**
* @Description :处理拓扑图中连接的文字的最左侧坐标的位置
* @author : yjz
* @param :
* @return :
* @exception :
* @date : 2019/05/10
*/
handleTopologyLinkTextX(p) {
//x指定文字最左侧坐标位置,根据连线两端节点的坐标,勾股出连线的长度l,让文字最左侧位于连线的中间,就是让x = l/2;
let x = p.targetAxis[0] - p.sourceAxis[0],y = p.targetAxis[1] - p.sourceAxis[1];
let l = Math.sqrt(x * x + y * y)
return l/2;
},
/**
* @Description :处理拓扑图中连接的文字的顺序方向,保证文字正常显示
* @author : yjz
* @param :
* @return :
* @exception :
* @date : 2019/05/10
*/
handleTopologyLinkTextDirection(p) {
//为进行旋转的时候,文字方向是正常;当进行旋转之后,文字就反序显示了,需要将文字转换为顺序。
if (p.sourceAxis[0] < p.targetAxis[0]) {
return p.linkName
}
return p.linkName.split("").reverse().join("");
},