d3.v3实现分层分类可拖拽图表效果代码
代码语言:html
所属分类:图表
代码描述:d3.v3实现分层分类可拖拽图表效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<style>
.nodebox {
fill: #fff;
stroke: steelblue;
stroke-width: 3.5px;
}
#node_PHYSICAL .nodebox {
stroke: beige;
}
#node_PHYSICAL_HARD .nodebox {
stroke: tan;
}
#node_PHYSICAL_SOFT .nodebox {
stroke: yellow;
}
#node_BIOTA .nodebox {
stroke: darkgreen;
}
#node_BIOTA_SPONGES .nodebox {
stroke: orange;
}
#node_BIOTA_ALGAE .nodebox {
stroke: green;
}
#node_BIOTA_ALGAE_CANOPY_ECK .nodebox {
stroke: lightgreen;
}
#node_BIOTA_ALGAE_CRUSTOSE .nodebox {
stroke: purple;
}
.nodeTitle {
font: 8px sans-serif;
font-weight: bold;
}
.nodeText {
font: 8px sans-serif;
}
.f1Text {
fill: orange;
font-weight: bold;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 3.5px;
}
</style>
</head>
<body translate="no">
<div>This is not my code, just a port of <a href="" target="_blank">this</a> to codepen.</div>
<div>Drag to rearrange these nodes, then click
<button onclick="return refresh();">refresh data</button> Some nodes will be replaced.
</div>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/d3.v3.js"></script>
<script type="module">
function graph(d3) {
//step 0, new graph() ,import "https://d3js.org/d3.v3.min.js" to get d3
var svg;
//step 1, custom the config
this.config = {
bg_size: {
width: 800,
height: 600 },
edge_def_width: 5,
edge_show_arrow: true,
node_draggable: true,
show_performance_bar: false };
var self = this;
var cluster = d3.layout.cluster().size([self.config.bg_size.height, self.config.bg_size.width - 160]);
/// step 2, custom the actions
var showTitleAction;
var showSubheadAction;
var showPathDesc;
this.showTitle = function (f) {
showTitleAction = f;
};
this.showSubhead = function (f) {
showSubheadAction = f;
};
this.showPathDesc = function (f) {
showPathDesc = f;
};
/// final step , bind some data
this.bind = function (data) {
/**
忽略连通图中的回路,产生一棵树。
这棵树符合cluster.nodes(tree)的调用要求(参见:https://github.com/mbostock/d3/wiki/Cluster-Layout)
*/
var conv2tree = function (data) {
var root = self.getRoot(data);
var hasParentFlag = {}; //保证每个节点只有一个父节点,以便形成树状结构
hasParentFlag[root.id] = true; //根节点不允许作为子节点
self.traverseEdge(data, function (source, target) {//遍历每条边,即所有节点间关系
if (!hasParentFlag[target.id] && source.id != target.id) {//首次被遍历到的target,作为source的子节点,后续将不被其它节点作为子节点
if (!source.children) {
source.children = [];
}
source.children.push(target);
hasParentFlag[target.id] = true;
}
});
return root;
};
/**
通过cluster.nodes(tree),为tree的每个节点计算x,y,depth等属性以便定位
*/
var buildNodes = function (tree) {
return cluster.nodes(tree);
};
/**
建立节点之间各条边。
如果直接调用cluster.links(nodes),其只支持树状结构,回路会被丢弃,借此把所有边补充完整。
*/
var buildLinks = function (data) {
var result = [];
self.traverseEdge(data, function (source, target, ref) {
result.push({
'source': source,
'target': target,
'ref': ref });
});
return result;
};
/**
更新数据时保留原有节点的位置信息
*/
var merge = function (nodes, links) {
var oldData = [];
if (self.nodes) {//原nodes存在,输出oldData
self.nodes.forEach(function (d) {
oldData[d.id] = d;
});
}
if (oldData) {//用oldData里的数据覆盖现nodes里的数据
nodes.forEach(function (d) {
if (oldData[d.id]) {
d.x = oldData[d.id].x;
d.y = oldData[d.id].y;
}
});
}
self.nodes = nodes;
self.links = links;
};
//1)连通图->树 参见:https://github.com/mbostock/d3/wiki/Cluster-Layout)
//1)temporarily convert a connectivity to a tree
var tree = conv2tree(data);
//2)根据树状结构计算节点位置.
//2)caculate for nodes' coords with <code>cluster.nodes(tree);</code>
var nodes = buildNodes(tree);
//3)因为连通图是网状而非树状,将所有边补充完整
//3)fill in all the edges(links) of the connectivity
var links = buildLinks(data);
//4)与原有的数据做一次merge,保留位置等信息
//4)do merge to keep info like node's position
merge(nodes, links);
//5)重绘
//5)redraw
self.redraw();
};
/// call redraw() if necessary (reconfig,recostom the actions, etc. )
this.redraw = function () {
var fontSize = 8;
var lineSpace = 2;
var boxHeight = 50;
var boxWidth = 85;
var width = self.config.bg_size.width;
var height = self.config.bg_size.height;
var yscale_performancebar = d3.scale.linear().
domain([0, 1]).
rangeRound([boxHeight / 2, -boxHeight / 2]);
var diagonal = d3.svg.diagonal().
projection(function (d) {
return [d.y - boxWidth / 2, d.x];
});
var _clear = function () {
d3.select("svg").remove();
svg = d3.select("body").append("svg").
attr("width", width).
attr("height", height).
append("g").
attr("transform", "translate(80,0)");
svg.append("svg:defs").selectAll("marker").
data(["suit"]).
enter().append("svg:marker").
attr("id", "idArrow").
attr("viewBox", "0 -5 10 10").
attr("refX", 15).
attr("refY", -1.5).
attr("markerWidth", 6).
attr("markerHeight", 6).
attr("orient", "auto").
append("svg:path").
attr("d", "M0,-5L10,0L0,5");
};
var _redrawEdges = function () {
var linksWithArrow = self.links;
//to show arrow at the end of the path with fixed size, we have to copy each path with .stroke-width=1
if (self.config.edge_show_arrow) {
linksWithArrow = [];
self.links.forEach(function (d) {
var fake = {};
for (var prop in d) {
fake[prop] = d[prop];
}
fake.faked = true; //copy each path with .faked=true as flag
linksWithArrow.push(fake);
linksWithArrow.push(d);
});
}
var path = svg.selectAll(".link").data(linksWithArrow);
// when new path ar.........完整代码请登录后点击上方下载按钮下载查看
网友评论0