我想在javascript中使用时间轴创建动态变化的图形,这看起来像this。 编辑:我想自己决定哪个节点应该在哪个时间片。
我想知道,是否有一个我可以用来做这个的库,或者我需要自己创建它(通过简单地画在画布上)?我试图找到一个,但似乎有很多时间轴和图形的实现,但很难找到这两者的组合。最合适的解决方案是使用gojs。但是我无法创建一个包含两个父节点的节点,因为它是作为树数据结构实现的。
答案 0 :(得分:2)
你可能不得不玩数学,但我希望这将有用作为一个起点:
DEMO :JSFiddle
<强> HTML 强>
<div id='board'>
<div id='titles'></div>
</div>
<强> CSS 强>
#board {
position: relative;
width: 500px;
height: 600px;
background-color:#f83213;
}
#titles {
color: #ffffff;
width: 100%;
height: 18px;
font-size: 12px;
}
#titles div {
display:inline-block;
margin: 10px;
}
.event{
border: 0px;
background-color: #3a2356;
color: #ffffff;
width: 18px;
height: 18px;
position: absolute;
padding: 4px;
font-size: 18px;
z-index: 2;
}
.line{
height: 1px;
width: 60px;
background-color: #3a2356;
position: absolute;
z-index: 1;
}
** JavaScript **
var margin = 20;
var events = {
"A": {
day: 0,
indexInDay: 0,
lineTos: ["D"]
},
"B": {
day: 0,
indexInDay: 1,
lineTos: ["D"]
},
"D": {
day: 1,
indexInDay: 0,
lineTos: ["E","F"]
},
"E": {
day: 2,
indexInDay: 0,
lineTos: null
},
"C": {
day: 0,
indexInDay: 2,
lineTos: ["F"]
},
"F": {
day: 2,
indexInDay: 2,
lineTos: null
},
};
drawAll(events);
function drawAll(events) {
drawTitles(events);
drawEvents(events);
drawLines(events);
}
function drawTitles(events) {
var titles = document.getElementById('titles');
var max = 0;
for (var name in events) {
if (events[name].day > max)
max = events[name].day;
}
for (var i = 0 ; i <= max ; i++)
titles.innerHTML += '<div>' + 'Day' + i + '</div>';
}
function drawEvents(events) {
var board = document.getElementById('board');
for (var name in events) {
var ev = events[name];
var eventDiv = document.createElement('DIV');
board.appendChild(eventDiv);
eventDiv.className = 'event';
setTopLeftEvent(ev, eventDiv);
eventDiv.innerText = name;
}
}
function drawLines(events) {
var board = document.getElementById('board');
for (var name in events) {
var from = events[name];
var tos = from.lineTos;
if (!tos) continue;
for (var j = 0 ; j < tos.length ; j++) {
var to = events[tos[j]];
var lineDiv = document.createElement('DIV');
board.appendChild(lineDiv);
lineDiv.className = 'line';
setTopLeftLine(from, lineDiv);
lineDiv.style.width = margin + 1 * margin * distance(to.indexInDay,from.indexInDay,to.day, from.day) + 'px';
var tan = (to.indexInDay - from.indexInDay) / (to.day - from.day);
lineDiv.style.top = lineDiv.offsetTop + (tan * margin) +'px';
var angle = Math.atan(tan) * 180/Math.PI;
// Code for Safari
lineDiv.style.WebkitTransform = "rotate(" + angle + "deg)";
// Code for IE9
lineDiv.style.msTransform = "rotate(" + angle + "deg)";
// Standard syntax
lineDiv.style.transform = "rotate(" + angle + "deg)";
}
}
}
function distance(x1, y1, x2, y2){
var res = Math.sqrt((y2-y1)*(y2-y1) + (x2-x1)*(x2-x1));
return res;
}
function setTopLeftEvent(event, eventDiv) {
eventDiv.style.left = (margin + event.day * (margin * 2)) + 'px';
eventDiv.style.top = (margin * 2 + event.indexInDay * (margin * 2)) + 'px';
}
function setTopLeftLine(event, lineDiv) {
lineDiv.style.left = (margin + event.day * (margin * 2)) + 'px';
lineDiv.style.top = (margin * 2.5 + event.indexInDay * (margin * 2)) + 'px';
}
答案 1 :(得分:1)
正如文本中提到GoJS sample一样,很容易用 LayeredDigraphLayout 和 TreeModel 替换 TreeLayout GraphLinksModel 。这就是我刚刚修改样本所做的事情。
将SSH_ASKPASS
替换为go.TreeLayout
,以便自定义布局不再继承自TreeLayout。更改构造函数不要打扰设置TreeLayout特定属性。更改图表的布局以使用LayeredDigraphLayout特定属性:
go.LayeredDigraphLayout
使用包含所需数据的GraphLinksModel替换该样本的模型:
layout: $(LayeredTreeLayout, // custom layout is defined above
{
angle: HORIZONTAL ? 0 : 90,
columnSpacing: 5,
layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource
}),
如果没有更改任何模板或样式,结果是:
为了确保它有效,我还尝试设置// define the node data
var nodearray = [
{ // this is the information needed for the headers of the bands
key: "_BANDS",
category: "Bands",
itemArray: [
{ text: "Day 0" },
{ text: "Day 1" },
{ text: "Day 2" },
{ text: "Day 3" },
{ text: "Day 4" },
{ text: "Day 5" }
]
}
];
var linkarray = [
{ from: "A", to: "D" },
{ from: "B", to: "D" },
{ from: "D", to: "E" },
{ from: "D", to: "F" },
{ from: "C", to: "F" }
];
myDiagram.model = $(go.GraphLinksModel,
{ // automatically create node data objects for each "from" or "to" reference
// (set this property before setting the linkDataArray)
archetypeNodeData: {},
nodeDataArray: nodearray,
linkDataArray: linkarray
});
: