Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript D3js部队布局,动态链接_Javascript_Svg_D3.js_Visualization_Force Layout - Fatal编程技术网

Javascript D3js部队布局,动态链接

Javascript D3js部队布局,动态链接,javascript,svg,d3.js,visualization,force-layout,Javascript,Svg,D3.js,Visualization,Force Layout,感谢阅读——我正在使用D3js force bubble布局设计一个交互式外语教学工具。本质上,用户可以选择语言教科书的章节、词性或特定单词,界面将以一系列气泡的形式显示这些单词,每个气泡按其词性(形容词、名词、动词等)聚集在一起。这些气泡是自由浮动的,它们之间没有链接 当你点击一个单词时,我会让它打开更多关于该单词的信息(词素、英语意思、频率等),但我希望这些气泡通过链接附加到原始气泡上。我在概念化如何动态地(source->target)实现这一点上遇到了很多困难,尽管它应该非常简单 首先,

感谢阅读——我正在使用D3js force bubble布局设计一个交互式外语教学工具。本质上,用户可以选择语言教科书的章节、词性或特定单词,界面将以一系列气泡的形式显示这些单词,每个气泡按其词性(形容词、名词、动词等)聚集在一起。这些气泡是自由浮动的,它们之间没有链接

当你点击一个单词时,我会让它打开更多关于该单词的信息(词素、英语意思、频率等),但我希望这些气泡通过链接附加到原始气泡上。我在概念化如何动态地(source->target)实现这一点上遇到了很多困难,尽管它应该非常简单

首先,我根据用户输入绘制气泡图,其中一些气泡图我省略了,因此代码不会太长:

var nodes = d3.range(n).map(function(j) { return createNode(colorList, j); });
function createNode(info, j){
    var keys = objectKeys;
    var cluster, r;
    if (info[j].Lexeme.length < 3) {
        var radius = info[j].Lexeme.length * 15;
    }
    else {
        var radius = info[j].Lexeme.length * 5;
    }
    $.each(keys, function(x, y){
        if (info[j].POS == x){
            cluster = y;
        }
    });
    d = {cluster: cluster, radius: radius, info: info[j]};
    if (!clusters[cluster] || (r > clusters[cluster].radius)) clusters[cluster] = d;
    return d;
}

d3.layout.pack()
    .sort(null)
    .size([width, height])
    .children(function(d) { return d.values;})
    .value(function(d) { return d.radius * d.radius; })
    .nodes({values: d3.nest()
      .key(function(d) { return d.cluster; })
      .entries(nodes)});

var force = d3.layout.force()
    .nodes(nodes)
    .size([width, height])
    .gravity(.00001)
    .charge(0)
    .on("tick", tick)
    .start();           

var svg = d3.select("#canvas").append("svg")
    .attr("width", width)
    .attr("height", height);

var node = svg.selectAll("circle")
    .data(nodes)
    .enter().append("circle")
    .attr("class", function (d, i) { return "node_n" + i; })
    .style("fill", function(d) {return d.info.fillColor;})
    .on("click", nodeSelect)
    .on("dblclick", infoNode)
    .call(force.drag);
    //Add the SVG Text Element to the svgContainer
    var text = svg.selectAll("text")
    .data(nodes)
    .enter()
    .append("text");

    //Add SVG Text Element Attributes
    text
     .attr("cx", function(d) { return d.x; })
     .attr("cy", function(d) { return d.y; })
     .text( function (d) { return d.info.Lexeme; })
     .attr("font-family", "sans-serif")
     .attr("text-anchor", "middle")
     .attr("font-size", "13px")
     .attr("fill", "#000000");

node.transition()
    .duration(750)
    .delay(function(d, i) { return i * 5; })
    .attrTween("r", function(d) {
        var i = d3.interpolate(0, d.radius);
        return function(t) { return d.radius = i(t); };
    });

function tick(e) {

    node
      .each(cluster(5 * e.alpha * e.alpha))
      .each(collide(.3))
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });

    text
       .attr("transform", transform);
}


