我试图使单个单词/短语可单击,一旦选择了两个单词/短语,提供从一个单词到另一个单词绘制一条线(带箭头)的选项。我怎样才能在d3中实现这个目标?
这里是一个fiddle我在哪里可以选择文字(只选择文字范围或双击文字)。现在我需要做的就是启用“点击”#39;在选定的文本元素上,从一个箭头到另一个绘制箭头。有什么建议吗?
到目前为止,这是代码:
body = d3.select('body')
svg = body.append('svg')
.attr('height', 600)
.attr('width', 600);
var g = svg.append('g').attr("transform" ,"scale(0)");
rect = g.append('rect')
.attr('width', 300)
.attr('height', 300)
.attr('x', 40)
.attr('y', 100)
.style('fill', 'none')
.attr('stroke', 'black')
text = g.append('foreignObject')
.attr('x', 50)
.attr('y', 130)
.attr('width', 280)
.attr('height', 280)
.append("xhtml:body")
.html('<p style="width: 280px;">This is some information about whatever where I want two words to be clickable individually and then provide a way to drag from one word to another to draw an arrow</p>').on('click', function() {
console.log(d3.select(this).text());
});
g.transition().duration(500).attr("transform" ,"scale(1)");
d3.selectAll("p").on("mouseup", checkSelection)
.on("keyup", checkSelection);
function checkSelection(d,i) {
var selection = document.getSelection();
if (selection.isCollapsed) return;
var range = selection.getRangeAt(0);
highlightRange(range);
}
function highlightRange(range) {
var newNode = document.createElement("div");
newNode.setAttribute(
"style",
"background-color: yellow; display: inline;"
);
range.surroundContents(newNode);
}
答案 0 :(得分:2)
使用d3拖动行为在选择之间绘制连接线。创建用于绘制连接路径的虚拟路径,如果拖动在选择处结束,则绘制一条线。
<强> JS 强>
svg.append("defs").append("marker")
.attr("id", "arrowhead")
.attr("refX", 9)
.attr("refY", 2)
.attr("markerWidth", 6)
.attr("markerHeight", 4)
.attr("orient", "auto")
.append("path")
.attr("d", "M 0,0 V 4 L6,2 Z");
var dummy = svg.append("line")
.attr("class","dummy")
.style("display","none")
.attr("marker-end", "url(#arrowhead)");
var drag = d3.behavior.drag()
.on("dragstart", function(){
var x= d3.event.sourceEvent.x, y= d3.event.sourceEvent.y;
dummy.attr("x1",x)
.attr("y1",y).attr("x2",x)
.attr("y2",y)
.style("display","block");
})
.on("drag", function(d,i) {
var x= d3.event.sourceEvent.x, y= d3.event.sourceEvent.y;
dummy.attr("x2",x)
.attr("y2",y)
})
.on("dragend",function(){
var isSelected = d3.select(d3.event.sourceEvent.target).classed("selected");
if(isSelected && d3.event.sourceEvent.target!=this){
var x1=dummy.attr("x1"), y1=dummy.attr("y1"),
x2=dummy.attr("x2"), y2=dummy.attr("y2");
svg.append("line")
.attr("class","connector")
.attr("x1",x1)
.attr("y1",y1)
.attr("x2",x2)
.attr("y2",y2)
.attr("marker-end", "url(#arrowhead)");
}
dummy.style("display","none");
});
function highlightRange(range) {
var newNode = document.createElement("div");
d3.select(newNode).attr("class","selected").call(drag);
range.surroundContents(newNode);
}
<强>样式强>
::selection {
background-color:yellow;
}
.dummy{
stroke: black;
fill:none;
stroke-width: 2px;
stroke-dasharray: 5 5;
}
.connector{
stroke: steelblue;
fill:none;
stroke-width: 2px;
}
.selected{
background-color: yellow;
display: inline;
}
更新了JSFiddle