在点击的文本元素上绘制箭头?

时间:2015-02-02 18:49:49

标签: javascript jquery html css d3.js

我试图使单个单词/短语可单击,一旦选择了两个单词/短语,提供从一个单词到另一个单词绘制一条线(带箭头)的选项。我怎样才能在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);
}

1 个答案:

答案 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