.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;
}
// 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
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 + ")";
}
D3.js力导向图(适用于其他类型图)中后添加元素遮盖已有元素的问题解决
上一篇说了在D3.js中动态增加节点及连线的一种实现方式,但是有后添加元素遮盖原节点的现象,这一篇说一下出现这个现象的解决办法. 在D3.js中后添加的元素是会遮盖先添加的元素的,同时还有一个设定:后 ...
D3.js 力导向图的显示优化
D3.js 作为一个前端,说到可视化除了听过 D3.js 的大名,常见的可视化库还有 ECharts.Chart.js,这两个库功能也很强大,但是有一个共同特点是封装层次高,留给开发者可设计和控制的部 ...
D3.js力导向图中新增节点及新增关系连线示例
大家在使用D3.js中的力导向图时,基本都会遇到动态增加节点及连线的需求,这里记录一下我的实现方式. 话不多说,先放代码:
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 .0" encoding="utf-8" ?>
TDD实践感悟
每个开发者都想开发出高质量的代码,更少的Bug.更容易维护不仅让人心情愉悦,也让我们有更多时间去学习和生活. 少加一些班,多陪家人,:) 当开发任务非常简单时,比如基本的增删改查,可能使用怎样的方式开 ...
esLint 配置
默认eslint规则: 代码末尾不能加分号 ;(强迫症的我受不了)代码中不能存在多行空行:(这个我更也忍不了)tab键不能使用,必须换成两个空格:(超级不习惯)代码中不能存在声明了但未使用的变量:(这 ...
python基础--模块使用
一:模块介绍 模块分为三种: 自定义模块 内置标准模块(又称标准库) 开源模块 自定义模块使用 # -*- coding:utf-8 -*- __author__ = 'shisanjun' &q ...
codevs 2292 图灵机游戏
2292 图灵机游戏 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 黄金 Gold 题目描述 Description [Shadow 1]第二题 Shadow最近知道了图灵 ...
【Mac】Docker安装及基础使用
Docker 安装 在 Mac OS X 系统中,首先你要下载安装包安装:Docker Toolbox 安装过程中,可以选择是否安装 Docker Machine,Docker Compose 等,默 ...