function transform(d) {
  return "translate(" + d.x + "," + d.y + ")";
}

function nodeSelect(d) {
    if (d3.select(this).style("opacity") == 1 && nodeSelected == 0) {
        nodeSelected = 1;
        d3.select(this).style("opacity", ".3");
    }
    else if (d3.select(this).style("opacity") == .3 && nodeSelected == 1){
        nodeSelected = 0;
        d3.select(this).style("opacity", "1");
    }
}

// Move d to be adjacent to the cluster node.
function cluster(alpha) {
  return function(d) {
    var cluster = clusters[d.cluster];
    if (cluster === d) return;
    var x = d.x - cluster.x,
        y = d.y - cluster.y,
        l = Math.sqrt(x * x + y * y),
        r = d.radius + cluster.radius;
    if (l != r) {
      l = (l - r) / l * alpha;
      d.x -= x *= l;
      d.y -= y *= l;
      cluster.x += x;
      cluster.y += y;
    }
  };
}   

// Resolves collisions between d and all other circles.
function collide(alpha) {
  var quadtree = d3.geom.quadtree(nodes);
  return function(d) {
    var r = d.radius + maxRadius + Math.max(padding, clusterPadding),
        nx1 = d.x - r,
        nx2 = d.x + r,
        ny1 = d.y - r,
        ny2 = d.y + r;
    quadtree.visit(function(quad, x1, y1, x2, y2) {
      if (quad.point && (quad.point !== d)) {
        var x = d.x - quad.point.x,
            y = d.y - quad.point.y,
            l = Math.sqrt(x * x + y * y),
            r = d.radius + quad.point.radius + (d.cluster === quad.point.cluster ? padding : clusterPadding);
        if (l < r) {
          l = (l - r) / l * alpha;
          d.x -= x *= l;
          d.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y;
        }
      }
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    });
  };
}
function infoNodes(d){
    $.each(d.info, function(i, val){
        if (val != "" && val !="NA" && i != "fillColor"){
            var b = d.cluster;
            var r = 50;
            var q = {cluster: b, radius: r, info: val, fillColor: d.info.fillColor};
            if (!clusters[cluster] || (r > clusters[cluster].radius)) clusters[cluster] = q;
            nodes.push(q);
        }

    });
    update(d);

}


