mirror of
https://github.com/TBEDP/datavjs.git
synced 2025-12-08 19:45:52 +00:00
Dag图
This commit is contained in:
parent
633a6a9d3b
commit
cec3edef4b
413
build/all.js
413
build/all.js
File diff suppressed because it is too large
Load Diff
@ -8382,7 +8382,7 @@ if (!JSON) {
|
||||
dH = endH - startH;
|
||||
dNum = endNum - startNum;
|
||||
}
|
||||
|
||||
|
||||
var h = (startH + dH * num) / 360;
|
||||
var s = (70 + Math.abs(4 - (startNum + dNum * num) % 8) * 5) / 100;
|
||||
var b = (100 - Math.abs(4 - (startNum + dNum * num) % 8) * 5) / 100;
|
||||
@ -8705,6 +8705,15 @@ if (!JSON) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建画布
|
||||
*/
|
||||
Chart.prototype.createCanvas = function () {
|
||||
var conf = this.defaults;
|
||||
this.node.style.position = "relative";
|
||||
this.paper = new Raphael(this.node, conf.width, conf.height);
|
||||
};
|
||||
|
||||
/**
|
||||
* 拥有一个组件
|
||||
*/
|
||||
|
||||
@ -7941,7 +7941,7 @@ if (!JSON) {
|
||||
dH = endH - startH;
|
||||
dNum = endNum - startNum;
|
||||
}
|
||||
|
||||
|
||||
var h = (startH + dH * num) / 360;
|
||||
var s = (70 + Math.abs(4 - (startNum + dNum * num) % 8) * 5) / 100;
|
||||
var b = (100 - Math.abs(4 - (startNum + dNum * num) % 8) * 5) / 100;
|
||||
@ -8264,6 +8264,15 @@ if (!JSON) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建画布
|
||||
*/
|
||||
Chart.prototype.createCanvas = function () {
|
||||
var conf = this.defaults;
|
||||
this.node.style.position = "relative";
|
||||
this.paper = new Raphael(this.node, conf.width, conf.height);
|
||||
};
|
||||
|
||||
/**
|
||||
* 拥有一个组件
|
||||
*/
|
||||
|
||||
413
build/datav.js
413
build/datav.js
File diff suppressed because it is too large
Load Diff
402
build/deps.js
402
build/deps.js
File diff suppressed because it is too large
Load Diff
413
build/v5.js
413
build/v5.js
File diff suppressed because it is too large
Load Diff
402
deps/raphael.js
vendored
402
deps/raphael.js
vendored
File diff suppressed because it is too large
Load Diff
63
example/dag/dag.html
Normal file
63
example/dag/dag.html
Normal file
@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Dag Graph</title>
|
||||
|
||||
<script src="../../build/deps.js"></script>
|
||||
<script src="../../lib/datav.js"></script>
|
||||
<script src="../../lib/components/dag.js"></script>
|
||||
<style type="text/css">
|
||||
#chart {
|
||||
border-top: 1px dashed #F00;
|
||||
border-bottom: 1px dashed #F00;
|
||||
padding-left: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="chart"></div>
|
||||
<script>
|
||||
// ├─┬ anywhere@0.0.2
|
||||
// │ └─┬ connect@2.7.1
|
||||
// │ ├── bytes@0.1.0
|
||||
// │ ├── cookie@0.0.5
|
||||
// │ ├── cookie-signature@0.0.1
|
||||
// │ ├── crc@0.2.0
|
||||
// │ ├── debug@0.7.0
|
||||
// │ ├── formidable@1.0.11
|
||||
// │ ├── fresh@0.1.0
|
||||
// │ ├── pause@0.0.1
|
||||
// │ ├── qs@0.5.1
|
||||
// │ └─┬ send@0.1.0
|
||||
// │ ├── mime@1.2.6
|
||||
// │ └── range-parser@0.0.4
|
||||
var source = [
|
||||
// name, dep, etc
|
||||
['anywhere', ['connect', 'eventproxy']],
|
||||
['connect', ['bytes', 'send', 'cookie', 'cookie-signature', 'crc', 'debug', 'formidable', 'fresh', 'pause', 'qs']],
|
||||
['send', ['mime', 'range-parser']],
|
||||
['mime'],
|
||||
['range-parser'],
|
||||
['bytes'],
|
||||
['cookie'],
|
||||
['cookie-signature'],
|
||||
['crc'],
|
||||
['debug'],
|
||||
['formidable'],
|
||||
['fresh'],
|
||||
['pause'],
|
||||
['qs'],
|
||||
['taobaoindex', ['eventproxy', 'connect']],
|
||||
['asynclist', ['eventproxy']],
|
||||
['eventproxy'],
|
||||
['datav', ['anywhere', 'eventproxy']],
|
||||
['mofang', ['connect', 'datav']],
|
||||
['taobaoindexapi', ['taobaoindex']]
|
||||
];
|
||||
var dag = new Dag('chart');
|
||||
dag.setSource(source);
|
||||
dag.render('eventproxy');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
316
lib/components/dag.js
Normal file
316
lib/components/dag.js
Normal file
@ -0,0 +1,316 @@
|
||||
/*global $, _, define */
|
||||
/*!
|
||||
* Stream的兼容定义
|
||||
*/
|
||||
;(function (name, definition) {
|
||||
if (typeof define === 'function') { // Module
|
||||
define(definition);
|
||||
} else { // Assign to common namespaces or simply the global object (window)
|
||||
this[name] = definition(function (id) { return this[id];});
|
||||
}
|
||||
})('Dag', function (require) {
|
||||
var DataV = require('DataV');
|
||||
|
||||
var Dag = DataV.extend(DataV.Chart, {
|
||||
initialize: function (node, options) {
|
||||
this.type = "Dag";
|
||||
this.node = this.checkContainer(node);
|
||||
this.defaults = {};
|
||||
// Properties
|
||||
this.defaults.width = 500;
|
||||
this.defaults.height = 500;
|
||||
|
||||
// Data bind
|
||||
/**
|
||||
* 柱纬度
|
||||
*/
|
||||
this.dimension.name = {
|
||||
type: "string",
|
||||
required: true,
|
||||
index: 0
|
||||
};
|
||||
/**
|
||||
* 横向纬度
|
||||
*/
|
||||
this.dimension.deps = {
|
||||
type: "string",
|
||||
required: true,
|
||||
index: 1
|
||||
};
|
||||
|
||||
/**
|
||||
* 横向纬度
|
||||
*/
|
||||
this.dimension.status = {
|
||||
type: "string",
|
||||
required: true,
|
||||
index: 2
|
||||
};
|
||||
// 设置选项
|
||||
this.setOptions(options);
|
||||
// 创建画布
|
||||
this.createCanvas(); // this.paper
|
||||
// 创建菜单
|
||||
this.createMenu(); // this.menu
|
||||
// 绑定右键事件
|
||||
this.initEvents();
|
||||
this.cache = {};
|
||||
this.connector = [];
|
||||
}
|
||||
});
|
||||
|
||||
Dag.prototype.setSource = function (source, map) {
|
||||
this.source = source;
|
||||
this.map(map);
|
||||
};
|
||||
|
||||
Dag.prototype.createMenu = function () {
|
||||
var that = this;
|
||||
var menu = $('<ul></ul>');
|
||||
menu.css({
|
||||
position: 'absolute',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
listStyleType: 'none'
|
||||
}).wall();
|
||||
var item = $('<li class="view_parent">查看父节点</li>');
|
||||
item.click(function () {
|
||||
that.showDeps();
|
||||
menu.wall();
|
||||
});
|
||||
var item2 = $('<li>查看子节点</li></ul>');
|
||||
item2.click(function () {
|
||||
that.showDepents();
|
||||
menu.wall();
|
||||
});
|
||||
var item3 = $('<li>隐藏节点</li></ul>');
|
||||
item3.click(function () {
|
||||
that.hideNode();
|
||||
menu.wall();
|
||||
});
|
||||
menu.append(item).append(item2).append(item3);
|
||||
this.menu = menu;
|
||||
$(this.node).append(menu);
|
||||
};
|
||||
|
||||
Dag.prototype.initEvents = function () {
|
||||
var that = this;
|
||||
|
||||
$(this.paper.canvas).on('contextmenu', function (e) {
|
||||
var elem = that.paper.getElementByPoint(e.pageX, e.pageY);
|
||||
if (elem && elem.data('name')) {
|
||||
that.expand(elem);
|
||||
}
|
||||
return false;
|
||||
}).click(function (e) {
|
||||
var elem = that.paper.getElementByPoint(e.pageX, e.pageY);
|
||||
if (elem && elem.data('name')) {
|
||||
that.toggle(elem);
|
||||
}
|
||||
that.menu.wall();
|
||||
}).dblclick(function (e) {
|
||||
// TODO: 双击事件
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 找出先前节点
|
||||
*/
|
||||
Dag.prototype.showDeps = function () {
|
||||
var that = this;
|
||||
var deps = this.getDeps(this.menu.data('name'));
|
||||
var node = this.menu.data('node');
|
||||
var bbox = node.getBBox();
|
||||
var pos = {
|
||||
x: bbox.x - 50
|
||||
};
|
||||
var half = (deps.length - 1) / 2;
|
||||
deps.forEach(function (name, i) {
|
||||
pos.y = bbox.y + (i - half) * 50;
|
||||
var from = that.drawNode(name, pos, node);
|
||||
that.drawLine(from, node);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 隐藏节点
|
||||
*/
|
||||
Dag.prototype.hideNode = function () {
|
||||
var name = this.menu.data('name');
|
||||
var froms = _.filter(this.connector, function (line) {
|
||||
return line[0] === name && line[3];
|
||||
});
|
||||
var tos = _.filter(this.connector, function (line) {
|
||||
return line[1] === name && line[3];
|
||||
});
|
||||
var set = this.cache[name].set;
|
||||
if (froms.length === 0 && tos.length === 0) {
|
||||
alert("唯一节点,不能隐藏");
|
||||
} else {
|
||||
if (froms.length === 0) {
|
||||
set.hide();
|
||||
tos.forEach(function (line) {
|
||||
line[2].hide();
|
||||
line[3] = false;
|
||||
});
|
||||
} else if (tos.length === 0) {
|
||||
set.hide();
|
||||
froms.forEach(function (line) {
|
||||
line[2].hide();
|
||||
line[3] = false;
|
||||
});
|
||||
} else {
|
||||
alert("还有相关节点,不能隐藏");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Dag.prototype.showDepents = function () {
|
||||
var that = this;
|
||||
var depents = this.getDependents(this.menu.data('name'));
|
||||
var node = this.menu.data('node');
|
||||
var bbox = node.getBBox();
|
||||
var pos = {
|
||||
x: bbox.x2 + 50
|
||||
};
|
||||
var half = (depents.length - 1) / 2;
|
||||
depents.forEach(function (name, i) {
|
||||
pos.y = bbox.y + (i - half) * 50;
|
||||
var to = that.drawNode(name, pos, node);
|
||||
that.drawLine(node, to);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 找出节点的依赖
|
||||
*/
|
||||
Dag.prototype.getDeps = function (name) {
|
||||
var mapping = this.mapping;
|
||||
var source = this.source;
|
||||
var item = _.find(source, function (item) {
|
||||
return item[mapping.name] === name;
|
||||
});
|
||||
var deps = item ? (item[mapping.deps] || []) : [];
|
||||
return deps;
|
||||
};
|
||||
|
||||
/**
|
||||
* 找出依赖它的节点
|
||||
*/
|
||||
Dag.prototype.getDependents = function (name) {
|
||||
var mapping = this.mapping;
|
||||
var source = this.source;
|
||||
return _.filter(source, function (item) {
|
||||
return _.indexOf(item[mapping.deps], name) !== -1;
|
||||
}).map(function (item) {
|
||||
return item[mapping.name];
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 展开右键菜单
|
||||
*/
|
||||
Dag.prototype.expand = function (elem) {
|
||||
var name = elem.data('name');
|
||||
var menu = this.menu;
|
||||
var bbox = elem.getBBox();
|
||||
menu.css({
|
||||
left: bbox.x + (bbox.width) / 2,
|
||||
top: bbox.y + (bbox.height) / 2
|
||||
})
|
||||
.unwall()
|
||||
.data('name', name)
|
||||
.data('node', elem);
|
||||
};
|
||||
|
||||
Dag.prototype.toggle = function (elem) {
|
||||
var name = elem.data('name');
|
||||
var mapping = this.mapping;
|
||||
var node = _.find(this.source, function (item) {
|
||||
return item[mapping.name] === name;
|
||||
});
|
||||
if (node[mapping.status]) {
|
||||
node[mapping.status] = false;
|
||||
this.cache[name].set[1].attr('fill', '#f00');
|
||||
} else {
|
||||
node[mapping.status] = true;
|
||||
this.cache[name].set[1].attr('fill', '#0f0');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 显示已经绘制的节点
|
||||
*/
|
||||
Dag.prototype.showNode = function (name, direction) {
|
||||
this.cache[name].set.show();
|
||||
// 显示连接线
|
||||
var line = _.find(this.connector, function (item) {
|
||||
var index = direction === 'to' ? 0 : 1;
|
||||
return item[index] === name;
|
||||
});
|
||||
if (line) {
|
||||
line[2].show();
|
||||
line[3] = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 绘制节点
|
||||
*/
|
||||
Dag.prototype.drawNode = function (nodeName, opts, direction) {
|
||||
var that = this;
|
||||
var item = _.find(this.source, function (item) {
|
||||
return item[that.mapping.name] === nodeName;
|
||||
});
|
||||
var name = item ? item[that.mapping.name] : 'unkown';
|
||||
|
||||
if (this.cache[name]) {
|
||||
this.showNode(name, direction);
|
||||
return this.cache[name].set[0];
|
||||
}
|
||||
|
||||
var pos = {
|
||||
x: 250,
|
||||
y: 250
|
||||
};
|
||||
|
||||
if (opts) {
|
||||
_.extend(pos, opts);
|
||||
}
|
||||
|
||||
var paper = this.paper;
|
||||
var set = paper.set();
|
||||
var text = paper.text(pos.x, pos.y, name);
|
||||
text.data('name', name);
|
||||
// Creates circle at x = 50, y = 40, with radius 10
|
||||
var width = text.getBBox().width;
|
||||
var radius = width / 2 + (width > 50 ? 2 : 5);
|
||||
var circle = paper.circle(pos.x, pos.y, radius);
|
||||
circle.toBack();
|
||||
// Sets the stroke attribute of the circle to white
|
||||
circle.attr("fill", "red").attr("stroke", "#000");
|
||||
this.cache[name] = {
|
||||
pos: pos,
|
||||
set: set.push(text, circle)
|
||||
};
|
||||
return text;
|
||||
};
|
||||
|
||||
Dag.prototype.drawLine = function (from, to) {
|
||||
var paper = this.paper;
|
||||
var pos = from.getMidpoint();
|
||||
var mid = to.getMidpoint();
|
||||
var path = "M" + pos.x + "," + pos.y + "L" + mid.x + "," + mid.y;
|
||||
var line = paper.path(path).toBack();
|
||||
this.connector.push([from.data('name'), to.data('name'), line, true]);
|
||||
};
|
||||
|
||||
/**
|
||||
* 渲染初始节点
|
||||
*/
|
||||
Dag.prototype.render = function (name) {
|
||||
this.drawNode(name);
|
||||
};
|
||||
|
||||
return Dag;
|
||||
});
|
||||
11
lib/datav.js
11
lib/datav.js
@ -235,7 +235,7 @@
|
||||
dH = endH - startH;
|
||||
dNum = endNum - startNum;
|
||||
}
|
||||
|
||||
|
||||
var h = (startH + dH * num) / 360;
|
||||
var s = (70 + Math.abs(4 - (startNum + dNum * num) % 8) * 5) / 100;
|
||||
var b = (100 - Math.abs(4 - (startNum + dNum * num) % 8) * 5) / 100;
|
||||
@ -558,6 +558,15 @@
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建画布
|
||||
*/
|
||||
Chart.prototype.createCanvas = function () {
|
||||
var conf = this.defaults;
|
||||
this.node.style.position = "relative";
|
||||
this.paper = new Raphael(this.node, conf.width, conf.height);
|
||||
};
|
||||
|
||||
/**
|
||||
* 拥有一个组件
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user