D3.js 力导向图(气泡+线条+箭头+文字)
<!DOCTYPE html>
<meta charset="utf-8">
<style> .link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
} #licensing {
fill: green;
} .link.licensing {
stroke: green;
} .link.resolved {
stroke-dasharray: 0,2 1;
} circle {
fill: #ccc;
stroke: #333;
stroke-width: 1.5px;
} text {
font: 12px Microsoft YaHei;
pointer-events: none;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
} .linetext {
font-size: 12px Microsoft YaHei;
} </style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script> // http://blog.thomsonreuters.com/index.php/mobile-patent-suits-graphic-of-the-day/
var links = [
{source: "同花顺", target: "IFIND", type: "resolved", rela:"主营产品"},
{source: "同花顺", target: "手机金融信息服务", type: "resolved", rela:"主营产品"},
{source: "同花顺", target: "互联网金融信息服务", type: "resolved", rela:"主营产品"},
{source: "同花顺", target: "网上行情交易系统", type: "resolved", rela:"主营产品"},
{source: "同花顺", target: "金融资讯及数据服务", type: "resolved", rela:"主营产品"},
{source: "同花顺", target: "互联网金融", type: "resolved",rela:"主营产品"},
{source: "同花顺", target: "金融服务", type: "resolved",rela:"主营产品"},
{source: "手机金融信息服务", target: "金融信息服务", type: "resolved", rela:"上位产品"},
{source: "互联网金融信息服务", target: "金融信息服务", type: "resolved", rela:"上位产品"},
{source: "二三四五002195", target: "金融信息服务", type: "resolved", rela:"主营产品"},
{source: "大智慧601519", target: "金融信息服务", type: "resolved", rela:"主营产品"},
{source: "大智慧601519", target: "互联网金融信息服务", type: "resolved", rela:"主营产品"},
{source: "金融服务", target: "移动互联网", type: "resolved", rela:"上游"},
{source: "金融服务", target: "互联网金融服务", type: "resolved", rela:"下位产品"},
{source: "金融服务", target: "综合金融服务", type: "resolved", rela:"下位产品"}
]; var nodes = {}; links.forEach(function(link) {
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
}); var width = 1560,
height = 800; var force = d3.layout.force()//layout将json格式转化为力学图可用的格式
.nodes(d3.values(nodes))//设定节点数组
.links(links)//设定连线数组
.size([width, height])//作用域的大小
.linkDistance(180)//连接线长度
.charge(-1500)//顶点的电荷数。该参数决定是排斥还是吸引,数值越小越互相排斥
.on("tick", tick)//指时间间隔,隔一段时间刷新一次画面
.start();//开始转换 var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height); //箭头
var marker=
svg.append("marker")
//.attr("id", function(d) { return d; })
.attr("id", "resolved")
//.attr("markerUnits","strokeWidth")//设置为strokeWidth箭头会随着线的粗细发生变化
.attr("markerUnits","userSpaceOnUse")
.attr("viewBox", "0 -5 10 10")//坐标系的区域
.attr("refX",32)//箭头坐标
.attr("refY", -1)
.attr("markerWidth", 12)//标识的大小
.attr("markerHeight", 12)
.attr("orient", "auto")//绘制方向,可设定为:auto(自动确认方向)和 角度值
.attr("stroke-width",2)//箭头宽度
.append("path")
.attr("d", "M0,-5L10,0L0,5")//箭头的路径
.attr('fill','#000000');//箭头颜色 /* 将连接线设置为曲线
var path = svg.append("g").selectAll("path")
.data(force.links())
.enter().append("path")
.attr("class", function(d) { return "link " + d.type; })
.style("stroke",function(d){
//console.log(d);
return "#A254A2";//连接线的颜色
})
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
*/ //设置连接线
var edges_line = svg.selectAll(".edgepath")
.data(force.links())
.enter()
.append("path")
.attr({
'd': function(d) {return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y},
'class':'edgepath',
//'fill-opacity':0,
//'stroke-opacity':0,
//'fill':'blue',
//'stroke':'red',
'id':function(d,i) {return 'edgepath'+i;}})
.style("stroke",function(d){
var lineColor;
//根据关系的不同设置线条颜色
if(d.rela=="上位产品" || d.rela=="上游" || d.rela=="下位产品"){
lineColor="#A254A2";
}else if(d.rela=="主营产品"){
lineColor="#B43232";
}
return lineColor;
})
.style("pointer-events", "none")
.style("stroke-width",0.5)//线条粗细
.attr("marker-end", "url(#resolved)" );//根据箭头标记的id号标记箭头 var edges_text = svg.append("g").selectAll(".edgelabel")
.data(force.links())
.enter()
.append("text")
.style("pointer-events", "none")
//.attr("class","linetext")
.attr({ 'class':'edgelabel',
'id':function(d,i){return 'edgepath'+i;},
'dx':80,
'dy':0
//'font-size':10,
//'fill':'#aaa'
}); //设置线条上的文字
edges_text.append('textPath')
.attr('xlink:href',function(d,i) {return '#edgepath'+i})
.style("pointer-events", "none")
.text(function(d){return d.rela;}); //圆圈
var circle = svg.append("g").selectAll("circle")
.data(force.nodes())//表示使用force.nodes数据
.enter().append("circle")
.style("fill",function(node){
var color;//圆圈背景色
var link=links[node.index];
if(node.name==link.source.name && link.rela=="主营产品"){
color="#F6E8E9";
}else{
color="#F9EBF9";
}
return color;
})
.style('stroke',function(node){
var color;//圆圈线条的颜色
var link=links[node.index];
if(node.name==link.source.name && link.rela=="主营产品"){
color="#B43232";
}else{
color="#A254A2";
}
return color;
})
.attr("r", 28)//设置圆圈半径
.on("click",function(node){
//单击时让连接线加粗
edges_line.style("stroke-width",function(line){
console.log(line);
if(line.source.name==node.name || line.target.name==node.name){
return 4;
}else{
return 0.5;
}
});
//d3.select(this).style('stroke-width',2);
})
.call(force.drag);//将当前选中的元素传到drag函数中,使顶点可以被拖动
/*
circle.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")//在圆圈内添加文字
.text(function(d) {
//console.log(d);
return d.name;
}); */ //圆圈的提示文字
circle.append("svg:title")
.text(function(node) {
var link=links[node.index];
if(node.name==link.source.name && link.rela=="主营产品"){
return "双击可查看详情"
}
});
/* 矩形
var rect=svg.append("rect")
.attr({"x":100,"y":100,
"width":100,"height":50,
"rx":5,//水平圆角
"ry":10//竖直圆角
})
.style({
"stroke":"red",
"stroke-width":1,
"fill":"yellow"
});*/
var text = svg.append("g").selectAll("text")
.data(force.nodes())
//返回缺失元素的占位对象(placeholder),指向绑定的数据中比选定元素集多出的一部分元素。
.enter()
.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")//在圆圈中加上数据
.style('fill',function(node){
var color;//文字颜色
var link=links[node.index];
if(node.name==link.source.name && link.rela=="主营产品"){
color="#B43232";
}else{
color="#A254A2";
}
return color;
}).attr('x',function(d){
// console.log(d.name+"---"+ d.name.length);
var re_en = /[a-zA-Z]+/g;
//如果是全英文,不换行
if(d.name.match(re_en)){
d3.select(this).append('tspan')
.attr('x',0)
.attr('y',2)
.text(function(){return d.name;});
}
//如果小于四个字符,不换行
else if(d.name.length<=4){
d3.select(this).append('tspan')
.attr('x',0)
.attr('y',2)
.text(function(){return d.name;});
}else{
var top=d.name.substring(0,4);
var bot=d.name.substring(4,d.name.length); d3.select(this).text(function(){return '';}); d3.select(this).append('tspan')
.attr('x',0)
.attr('y',-7)
.text(function(){return top;}); d3.select(this).append('tspan')
.attr('x',0)
.attr('y',10)
.text(function(){return bot;});
}
//直接显示文字
/*.text(function(d) {
return d.name; */
}); /* 将文字显示在圆圈的外面
var text2 = svg.append("g").selectAll("text")
.data(force.links())
//返回缺失元素的占位对象(placeholder),指向绑定的数据中比选定元素集多出的一部分元素。
.enter()
.append("text")
.attr("x", 150)//设置文字坐标
.attr("y", ".50em")
.text(function(d) {
//console.log(d);
//return d.name;
//return d.rela;
console.log(d);
return '1111';
});*/ function tick() {
//path.attr("d", linkArc);//连接线
circle.attr("transform", transform1);//圆圈
text.attr("transform", transform2);//顶点文字
//edges_text.attr("transform", transform3);
//text2.attr("d", linkArc);//连接线文字
//console.log("text2...................");
//console.log(text2);
//edges_line.attr("x1",function(d){ return d.source.x; });
//edges_line.attr("y1",function(d){ return d.source.y; });
//edges_line.attr("x2",function(d){ return d.target.x; });
//edges_line.attr("y2",function(d){ return d.target.y; }); //edges_line.attr("x",function(d){ return (d.source.x + d.target.x) / 2 ; });
//edges_line.attr("y",function(d){ return (d.source.y + d.target.y) / 2 ; }); edges_line.attr('d', function(d) {
var path='M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y;
return path;
}); edges_text.attr('transform',function(d,i){
if (d.target.x<d.source.x){
bbox = this.getBBox();
rx = bbox.x+bbox.width/2;
ry = bbox.y+bbox.height/2;
return 'rotate(180 '+rx+' '+ry+')';
}
else {
return 'rotate(0)';
}
});
} //设置连接线的坐标,使用椭圆弧路径段双向编码
function linkArc(d) {
//var dx = d.target.x - d.source.x,
// dy = d.target.y - d.source.y,
// dr = Math.sqrt(dx * dx + dy * dy);
//return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
//打点path格式是:Msource.x,source.yArr00,1target.x,target.y return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y
}
//设置圆圈和文字的坐标
function transform1(d) {
return "translate(" + d.x + "," + d.y + ")";
}
function transform2(d) {
return "translate(" + (d.x) + "," + d.y + ")";
} </script>
D3.js 力导向图(气泡+线条+箭头+文字)的更多相关文章
- D3.js力导向图(适用于其他类型图)中后添加元素遮盖已有元素的问题解决
上一篇说了在D3.js中动态增加节点及连线的一种实现方式,但是有后添加元素遮盖原节点的现象,这一篇说一下出现这个现象的解决办法. 在D3.js中后添加的元素是会遮盖先添加的元素的,同时还有一个设定:后 ...
- D3.js 力导向图的显示优化
D3.js 作为一个前端,说到可视化除了听过 D3.js 的大名,常见的可视化库还有 ECharts.Chart.js,这两个库功能也很强大,但是有一个共同特点是封装层次高,留给开发者可设计和控制的部 ...
- D3.js力导向图中新增节点及新增关系连线示例
大家在使用D3.js中的力导向图时,基本都会遇到动态增加节点及连线的需求,这里记录一下我的实现方式. 话不多说,先放代码: <!DOCTYPE html> <html lang=&q ...
- D3.js 力导向图
花了大半天看了一个八十几行的代码..心累 力导向图是之前就有画过很多次的东西,但是这次的代码看上去很陌生,然后发现是D3更新了4.0.... 先贴代码 var svg = d3.select(&quo ...
- D3.js 力导向图的制作
力导向图中每一个节点都受到力的作用而运动,这种是一种非常绚丽的图表. 力导向图(Force-Directed Graph),是绘图的一种算法.在二维或三维空间里配置节点,节点之间用线连接,称为连线. ...
- D3.js 力导向图的拖拽(drag)与缩放(zoom)
不知道大家会不会跟我一样遇到这样的问题,在之前做的力导向图的基础上加上缩放功能的时候,拖动节点时整体会平移不再是之前酷炫的效果(失去了拉扯的感觉!).天啊,简直不能接受如此丑X的效果.经过不懈的努力终 ...
- 记录d3.js 力导向图的平移缩放,类似地图导航点击某一项移动到当前位置
项目中有用到d3.js用于图结构的查询, 需求如下: 右上角有个模糊搜索功能,查询出来的结果用列表展示 点击列表的某一列,要求画布移动到当前选中的节点的位置,基于画布正中间 搜索出来的结果列表展示用的 ...
- D3.js 力导向图(小气泡围绕中心气泡)
html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3 ...
- Vue和d3.js(v4)力导向图force结合使用,v3版本升级v4【一】
前段时间因为参与项目涉密,所以一直没有更新博客,有些博友给我私信或者留言要部分博文的源码,因为我的电脑更换,demo的源码没有备份 所以无法提供.大家可针对具体问题问我,有空我定会回复的.另外转发文章 ...
随机推荐
- 负载均衡之Ocelot
Ocelot 负载均衡: 背景知识,ocelot是基于 webapi 的网关框架,要使用ocelot来做路由转发和负载均衡,需要创建一个webapi,然后以这个webapi来做gateway. ...
- Shiro_DelegatingFilterProxy
1.DelegatingFilterProxy实际上是Filter的一个代理对象.默认情况下,Spring会到IOC容器中查找与<filter-name>对应的filter bean.也可 ...
- 【codeforces 3C】Tic-tac-toe
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 写一个函数判断当前局面是否有人赢. 然后枚举上一个人的棋子下在哪个地方. 然后把他撤回 看看撤回前是不是没人赢然后没撤回之前是不是有人赢了. ...
- noip模拟赛 密码
题目描述 YJC把核弹发射密码忘掉了……其实是密码被加密了,但是YJC不会解密.密码由n个数字组成,第i个数字被加密成了如下形式:第k小的满足(2^L)|(P-1)且P为质数的P.YJC希望你能帮他算 ...
- [K/3Cloud]关于数据库sa密码更改,管理中心登录不上的问题。
有时候可能应为别的原因可能一不小心更改了数据库的密码,导致K/3 Cloud管理中心和单据打不开. 这个时候其实只要在注册一下就能解决了,在浏览器中输入http://192.168.25.35:800 ...
- 建立DJANGO的自定义TAG
DJANGO的TAG分为三类: • simple_tag : Processes the data and returns a string• inclusion_tag : Processes th ...
- - > 网络流(【最大流】草地排水模板题)
1993 草地排水 USACO 时间限制: 2 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 在农夫约翰的农场上,每 ...
- 今天開始慢下脚步,開始ios技术知识的查漏补缺。
从2014.6.30 開始工作算起. 如今已经是第416天了.不止不觉.时间过的真快. 通过对之前工作的总结.发现,你的知识面.会决定你面对问题时的态度.过程和结果. 简单来讲.知识面拓展了,你才干有 ...
- C++对象模型——继承体系下的对象构造(第五章)
5.2 继承体系下的对象构造 当定义一个object例如以下: T object; 时,实际上会发生什么事情呢?假设T有一个constructor(不论是由user提供或是由编译器合成),它会被调用. ...
- 如何使用IVT BlueSoleil 如何在电脑上使用蓝牙耳机
1 确保电脑上有蓝牙适配器 (现在很多电脑是不配蓝牙的),如果没有,网上买个蓝牙适配去,十几块钱很便宜.好了之后装一个下面这个软件,然后搜索蓝牙耳机,下面的状态栏就是"搜索设备" ...