function update(j) {

    node = svg.selectAll("circle")
        .data(nodes)
        .call(force.drag);

    node.enter().append("circle")
        .attr("class", function (d, i) { return "info_" + d;})
        .attr("cx", function (d) { return d.x; })
        .attr("cy", function (d) { return d.y; })
        .attr("r", function (d) { if (d.info.length < 5 || d.info.length == null) { return 30; } else { return d.info.length * 3.3; } })
        .style("fill", function(d) {return d.fillColor;})
        .call(force.drag);

    text = svg.selectAll("text")
        .data(nodes)
        .call(force.drag);

    text.enter().append("text")
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; })
        .text( function (d) { return d.info; })
        .attr("font-family", "sans-serif")
        .attr("text-anchor", "middle")
        .attr("font-size", "13px")
        .attr("fill", "#000000")
        .call(force.drag);

    force.start();

}
var nodes=d3.range(n).map(函数(j){returncreatenode(colorList,j);});
函数createNode(信息,j){
var-keys=objectKeys;
var聚类,r;
if(info[j].Lexeme.length<3){
var radius=info[j].Lexeme.length*15;
}
否则{
var radius=info[j].Lexeme.length*5;
}
$。每个(键、函数(x、y){
如果(信息[j]。位置==x){
簇=y;
}
});
d={cluster:cluster,radius:radius,info:info[j]};
如果(!clusters[cluster]| |(r>clusters[cluster].radius))clusters[cluster]=d;
返回d;
}
d3.layout.pack()
.sort(空)
.尺寸([宽度、高度])
.children(函数(d){返回d.values;})
.value(函数(d){返回d.radius*d.radius;})
.nodes({值:d3.nest())
.key(函数(d){返回d.cluster;})
.entries(nodes)});
var-force=d3.layout.force()
.节点(节点)
.尺寸([宽度、高度])
.重力(.00001)
.收费(0)
.on(“滴答”,滴答)
.start();
var svg=d3.选择(“画布”).追加(“svg”)
.attr(“宽度”,宽度)
.attr(“高度”,高度);
var node=svg.selectAll(“圆”)
.数据(节点)
.enter().append(“圆”)
.attr(“类”,函数(d,i){return“node_n”+i;})
.style(“fill”,函数(d){return d.info.fillColor;})
。打开(“单击”,节点选择)
.on(“dblclick”,infoNode)
.呼叫(强制拖动);
//将SVG文本元素添加到svgContainer
var text=svg.selectAll(“文本”)
.数据(节点)
.输入()
.附加(“文本”);
//添加SVG文本元素属性
文本
.attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;})
.text(函数(d){return d.info.Lexeme;})
.attr(“字体系列”、“无衬线”)
.attr(“文本锚定”、“中间”)
.attr(“字体大小”,“13px”)
.attr(“填充”,000000);
node.transition()
.持续时间(750)
.delay(函数(d,i){返回i*5;})
.attrTween(“r”,函数(d){
var i=d3.插值(0,d.半径);
返回函数(t){returnd.radius=i(t);};
});
功能勾号(e){
节点
.每个(簇(5*e.alpha*e.alpha))
.每个(碰撞(.3))
.attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;});
文本
.attr(“变换”,变换);
}
函数变换(d){
返回“translate”(“+d.x+”,“+d.y+”);
}
功能节点选择(d){
if(d3.select(this.style(“不透明”)==1&&nodeSelected==0){
nodeSelected=1;
d3.选择(此).style(“不透明度”和“.3”);
}
else if(d3.select(this.style(“不透明”)=.3&&nodeSelected==1){
nodeSelected=0;
d3.选择(此).样式(“不透明度”、“1”);
}
}
//将d移动到与群集节点相邻的位置。
功能簇(alpha){
返回函数(d){
var cluster=簇[d.cluster];
if(cluster==d)返回;
var x=d.x-cluster.x,
y=d.y-cluster.y,
l=数学sqrt(x*x+y*y),
r=d.radius+cluster.radius;
如果(l!=r){
l=(l-r)/l*α;
d、 x-=x*=l;
d、 y-=y*=l;
簇x+=x;
簇y+=y;
}
};
}   
//解决d和所有其他圆之间的碰撞。
函数碰撞(alpha){
var四叉树=d3.geom.quadtree(节点);
返回函数(d){
var r=d.radius+maxRadius+Math.max(填充,簇填充),
nx1=d.x-r,
nx2=d.x+r,
ny1=d.y-r,
ny2=d.y+r;
四叉树访问(函数(四叉树,x1,y1,x2,y2){
if(quad.point&&(quad.point!==d)){
var x=d.x-四点x,
y=d.y-四点y,
l=数学sqrt(x*x+y*y),
r=d.radius+quad.point.radius+(d.cluster===quad.point.cluster?填充:clusterPadding);
if(lnx2 | x2ny2 | y2clusters[cluster].radius))clusters[cluster]=q;
节点推送(q);
}
});
更新(d);
}
功能更新(j){
node=svg.selectAll(“圆”)
.数据(节点)
.呼叫(强制拖动);
node.enter().append(“圆”)
.attr(“类”,函数(d,i){return“info_”+d;})
.attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;})
.attr(“r”,函数(d){if(d.info.length<5 | | d.info.length==null){return 30;}else{return d.info.length*3.3;})
.style(“fill”,函数(d){return d.fillColor;})
.呼叫(强制拖动);
text=svg。选择全部(“文本”)
.数据(节点)
加利福尼亚州