在单击的文本元素上绘制箭头?
Drawing an arrow on clicked text elements?
我正在尝试使单个 words/phrases 可点击,一旦两个 words/phrases 被 selected,提供一个选项来从一个词到其他。我怎样才能在 d3 中实现这一点?
这是一个 fiddle 文本 selection 可以工作的地方(只需 select 文本跨度或双击单词)。现在我需要做的就是在 selected 文本元素上启用 'click' 并绘制一个箭头从一个到另一个。有什么建议吗?
目前的代码如下:
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);
}
使用 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
我正在尝试使单个 words/phrases 可点击,一旦两个 words/phrases 被 selected,提供一个选项来从一个词到其他。我怎样才能在 d3 中实现这一点?
这是一个 fiddle 文本 selection 可以工作的地方(只需 select 文本跨度或双击单词)。现在我需要做的就是在 selected 文本元素上启用 'click' 并绘制一个箭头从一个到另一个。有什么建议吗?
目前的代码如下:
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);
}
使用 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