Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
x649585723
incubator-echarts
提交
db308726
I
incubator-echarts
项目概览
x649585723
/
incubator-echarts
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
I
incubator-echarts
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
db308726
编写于
12月 09, 2015
作者:
L
lang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add force layout
上级
456cffcc
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
342 addition
and
75 deletion
+342
-75
src/chart/geoLine/GeoLineView.js
src/chart/geoLine/GeoLineView.js
+2
-0
src/chart/graph.js
src/chart/graph.js
+1
-0
src/chart/graph/GraphSeries.js
src/chart/graph/GraphSeries.js
+5
-0
src/chart/graph/GraphView.js
src/chart/graph/GraphView.js
+14
-1
src/chart/graph/circularLayout.js
src/chart/graph/circularLayout.js
+2
-41
src/chart/graph/circularLayoutHelper.js
src/chart/graph/circularLayoutHelper.js
+45
-0
src/chart/graph/forceHelper.js
src/chart/graph/forceHelper.js
+128
-0
src/chart/graph/forceLayout.js
src/chart/graph/forceLayout.js
+84
-0
src/chart/graph/simpleLayout.js
src/chart/graph/simpleLayout.js
+2
-26
src/chart/graph/simpleLayoutHelper.js
src/chart/graph/simpleLayoutHelper.js
+28
-0
src/chart/helper/EffectLine.js
src/chart/helper/EffectLine.js
+3
-0
src/chart/helper/Line.js
src/chart/helper/Line.js
+4
-1
src/data/Graph.js
src/data/Graph.js
+23
-5
test/graph.html
test/graph.html
+1
-1
未找到文件。
src/chart/geoLine/GeoLineView.js
浏览文件 @
db308726
...
...
@@ -29,6 +29,8 @@ define(function (require) {
var
trailLength
=
seriesModel
.
get
(
'
effect.trailLength
'
);
var
zr
=
api
.
getZr
();
// Avoid the drag cause ghost shadow
// FIXME Better way ?
zr
.
painter
.
getLayer
(
zlevel
).
clear
(
true
);
// Config layer with motion blur
if
(
this
.
_lastZlevel
!=
null
)
{
...
...
src/chart/graph.js
浏览文件 @
db308726
...
...
@@ -17,6 +17,7 @@ define(function (require) {
echarts
.
registerLayout
(
require
(
'
./graph/simpleLayout
'
));
echarts
.
registerLayout
(
require
(
'
./graph/circularLayout
'
));
echarts
.
registerLayout
(
require
(
'
./graph/forceLayout
'
));
// Graph view coordinate system
echarts
.
registerCoordinateSystem
(
'
graphView
'
,
{
...
...
src/chart/graph/GraphSeries.js
浏览文件 @
db308726
...
...
@@ -112,6 +112,11 @@ define(function (require) {
layout
:
null
,
// Configuration of force
force
:
{
initLayout
:
null
},
x
:
'
center
'
,
y
:
'
center
'
,
x2
:
null
,
...
...
src/chart/graph/GraphView.js
浏览文件 @
db308726
...
...
@@ -62,7 +62,6 @@ define(function (require) {
});
});
// Save the original lineWidth
data
.
graph
.
eachEdge
(
function
(
edge
)
{
edge
.
__lineWidth
=
edge
.
getModel
(
'
lineStyle.normal
'
).
get
(
'
width
'
);
...
...
@@ -80,6 +79,20 @@ define(function (require) {
this
.
_updateNodeAndLinkScale
();
this
.
_updateController
(
seriesModel
,
coordSys
,
api
);
if
(
seriesModel
.
forceLayout
)
{
this
.
_startForceLayoutIteration
(
seriesModel
.
forceLayout
);
}
},
_startForceLayoutIteration
:
function
(
forceLayout
)
{
var
self
=
this
;
(
function
step
()
{
forceLayout
.
step
(
function
(
stopped
)
{
self
.
updateLayout
();
!
stopped
&&
setTimeout
(
step
,
16
);
});
})();
},
_updateController
:
function
(
seriesModel
,
coordSys
,
api
)
{
...
...
src/chart/graph/circularLayout.js
浏览文件 @
db308726
define
(
function
(
require
)
{
var
circularLayoutHelper
=
require
(
'
./circularLayoutHelper
'
);
return
function
(
ecModel
,
api
)
{
ecModel
.
eachSeriesByType
(
'
graph
'
,
function
(
seriesModel
)
{
if
(
seriesModel
.
get
(
'
layout
'
)
===
'
circular
'
)
{
var
coordSys
=
seriesModel
.
coordinateSystem
;
if
(
coordSys
&&
coordSys
.
type
!==
'
view
'
)
{
return
;
}
var
rect
=
coordSys
.
getBoundingRect
();
var
nodeData
=
seriesModel
.
getData
();
var
graph
=
nodeData
.
graph
;
var
angle
=
0
;
var
unitAngle
=
Math
.
PI
*
2
/
nodeData
.
getSum
(
'
value
'
);
var
cx
=
rect
.
width
/
2
+
rect
.
x
;
var
cy
=
rect
.
height
/
2
+
rect
.
y
;
var
r
=
Math
.
min
(
rect
.
width
,
rect
.
height
)
/
2
;
graph
.
eachNode
(
function
(
node
)
{
var
value
=
node
.
getValue
(
'
value
'
);
angle
+=
unitAngle
*
value
/
2
;
node
.
setLayout
([
r
*
Math
.
cos
(
angle
)
+
cx
,
r
*
Math
.
sin
(
angle
)
+
cy
]);
angle
+=
unitAngle
*
value
/
2
;
});
graph
.
eachEdge
(
function
(
edge
)
{
var
curveness
=
edge
.
getModel
().
get
(
'
lineStyle.normal.curveness
'
);
var
p1
=
edge
.
node1
.
getLayout
();
var
p2
=
edge
.
node2
.
getLayout
();
var
cp1
;
if
(
curveness
>
0
)
{
cp1
=
[
cx
,
cy
];
}
edge
.
setLayout
([
p1
,
p2
,
cp1
]);
});
circularLayoutHelper
(
seriesModel
);
}
});
};
...
...
src/chart/graph/circularLayoutHelper.js
0 → 100644
浏览文件 @
db308726
define
(
function
(
require
)
{
return
function
(
seriesModel
)
{
var
coordSys
=
seriesModel
.
coordinateSystem
;
if
(
coordSys
&&
coordSys
.
type
!==
'
view
'
)
{
return
;
}
var
rect
=
coordSys
.
getBoundingRect
();
var
nodeData
=
seriesModel
.
getData
();
var
graph
=
nodeData
.
graph
;
var
angle
=
0
;
var
unitAngle
=
Math
.
PI
*
2
/
nodeData
.
getSum
(
'
value
'
);
var
cx
=
rect
.
width
/
2
+
rect
.
x
;
var
cy
=
rect
.
height
/
2
+
rect
.
y
;
var
r
=
Math
.
min
(
rect
.
width
,
rect
.
height
)
/
2
;
graph
.
eachNode
(
function
(
node
)
{
var
value
=
node
.
getValue
(
'
value
'
);
angle
+=
unitAngle
*
value
/
2
;
node
.
setLayout
([
r
*
Math
.
cos
(
angle
)
+
cx
,
r
*
Math
.
sin
(
angle
)
+
cy
]);
angle
+=
unitAngle
*
value
/
2
;
});
graph
.
eachEdge
(
function
(
edge
)
{
var
curveness
=
edge
.
getModel
().
get
(
'
lineStyle.normal.curveness
'
)
||
0
;
var
p1
=
edge
.
node1
.
getLayout
();
var
p2
=
edge
.
node2
.
getLayout
();
var
cp1
;
if
(
curveness
>
0
)
{
cp1
=
[
cx
,
cy
];
}
edge
.
setLayout
([
p1
,
p2
,
cp1
]);
});
};
});
\ No newline at end of file
src/chart/graph/forceHelper.js
0 → 100644
浏览文件 @
db308726
define
(
function
(
require
)
{
var
vec2
=
require
(
'
zrender/core/vector
'
);
var
scaleAndAdd
=
vec2
.
scaleAndAdd
;
function
adjacentNode
(
n
,
e
)
{
return
e
.
n1
===
n
?
e
.
n2
:
e
.
n1
;
}
return
function
(
nodes
,
edges
,
opts
)
{
var
width
=
opts
.
width
||
500
;
var
height
=
opts
.
height
||
500
;
var
center
=
opts
.
center
||
[
width
/
2
,
height
/
2
];
var
scale
=
opts
.
scale
||
1
;
var
gravity
=
opts
.
gravity
==
null
?
1
:
opts
.
gravity
;
for
(
var
i
=
0
;
i
<
edges
.
length
;
i
++
)
{
var
e
=
edges
[
i
];
e
.
n1
.
edges
=
e
.
n1
.
edges
||
[];
e
.
n2
.
edges
=
e
.
n2
.
edges
||
[];
e
.
n1
.
edges
.
push
(
e
);
e
.
n2
.
edges
.
push
(
e
);
}
// Init position
for
(
var
i
=
0
;
i
<
nodes
.
length
;
i
++
)
{
var
n
=
nodes
[
i
];
if
(
!
n
.
p
)
{
// Use the position from first adjecent node with defined position
// Or use a random position
// From d3
var
j
=
-
1
;
while
(
++
j
<
n
.
edges
.
length
)
{
var
e
=
n
.
edges
[
j
];
var
other
=
adjacentNode
(
n
,
e
);
if
(
other
.
p
)
{
n
.
p
=
vec2
.
clone
(
other
.
p
);
break
;
}
}
if
(
!
n
.
p
)
{
n
.
p
=
vec2
.
create
(
width
*
(
Math
.
random
()
-
0.5
)
+
center
[
0
],
height
*
(
Math
.
random
()
-
0.5
)
+
center
[
1
]
);
}
}
n
.
pp
=
vec2
.
clone
(
n
.
p
);
n
.
f
=
[
0
,
0
];
n
.
edges
=
null
;
}
// Formula in 'Graph Drawing by Force-directed Placement'
var
k
=
0.5
*
scale
*
Math
.
sqrt
(
width
*
height
/
nodes
.
length
);
var
k2
=
k
*
k
;
var
friction
=
1
;
return
{
warmUp
:
function
()
{
friction
=
0.7
;
},
step
:
function
(
cb
)
{
var
v12
=
[];
var
nLen
=
nodes
.
length
;
// Reset
for
(
var
i
=
0
;
i
<
nLen
;
i
++
)
{
vec2
.
set
(
nodes
[
i
].
f
,
0
,
0
);
}
// Repulsive
for
(
var
i
=
0
;
i
<
nLen
;
i
++
)
{
var
n1
=
nodes
[
i
];
for
(
var
j
=
i
+
1
;
j
<
nLen
;
j
++
)
{
var
n2
=
nodes
[
j
];
vec2
.
sub
(
v12
,
n2
.
p
,
n1
.
p
);
var
d
=
vec2
.
len
(
v12
);
// Ignore repulse larger than 500
if
(
d
>
500
)
{
continue
;
}
if
(
d
<
5
)
{
d
=
5
;
}
// k * k / d
var
repFact
=
(
n1
.
w
+
n2
.
w
)
*
k2
/
d
/
d
;
scaleAndAdd
(
n1
.
f
,
n1
.
f
,
v12
,
-
repFact
);
scaleAndAdd
(
n2
.
f
,
n2
.
f
,
v12
,
repFact
);
}
}
for
(
var
i
=
0
;
i
<
edges
.
length
;
i
++
)
{
var
e
=
edges
[
i
];
var
n1
=
e
.
n1
;
var
n2
=
e
.
n2
;
vec2
.
sub
(
v12
,
n2
.
p
,
n1
.
p
);
var
d2
=
vec2
.
lenSquare
(
v12
);
if
(
d2
===
0
)
{
continue
;
}
// d * d / k
var
attrFact
=
e
.
w
*
Math
.
sqrt
(
d2
)
/
k
;
scaleAndAdd
(
n1
.
f
,
n1
.
f
,
v12
,
attrFact
);
scaleAndAdd
(
n2
.
f
,
n2
.
f
,
v12
,
-
attrFact
);
}
// Gravity
for
(
var
i
=
0
;
i
<
nLen
;
i
++
){
var
n
=
nodes
[
i
];
vec2
.
sub
(
v12
,
center
,
n
.
p
);
var
forceFactor
=
vec2
.
len
(
v12
)
*
gravity
/
1000
;
vec2
.
scaleAndAdd
(
n
.
f
,
n
.
f
,
v12
,
forceFactor
);
}
var
v
=
[];
for
(
var
i
=
0
;
i
<
nLen
;
i
++
)
{
var
n
=
nodes
[
i
];
vec2
.
sub
(
v
,
n
.
p
,
n
.
pp
);
vec2
.
add
(
v
,
v
,
vec2
.
scale
(
n
.
f
,
n
.
f
,
friction
/
100
));
vec2
.
add
(
n
.
p
,
n
.
p
,
v
);
vec2
.
copy
(
n
.
pp
,
n
.
p
);
}
friction
=
friction
*
0.99
;
cb
&&
cb
(
nodes
,
edges
,
friction
<
0.012
);
}
};
};
});
\ No newline at end of file
src/chart/graph/forceLayout.js
0 → 100644
浏览文件 @
db308726
define
(
function
(
require
)
{
var
forceHelper
=
require
(
'
./forceHelper
'
);
var
numberUtil
=
require
(
'
../../util/number
'
);
var
simpleLayoutHelper
=
require
(
'
./simpleLayoutHelper
'
);
var
circularLayoutHelper
=
require
(
'
./circularLayoutHelper
'
);
return
function
(
ecModel
,
api
)
{
ecModel
.
eachSeriesByType
(
'
graph
'
,
function
(
graphSeries
)
{
if
(
graphSeries
.
get
(
'
layout
'
)
===
'
force
'
)
{
var
forceModel
=
graphSeries
.
getModel
(
'
force
'
);
var
initLayout
=
forceModel
.
get
(
'
initLayout
'
);
if
(
!
initLayout
||
initLayout
===
'
none
'
)
{
simpleLayoutHelper
(
graphSeries
);
}
else
if
(
initLayout
===
'
circular
'
)
{
circularLayoutHelper
(
graphSeries
);
}
var
graph
=
graphSeries
.
getGraph
();
var
nodeData
=
graph
.
data
;
var
edgeData
=
graph
.
edgeData
;
var
nodeDataExtent
=
nodeData
.
getDataExtent
(
'
value
'
);
var
edgeDataExtent
=
edgeData
.
getDataExtent
(
'
value
'
);
var
nodes
=
nodeData
.
mapArray
(
'
value
'
,
function
(
value
,
idx
)
{
var
point
=
nodeData
.
getItemLayout
(
idx
);
var
w
=
numberUtil
.
linearMap
(
value
,
nodeDataExtent
,
[
0
,
1
]);
return
{
w
:
isNaN
(
w
)
?
0.5
:
w
,
p
:
(
isNaN
(
point
[
0
])
||
isNaN
(
point
[
1
]))
?
null
:
point
};
});
var
edges
=
edgeData
.
mapArray
(
'
value
'
,
function
(
value
,
idx
)
{
var
edge
=
graph
.
getEdgeByIndex
(
idx
);
var
w
=
numberUtil
.
linearMap
(
value
,
edgeDataExtent
,
[
0
,
1
]);
return
{
w
:
isNaN
(
w
)
?
0.5
:
w
,
n1
:
nodes
[
edge
.
node1
.
dataIndex
],
n2
:
nodes
[
edge
.
node2
.
dataIndex
],
curveness
:
edge
.
getModel
().
get
(
'
lineStyle.normal.curveness
'
)
||
0
};
});
var
coordSys
=
graphSeries
.
coordinateSystem
;
var
rect
=
coordSys
.
getBoundingRect
();
var
forceInstance
=
forceHelper
(
nodes
,
edges
,
{
width
:
rect
.
width
,
height
:
rect
.
height
,
center
:
[
rect
.
x
+
rect
.
width
/
2
,
rect
.
y
+
rect
.
height
/
2
]
});
var
oldStep
=
forceInstance
.
step
;
forceInstance
.
step
=
function
(
cb
)
{
oldStep
(
function
(
nodes
,
edges
,
stopped
)
{
for
(
var
i
=
0
,
l
=
nodes
.
length
;
i
<
l
;
i
++
)
{
graph
.
getNodeByIndex
(
i
).
setLayout
(
nodes
[
i
].
p
);
}
for
(
var
i
=
0
,
l
=
edges
.
length
;
i
<
l
;
i
++
)
{
var
e
=
edges
[
i
];
var
p1
=
e
.
n1
.
p
;
var
p2
=
e
.
n2
.
p
;
var
points
=
[
p1
,
p2
];
if
(
e
.
curveness
>
0
)
{
points
.
push
([
(
p1
[
0
]
+
p2
[
0
])
/
2
-
(
p1
[
1
]
-
p2
[
1
])
*
e
.
curveness
,
(
p1
[
1
]
+
p2
[
1
])
/
2
-
(
p2
[
0
]
-
p1
[
0
])
*
e
.
curveness
]);
}
graph
.
getEdgeByIndex
(
i
).
setLayout
(
points
);
}
// Update layout
cb
&&
cb
(
stopped
);
});
};
graphSeries
.
forceLayout
=
forceInstance
;
}
else
{
// Remove prev injected forceLayout instance
graphSeries
.
forceLayout
=
null
;
}
});
};
});
\ No newline at end of file
src/chart/graph/simpleLayout.js
浏览文件 @
db308726
define
(
function
(
require
)
{
var
simpleLayoutHelper
=
require
(
'
./simpleLayoutHelper
'
);
return
function
(
ecModel
,
api
)
{
ecModel
.
eachSeriesByType
(
'
graph
'
,
function
(
seriesModel
)
{
var
layout
=
seriesModel
.
get
(
'
layout
'
);
if
(
!
layout
||
layout
===
'
none
'
)
{
var
coordSys
=
seriesModel
.
coordinateSystem
;
if
(
coordSys
&&
coordSys
.
type
!==
'
view
'
)
{
return
;
}
var
graph
=
seriesModel
.
getGraph
();
graph
.
eachNode
(
function
(
node
)
{
var
model
=
node
.
getModel
();
node
.
setLayout
([
+
model
.
get
(
'
x
'
),
+
model
.
get
(
'
y
'
)]);
});
graph
.
eachEdge
(
function
(
edge
)
{
var
curveness
=
edge
.
getModel
().
get
(
'
lineStyle.normal.curveness
'
);
var
p1
=
edge
.
node1
.
getLayout
();
var
p2
=
edge
.
node2
.
getLayout
();
var
cp1
;
if
(
curveness
>
0
)
{
cp1
=
[
(
p1
[
0
]
+
p2
[
0
])
/
2
-
(
p1
[
1
]
-
p2
[
1
])
*
curveness
,
(
p1
[
1
]
+
p2
[
1
])
/
2
-
(
p2
[
0
]
-
p1
[
0
])
*
curveness
];
}
edge
.
setLayout
([
p1
,
p2
,
cp1
]);
});
simpleLayoutHelper
(
seriesModel
);
}
});
};
...
...
src/chart/graph/simpleLayoutHelper.js
0 → 100644
浏览文件 @
db308726
define
(
function
(
require
)
{
return
function
(
seriesModel
)
{
var
coordSys
=
seriesModel
.
coordinateSystem
;
if
(
coordSys
&&
coordSys
.
type
!==
'
view
'
)
{
return
;
}
var
graph
=
seriesModel
.
getGraph
();
graph
.
eachNode
(
function
(
node
)
{
var
model
=
node
.
getModel
();
node
.
setLayout
([
+
model
.
get
(
'
x
'
),
+
model
.
get
(
'
y
'
)]);
});
graph
.
eachEdge
(
function
(
edge
)
{
var
curveness
=
edge
.
getModel
().
get
(
'
lineStyle.normal.curveness
'
)
||
0
;
var
p1
=
edge
.
node1
.
getLayout
();
var
p2
=
edge
.
node2
.
getLayout
();
var
cp1
;
if
(
curveness
>
0
)
{
cp1
=
[
(
p1
[
0
]
+
p2
[
0
])
/
2
-
(
p1
[
1
]
-
p2
[
1
])
*
curveness
,
(
p1
[
1
]
+
p2
[
1
])
/
2
-
(
p2
[
0
]
-
p1
[
0
])
*
curveness
];
}
edge
.
setLayout
([
p1
,
p2
,
cp1
]);
});
};
});
\ No newline at end of file
src/chart/helper/EffectLine.js
浏览文件 @
db308726
...
...
@@ -51,6 +51,8 @@ define(function (require) {
var
ty
=
quadraticDerivativeAt
(
p1
[
1
],
cp1
[
1
],
p2
[
1
],
t
);
this
.
rotation
=
-
Math
.
atan2
(
ty
,
tx
)
-
Math
.
PI
/
2
;
this
.
ignore
=
false
;
}
effectLineProto
.
_updateEffectSymbol
=
function
(
lineData
,
idx
)
{
...
...
@@ -68,6 +70,7 @@ define(function (require) {
symbol
=
symbolUtil
.
createSymbol
(
symbolType
,
-
0.5
,
-
0.5
,
1
,
1
,
color
);
symbol
.
ignore
=
true
;
symbol
.
z2
=
100
;
this
.
_symbolType
=
symbolType
;
this
.
_period
=
period
;
...
...
src/chart/helper/Line.js
浏览文件 @
db308726
...
...
@@ -36,7 +36,10 @@ define(function (require) {
function
createLine
(
points
)
{
var
line
=
new
LinePath
({
name
:
'
line
'
name
:
'
line
'
,
style
:
{
strokeNoScale
:
true
}
});
setLinePoints
(
line
.
shape
,
points
);
return
line
;
...
...
src/data/Graph.js
浏览文件 @
db308726
...
...
@@ -94,6 +94,15 @@ define(function(require) {
return
node
;
};
/**
* Get node by data index
* @param {number} dataIndex
* @return {module:echarts/data/Graph~Node}
*/
graphProto
.
getNodeByIndex
=
function
(
dataIndex
)
{
var
rawIdx
=
this
.
data
.
getRawIndex
(
dataIndex
);
return
this
.
nodes
[
rawIdx
];
};
/**
* Get node by id
* @param {string} id
...
...
@@ -148,7 +157,16 @@ define(function(require) {
};
/**
* Get edge by two nodes
* Get edge by data index
* @param {number} dataIndex
* @return {module:echarts/data/Graph~Node}
*/
graphProto
.
getEdgeByIndex
=
function
(
dataIndex
)
{
var
rawIdx
=
this
.
edgeData
.
getRawIndex
(
dataIndex
);
return
this
.
edges
[
rawIdx
];
};
/**
* Get edge by two linked nodes
* @param {module:echarts/data/Graph.Node|string} n1
* @param {module:echarts/data/Graph.Node|string} n2
* @return {module:echarts/data/Graph.Edge}
...
...
@@ -254,11 +272,11 @@ define(function(require) {
};
// TODO
graphProto
.
depthFirstTraverse
=
function
(
cb
,
startNode
,
direction
,
context
)
{
//
graphProto.depthFirstTraverse = function (
//
cb, startNode, direction, context
//
) {
};
//
};
// Filter update
graphProto
.
update
=
function
()
{
...
...
test/graph.html
浏览文件 @
db308726
...
...
@@ -64,7 +64,7 @@
}
},
animationDurationUpdate
:
1500
,
animationEasing
:
'
quinticInOut
'
,
animationEasing
Update
:
'
quinticInOut
'
,
series
:
[
{
name
:
'
Les Miserables
'
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录