Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
半栈学徒
incubator-echarts
提交
5c41f814
I
incubator-echarts
项目概览
半栈学徒
/
incubator-echarts
与 Fork 源项目一致
从无法访问的项目Fork
通知
5
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,发现更多精彩内容 >>
提交
5c41f814
编写于
6月 21, 2013
作者:
K
kener
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
force拖拽事件~
上级
342c1a26
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
493 addition
and
428 deletion
+493
-428
src/chart/force.js
src/chart/force.js
+493
-428
未找到文件。
src/chart/force.js
浏览文件 @
5c41f814
/**
* echarts图表类:力导向图
* Copyright 2013 Baidu Inc. All rights reserved.
*
* @author pissang (shenyi01@baidu.com)
*
*/
define
(
function
(
require
)
{
/**
* 构造函数
* @param {Object} messageCenter echart消息中心
* @param {ZRender} zr zrender实例
* @param {Object} series 数据
* @param {Object} component 组件
*/
function
Force
(
messageCenter
,
zr
,
option
,
component
)
{
var
ComponentBase
=
require
(
'
../component/base
'
);
ComponentBase
.
call
(
this
,
zr
);
var
ecConfig
=
require
(
'
../config
'
);
var
ecData
=
require
(
'
../util/ecData
'
);
var
zrColor
=
require
(
'
zrender/tool/color
'
);
var
zrUtil
=
require
(
'
zrender/tool/util
'
);
var
vec2
=
require
(
'
zrender/tool/vector
'
);
var
self
=
this
;
self
.
type
=
ecConfig
.
CHART_TYPE_FORCE
;
var
series
;
var
nodeShapes
=
[];
var
linkShapes
=
[];
// 节点分类
var
categories
=
[];
// 默认节点样式
var
nodeStyle
;
// 默认边样式
var
linkStyle
;
// nodes和links的原始数据
var
nodesRawData
=
[];
var
linksRawData
=
[];
// nodes和links的权重, 用来计算引力和斥力
var
nodeWeights
=
[];
var
linkWeights
=
[];
// 节点的受力
var
nodeForces
=
[];
// 节点的加速度
var
nodeAccelerations
=
[];
// 节点的位置
var
nodePositions
=
[];
var
nodePrePositions
=
[];
// 节点的质量
var
nodeMasses
=
[];
var
temperature
;
var
k
;
var
density
;
var
stepTime
=
1
/
20
;
var
viewportWidth
;
var
viewportHeight
;
var
centroid
=
[];
function
_buildShape
()
{
temperature
=
1.0
;
viewportWidth
=
zr
.
getWidth
();
viewportHeight
=
zr
.
getHeight
();
centroid
=
[
viewportWidth
/
2
,
viewportHeight
/
2
]
for
(
var
i
=
0
,
l
=
series
.
length
;
i
<
l
;
i
++
)
{
var
serie
=
series
[
i
];
if
(
serie
.
type
===
ecConfig
.
CHART_TYPE_FORCE
)
{
series
[
i
]
=
self
.
reformOption
(
series
[
i
]);
var
minRadius
=
self
.
deepQuery
([
serie
],
'
minRadius
'
);
var
maxRadius
=
self
.
deepQuery
([
serie
],
'
maxRadius
'
);
density
=
self
.
deepQuery
([
serie
],
'
density
'
);
categories
=
self
.
deepQuery
([
serie
],
'
categories
'
);
linkStyle
=
self
.
deepQuery
([
serie
],
'
linkStyle
'
);
nodeStyle
=
self
.
deepQuery
([
serie
],
'
nodeStyle
'
);
nodesRawData
=
self
.
deepQuery
([
serie
],
'
nodes
'
);
linksRawData
=
self
.
deepQuery
([
serie
],
'
links
'
);
var
area
=
viewportWidth
*
viewportHeight
;
// Formula in 'Graph Drawing by Force-directed Placement'
k
=
0.5
*
Math
.
sqrt
(
area
/
nodesRawData
.
length
);
_buildLinkShapes
(
nodesRawData
,
linksRawData
);
_buildNodeShapes
(
nodesRawData
,
minRadius
,
maxRadius
);
}
}
}
function
_buildNodeShapes
(
nodes
,
minRadius
,
maxRadius
)
{
// 将值映射到minRadius-maxRadius的范围上
var
radius
=
[];
var
l
=
nodes
.
length
;
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
var
node
=
nodes
[
i
];
radius
.
push
(
node
.
value
);
}
_map
(
radius
,
radius
,
minRadius
,
maxRadius
);
_normalize
(
nodeWeights
,
radius
);
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
var
node
=
nodes
[
i
];
var
x
,
y
;
var
r
=
radius
[
i
];
var
random
=
_randomInSquare
(
viewportWidth
/
2
,
viewportHeight
/
2
,
300
);
x
=
typeof
(
node
.
initial
)
===
"
undefined
"
?
random
.
x
:
node
.
initial
.
x
;
y
=
typeof
(
node
.
initial
)
===
"
undefined
"
?
random
.
y
:
node
.
initial
.
y
;
// 初始化位置
nodePositions
[
i
]
=
[
x
,
y
];
nodePrePositions
[
i
]
=
[
x
,
y
];
// 初始化受力
nodeForces
[
i
]
=
[
0
,
0
];
// 初始化加速度
nodeAccelerations
[
i
]
=
[
0
,
0
];
// 初始化质量
nodeMasses
[
i
]
=
r
*
r
*
density
;
var
shape
=
{
id
:
zr
.
newShapeId
(
self
.
type
),
shape
:
'
circle
'
,
style
:
{
r
:
r
,
x
:
x
,
y
:
y
}
};
// 优先级 node.style > category.style > defaultStyle
zrUtil
.
merge
(
shape
.
style
,
nodeStyle
);
if
(
typeof
(
node
.
category
)
!==
'
undefined
'
)
{
var
category
=
categories
[
node
.
category
];
if
(
category
){
var
style
=
category
.
style
;
if
(
style
){
zrUtil
.
merge
(
shape
.
style
,
style
,
{
overwrite
:
true
});
}
}
}
if
(
typeof
(
node
.
style
)
!==
'
undefined
'
)
{
zrUtil
.
merge
(
shape
.
style
,
node
.
style
,
{
overwrite
:
true
});
}
nodeShapes
.
push
(
shape
);
self
.
shapeList
.
push
(
shape
);
zr
.
addShape
(
shape
);
}
// _normalize(nodeMasses, nodeMasses);
}
function
_buildLinkShapes
(
nodes
,
links
)
{
var
l
=
links
.
length
;
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
var
link
=
links
[
i
];
var
source
=
nodes
[
link
.
source
];
var
target
=
nodes
[
link
.
target
];
var
weight
=
link
.
weight
||
1
;
linkWeights
.
push
(
weight
);
var
shape
=
{
id
:
zr
.
newShapeId
(
self
.
type
),
shape
:
'
line
'
,
style
:
{
xStart
:
0
,
yStart
:
0
,
xEnd
:
0
,
yEnd
:
0
}
};
zrUtil
.
merge
(
shape
.
style
,
linkStyle
);
if
(
typeof
(
link
.
style
)
!==
'
undefined
'
)
{
zrUtil
.
merge
(
shape
.
style
,
link
.
style
,
{
overwrite
:
true
})
}
linkShapes
.
push
(
shape
);
self
.
shapeList
.
push
(
shape
);
zr
.
addShape
(
shape
);
}
_normalize
(
linkWeights
,
linkWeights
);
}
function
_updateLinkShapes
(){
for
(
var
i
=
0
,
l
=
linksRawData
.
length
;
i
<
l
;
i
++
)
{
var
link
=
linksRawData
[
i
];
var
linkShape
=
linkShapes
[
i
];
var
sourceShape
=
nodeShapes
[
link
.
source
];
var
targetShape
=
nodeShapes
[
link
.
target
];
linkShape
.
style
.
xStart
=
sourceShape
.
style
.
x
;
linkShape
.
style
.
yStart
=
sourceShape
.
style
.
y
;
linkShape
.
style
.
xEnd
=
targetShape
.
style
.
x
;
linkShape
.
style
.
yEnd
=
targetShape
.
style
.
y
;
}
}
function
_update
(
stepTime
)
{
var
len
=
nodePositions
.
length
;
var
v12
=
[];
// 计算节点之间斥力
var
k2
=
k
*
k
;
// Reset force
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
nodeForces
[
i
][
0
]
=
0
;
nodeForces
[
i
][
1
]
=
0
;
}
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
for
(
var
j
=
i
+
1
;
j
<
len
;
j
++
){
var
w1
=
nodeWeights
[
i
];
var
w2
=
nodeWeights
[
j
];
var
p1
=
nodePositions
[
i
];
var
p2
=
nodePositions
[
j
];
// 节点1到2的向量
vec2
.
sub
(
v12
,
p2
,
p1
);
var
d
=
vec2
.
length
(
v12
);
// 距离大于500忽略斥力
if
(
d
>
500
){
continue
;
}
vec2
.
scale
(
v12
,
v12
,
1
/
d
);
var
forceFactor
=
1
*
(
w1
+
w2
)
*
k2
/
d
;
vec2
.
scale
(
v12
,
v12
,
forceFactor
);
//节点1受到的力
vec2
.
sub
(
nodeForces
[
i
],
nodeForces
[
i
],
v12
);
//节点2受到的力
vec2
.
add
(
nodeForces
[
j
],
nodeForces
[
j
],
v12
);
}
}
// 计算节点之间引力
for
(
var
i
=
0
,
l
=
linksRawData
.
length
;
i
<
l
;
i
++
)
{
var
link
=
linksRawData
[
i
];
var
w
=
linkWeights
[
i
];
var
s
=
link
.
source
;
var
t
=
link
.
target
;
var
p1
=
nodePositions
[
s
];
var
p2
=
nodePositions
[
t
];
vec2
.
sub
(
v12
,
p2
,
p1
);
var
d2
=
vec2
.
lengthSquare
(
v12
);
vec2
.
normalize
(
v12
,
v12
);
var
forceFactor
=
w
*
d2
/
k
;
// 节点1受到的力
vec2
.
scale
(
v12
,
v12
,
forceFactor
);
vec2
.
add
(
nodeForces
[
s
],
nodeForces
[
s
],
v12
);
//节点2受到的力
vec2
.
sub
(
nodeForces
[
t
],
nodeForces
[
t
],
v12
);
}
// 到质心的向心力
for
(
var
i
=
0
,
l
=
nodesRawData
.
length
;
i
<
l
;
i
++
){
var
p
=
nodePositions
[
i
];
vec2
.
sub
(
v12
,
centroid
,
p
);
var
d2
=
vec2
.
lengthSquare
(
v12
);
vec2
.
normalize
(
v12
,
v12
);
// 100是可调参数
var
forceFactor
=
d2
/
100
;
vec2
.
scale
(
v12
,
v12
,
forceFactor
);
vec2
.
add
(
nodeForces
[
i
],
nodeForces
[
i
],
v12
);
}
// 计算加速度
for
(
var
i
=
0
,
l
=
nodeAccelerations
.
length
;
i
<
l
;
i
++
)
{
vec2
.
scale
(
nodeAccelerations
[
i
],
nodeForces
[
i
],
1
/
nodeMasses
[
i
]);
}
var
velocity
=
[];
var
tmp
=
[];
// 计算位置(verlet积分)
for
(
var
i
=
0
,
l
=
nodePositions
.
length
;
i
<
l
;
i
++
)
{
var
p
=
nodePositions
[
i
];
var
p_
=
nodePrePositions
[
i
];
vec2
.
sub
(
velocity
,
p
,
p_
);
p_
[
0
]
=
p
[
0
];
p_
[
1
]
=
p
[
1
];
vec2
.
add
(
velocity
,
velocity
,
vec2
.
scale
(
tmp
,
nodeAccelerations
[
i
],
stepTime
));
// Damping
vec2
.
scale
(
velocity
,
velocity
,
temperature
);
vec2
.
add
(
p
,
p
,
velocity
);
nodeShapes
[
i
].
style
.
x
=
p
[
0
];
nodeShapes
[
i
].
style
.
y
=
p
[
1
];
}
}
function
_step
(){
if
(
temperature
<
0.005
)
{
return
;
}
_update
(
stepTime
);
_updateLinkShapes
();
for
(
var
i
=
0
;
i
<
nodeShapes
.
length
;
i
++
)
{
var
shape
=
nodeShapes
[
i
];
zr
.
modShape
(
shape
.
id
,
shape
);
}
for
(
var
i
=
0
;
i
<
linkShapes
.
length
;
i
++
)
{
var
shape
=
linkShapes
[
i
];
zr
.
modShape
(
shape
.
id
,
shape
);
}
zr
.
refresh
();
// Cool Down
temperature
*=
0.999
;
}
function
init
(
newOption
,
newComponent
)
{
option
=
newOption
;
component
=
newComponent
;
series
=
option
.
series
;
self
.
clear
();
_buildShape
();
setInterval
(
function
(){
_step
();
},
stepTime
);
}
function
refresh
()
{
self
.
clear
();
_buildShape
();
}
self
.
init
=
init
;
self
.
refresh
=
refresh
;
init
(
option
,
component
);
}
function
_map
(
output
,
input
,
mappedMin
,
mappedMax
)
{
var
min
=
input
[
0
];
var
max
=
input
[
0
];
var
l
=
input
.
length
;
for
(
var
i
=
1
;
i
<
l
;
i
++
)
{
var
val
=
input
[
i
];
if
(
val
<
min
)
{
min
=
val
;
}
if
(
val
>
max
)
{
max
=
val
;
}
}
var
range
=
max
-
min
;
var
mappedRange
=
mappedMax
-
mappedMin
;
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
if
(
range
===
0
)
{
output
[
i
]
=
mappedMin
;
}
else
{
var
val
=
input
[
i
];
var
percent
=
(
val
-
min
)
/
range
;
output
[
i
]
=
mappedRange
*
percent
+
mappedMin
;
}
}
}
function
_normalize
(
output
,
input
)
{
var
l
=
input
.
length
;
var
max
=
input
[
0
];
for
(
var
i
=
1
;
i
<
l
;
i
++
)
{
if
(
input
[
i
]
>
max
)
{
max
=
input
[
i
];
}
}
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
output
[
i
]
=
input
[
i
]
/
max
;
}
}
function
_randomInCircle
(
x
,
y
,
radius
)
{
var
theta
=
Math
.
random
()
*
Math
.
PI
*
2
;
var
r
=
radius
*
Math
.
random
();
return
{
x
:
Math
.
cos
(
theta
)
*
r
+
x
,
y
:
Math
.
sin
(
theta
)
*
r
+
y
}
}
function
_randomInSquare
(
x
,
y
,
size
)
{
return
{
x
:
(
Math
.
random
()
-
0.5
)
*
size
+
x
,
y
:
(
Math
.
random
()
-
0.5
)
*
size
+
y
}
}
// 图表注册
require
(
'
../chart
'
).
define
(
'
force
'
,
Force
);
return
Force
;
/**
* echarts图表类:力导向图
* Copyright 2013 Baidu Inc. All rights reserved.
*
* @author pissang (shenyi01@baidu.com)
*
*/
define
(
function
(
require
)
{
/**
* 构造函数
* @param {Object} messageCenter echart消息中心
* @param {ZRender} zr zrender实例
* @param {Object} series 数据
* @param {Object} component 组件
*/
function
Force
(
messageCenter
,
zr
,
option
,
component
)
{
// 基类装饰
var
ComponentBase
=
require
(
'
../component/base
'
);
ComponentBase
.
call
(
this
,
zr
);
// 可计算特性装饰
var
CalculableBase
=
require
(
'
./calculableBase
'
);
CalculableBase
.
call
(
this
,
zr
,
option
);
var
ecConfig
=
require
(
'
../config
'
);
var
ecData
=
require
(
'
../util/ecData
'
);
var
zrConfig
=
require
(
'
zrender/config
'
);
var
zrEvent
=
require
(
'
zrender/tool/event
'
);
var
zrColor
=
require
(
'
zrender/tool/color
'
);
var
zrUtil
=
require
(
'
zrender/tool/util
'
);
var
vec2
=
require
(
'
zrender/tool/vector
'
);
var
self
=
this
;
self
.
type
=
ecConfig
.
CHART_TYPE_FORCE
;
var
series
;
var
nodeShapes
=
[];
var
linkShapes
=
[];
// 节点分类
var
categories
=
[];
// 默认节点样式
var
nodeStyle
;
// 默认边样式
var
linkStyle
;
// nodes和links的原始数据
var
nodesRawData
=
[];
var
linksRawData
=
[];
// nodes和links的权重, 用来计算引力和斥力
var
nodeWeights
=
[];
var
linkWeights
=
[];
// 节点的受力
var
nodeForces
=
[];
// 节点的加速度
var
nodeAccelerations
=
[];
// 节点的位置
var
nodePositions
=
[];
var
nodePrePositions
=
[];
// 节点的质量
var
nodeMasses
=
[];
var
temperature
;
var
k
;
var
density
;
var
stepTime
=
1
/
20
;
var
viewportWidth
;
var
viewportHeight
;
var
centroid
=
[];
function
_buildShape
()
{
temperature
=
1.0
;
viewportWidth
=
zr
.
getWidth
();
viewportHeight
=
zr
.
getHeight
();
centroid
=
[
viewportWidth
/
2
,
viewportHeight
/
2
]
for
(
var
i
=
0
,
l
=
series
.
length
;
i
<
l
;
i
++
)
{
var
serie
=
series
[
i
];
if
(
serie
.
type
===
ecConfig
.
CHART_TYPE_FORCE
)
{
series
[
i
]
=
self
.
reformOption
(
series
[
i
]);
var
minRadius
=
self
.
deepQuery
([
serie
],
'
minRadius
'
);
var
maxRadius
=
self
.
deepQuery
([
serie
],
'
maxRadius
'
);
density
=
self
.
deepQuery
([
serie
],
'
density
'
);
categories
=
self
.
deepQuery
([
serie
],
'
categories
'
);
linkStyle
=
self
.
deepQuery
([
serie
],
'
linkStyle
'
);
nodeStyle
=
self
.
deepQuery
([
serie
],
'
nodeStyle
'
);
nodesRawData
=
self
.
deepQuery
([
serie
],
'
nodes
'
);
linksRawData
=
self
.
deepQuery
([
serie
],
'
links
'
);
var
area
=
viewportWidth
*
viewportHeight
;
// Formula in 'Graph Drawing by Force-directed Placement'
k
=
0.5
*
Math
.
sqrt
(
area
/
nodesRawData
.
length
);
_buildLinkShapes
(
nodesRawData
,
linksRawData
);
_buildNodeShapes
(
nodesRawData
,
minRadius
,
maxRadius
);
}
}
}
function
_buildNodeShapes
(
nodes
,
minRadius
,
maxRadius
)
{
// 将值映射到minRadius-maxRadius的范围上
var
radius
=
[];
var
l
=
nodes
.
length
;
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
var
node
=
nodes
[
i
];
radius
.
push
(
node
.
value
);
}
_map
(
radius
,
radius
,
minRadius
,
maxRadius
);
_normalize
(
nodeWeights
,
radius
);
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
var
node
=
nodes
[
i
];
var
x
,
y
;
var
r
=
radius
[
i
];
var
random
=
_randomInSquare
(
viewportWidth
/
2
,
viewportHeight
/
2
,
300
);
x
=
typeof
(
node
.
initial
)
===
"
undefined
"
?
random
.
x
:
node
.
initial
.
x
;
y
=
typeof
(
node
.
initial
)
===
"
undefined
"
?
random
.
y
:
node
.
initial
.
y
;
// 初始化位置
nodePositions
[
i
]
=
[
x
,
y
];
nodePrePositions
[
i
]
=
[
x
,
y
];
// 初始化受力
nodeForces
[
i
]
=
[
0
,
0
];
// 初始化加速度
nodeAccelerations
[
i
]
=
[
0
,
0
];
// 初始化质量
nodeMasses
[
i
]
=
r
*
r
*
density
;
var
shape
=
{
id
:
zr
.
newShapeId
(
self
.
type
),
shape
:
'
circle
'
,
style
:
{
r
:
r
,
x
:
x
,
y
:
y
}
};
// 优先级 node.style > category.style > defaultStyle
zrUtil
.
merge
(
shape
.
style
,
nodeStyle
);
if
(
typeof
(
node
.
category
)
!==
'
undefined
'
)
{
var
category
=
categories
[
node
.
category
];
if
(
category
){
var
style
=
category
.
style
;
if
(
style
){
zrUtil
.
merge
(
shape
.
style
,
style
,
{
overwrite
:
true
});
}
}
}
if
(
typeof
(
node
.
style
)
!==
'
undefined
'
)
{
zrUtil
.
merge
(
shape
.
style
,
node
.
style
,
{
overwrite
:
true
});
}
// 拖拽特性
self
.
setCalculable
(
shape
);
shape
.
ondragstart
=
self
.
shapeHandler
.
ondragstart
;
shape
.
draggable
=
true
;
nodeShapes
.
push
(
shape
);
self
.
shapeList
.
push
(
shape
);
zr
.
addShape
(
shape
);
}
// _normalize(nodeMasses, nodeMasses);
}
function
_buildLinkShapes
(
nodes
,
links
)
{
var
l
=
links
.
length
;
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
var
link
=
links
[
i
];
var
source
=
nodes
[
link
.
source
];
var
target
=
nodes
[
link
.
target
];
var
weight
=
link
.
weight
||
1
;
linkWeights
.
push
(
weight
);
var
shape
=
{
id
:
zr
.
newShapeId
(
self
.
type
),
shape
:
'
line
'
,
style
:
{
xStart
:
0
,
yStart
:
0
,
xEnd
:
0
,
yEnd
:
0
}
};
zrUtil
.
merge
(
shape
.
style
,
linkStyle
);
if
(
typeof
(
link
.
style
)
!==
'
undefined
'
)
{
zrUtil
.
merge
(
shape
.
style
,
link
.
style
,
{
overwrite
:
true
})
}
linkShapes
.
push
(
shape
);
self
.
shapeList
.
push
(
shape
);
zr
.
addShape
(
shape
);
}
_normalize
(
linkWeights
,
linkWeights
);
}
function
_updateLinkShapes
(){
for
(
var
i
=
0
,
l
=
linksRawData
.
length
;
i
<
l
;
i
++
)
{
var
link
=
linksRawData
[
i
];
var
linkShape
=
linkShapes
[
i
];
var
sourceShape
=
nodeShapes
[
link
.
source
];
var
targetShape
=
nodeShapes
[
link
.
target
];
linkShape
.
style
.
xStart
=
sourceShape
.
style
.
x
;
linkShape
.
style
.
yStart
=
sourceShape
.
style
.
y
;
linkShape
.
style
.
xEnd
=
targetShape
.
style
.
x
;
linkShape
.
style
.
yEnd
=
targetShape
.
style
.
y
;
}
}
function
_update
(
stepTime
)
{
var
len
=
nodePositions
.
length
;
var
v12
=
[];
// 计算节点之间斥力
var
k2
=
k
*
k
;
// Reset force
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
nodeForces
[
i
][
0
]
=
0
;
nodeForces
[
i
][
1
]
=
0
;
}
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
for
(
var
j
=
i
+
1
;
j
<
len
;
j
++
){
var
w1
=
nodeWeights
[
i
];
var
w2
=
nodeWeights
[
j
];
var
p1
=
nodePositions
[
i
];
var
p2
=
nodePositions
[
j
];
// 节点1到2的向量
vec2
.
sub
(
v12
,
p2
,
p1
);
var
d
=
vec2
.
length
(
v12
);
// 距离大于500忽略斥力
if
(
d
>
500
){
continue
;
}
vec2
.
scale
(
v12
,
v12
,
1
/
d
);
var
forceFactor
=
1
*
(
w1
+
w2
)
*
k2
/
d
;
vec2
.
scale
(
v12
,
v12
,
forceFactor
);
//节点1受到的力
vec2
.
sub
(
nodeForces
[
i
],
nodeForces
[
i
],
v12
);
//节点2受到的力
vec2
.
add
(
nodeForces
[
j
],
nodeForces
[
j
],
v12
);
}
}
// 计算节点之间引力
for
(
var
i
=
0
,
l
=
linksRawData
.
length
;
i
<
l
;
i
++
)
{
var
link
=
linksRawData
[
i
];
var
w
=
linkWeights
[
i
];
var
s
=
link
.
source
;
var
t
=
link
.
target
;
var
p1
=
nodePositions
[
s
];
var
p2
=
nodePositions
[
t
];
vec2
.
sub
(
v12
,
p2
,
p1
);
var
d2
=
vec2
.
lengthSquare
(
v12
);
vec2
.
normalize
(
v12
,
v12
);
var
forceFactor
=
w
*
d2
/
k
;
// 节点1受到的力
vec2
.
scale
(
v12
,
v12
,
forceFactor
);
vec2
.
add
(
nodeForces
[
s
],
nodeForces
[
s
],
v12
);
//节点2受到的力
vec2
.
sub
(
nodeForces
[
t
],
nodeForces
[
t
],
v12
);
}
// 到质心的向心力
for
(
var
i
=
0
,
l
=
nodesRawData
.
length
;
i
<
l
;
i
++
){
var
p
=
nodePositions
[
i
];
vec2
.
sub
(
v12
,
centroid
,
p
);
var
d2
=
vec2
.
lengthSquare
(
v12
);
vec2
.
normalize
(
v12
,
v12
);
// 100是可调参数
var
forceFactor
=
d2
/
100
;
vec2
.
scale
(
v12
,
v12
,
forceFactor
);
vec2
.
add
(
nodeForces
[
i
],
nodeForces
[
i
],
v12
);
}
// 计算加速度
for
(
var
i
=
0
,
l
=
nodeAccelerations
.
length
;
i
<
l
;
i
++
)
{
vec2
.
scale
(
nodeAccelerations
[
i
],
nodeForces
[
i
],
1
/
nodeMasses
[
i
]);
}
var
velocity
=
[];
var
tmp
=
[];
// 计算位置(verlet积分)
for
(
var
i
=
0
,
l
=
nodePositions
.
length
;
i
<
l
;
i
++
)
{
var
p
=
nodePositions
[
i
];
var
p_
=
nodePrePositions
[
i
];
vec2
.
sub
(
velocity
,
p
,
p_
);
p_
[
0
]
=
p
[
0
];
p_
[
1
]
=
p
[
1
];
vec2
.
add
(
velocity
,
velocity
,
vec2
.
scale
(
tmp
,
nodeAccelerations
[
i
],
stepTime
));
// Damping
vec2
.
scale
(
velocity
,
velocity
,
temperature
);
vec2
.
add
(
p
,
p
,
velocity
);
nodeShapes
[
i
].
style
.
x
=
p
[
0
];
nodeShapes
[
i
].
style
.
y
=
p
[
1
];
}
}
function
_step
(){
if
(
temperature
<
0.005
)
{
return
;
}
_update
(
stepTime
);
_updateLinkShapes
();
for
(
var
i
=
0
;
i
<
nodeShapes
.
length
;
i
++
)
{
var
shape
=
nodeShapes
[
i
];
zr
.
modShape
(
shape
.
id
,
shape
);
}
for
(
var
i
=
0
;
i
<
linkShapes
.
length
;
i
++
)
{
var
shape
=
linkShapes
[
i
];
zr
.
modShape
(
shape
.
id
,
shape
);
}
zr
.
refresh
();
// Cool Down
temperature
*=
0.999
;
}
function
init
(
newOption
,
newComponent
)
{
option
=
newOption
;
component
=
newComponent
;
series
=
option
.
series
;
self
.
clear
();
_buildShape
();
setInterval
(
function
(){
_step
();
},
stepTime
);
}
function
refresh
()
{
self
.
clear
();
_buildShape
();
}
/**
* 输出动态视觉引导线
*/
self
.
shapeHandler
.
ondragstart
=
function
()
{
self
.
isDragstart
=
true
;
}
/**
* 拖拽开始
*/
function
ondragstart
(
param
,
status
)
{
if
(
!
self
.
isDragstart
||
!
param
.
target
)
{
// 没有在当前实例上发生拖拽行为则直接返回
return
;
}
console
.
log
(
'
dragstart
'
,
param
.
target
);
// 处理完拖拽事件后复位
self
.
isDragstart
=
false
;
// 我想你需要这个
zr
.
on
(
zrConfig
.
EVENT
.
MOUSEMOVE
,
_onmousemove
);
}
/**
* 数据项被拖拽出去,重载基类方法
*/
function
ondragend
(
param
,
status
)
{
if
(
!
self
.
isDragend
||
!
param
.
target
)
{
// 没有在当前实例上发生拖拽行为则直接返回
return
;
}
console
.
log
(
'
dragend
'
,
param
.
target
);
// 别status = {}赋值啊!!
status
.
dragIn
=
true
;
//你自己refresh的话把他设为false,设true就会重新掉refresh接口
status
.
needRefresh
=
false
;
// 处理完拖拽事件后复位
self
.
isDragend
=
false
;
zr
.
un
(
zrConfig
.
EVENT
.
MOUSEMOVE
,
_onmousemove
);
}
// 拖拽中位移信息
function
_onmousemove
(
param
)
{
console
.
log
(
param
,
zrEvent
.
getX
(
param
.
event
),
zrEvent
.
getY
(
param
.
event
)
)
}
self
.
init
=
init
;
self
.
refresh
=
refresh
;
self
.
ondragstart
=
ondragstart
;
self
.
ondragend
=
ondragend
;
init
(
option
,
component
);
}
function
_map
(
output
,
input
,
mappedMin
,
mappedMax
)
{
var
min
=
input
[
0
];
var
max
=
input
[
0
];
var
l
=
input
.
length
;
for
(
var
i
=
1
;
i
<
l
;
i
++
)
{
var
val
=
input
[
i
];
if
(
val
<
min
)
{
min
=
val
;
}
if
(
val
>
max
)
{
max
=
val
;
}
}
var
range
=
max
-
min
;
var
mappedRange
=
mappedMax
-
mappedMin
;
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
if
(
range
===
0
)
{
output
[
i
]
=
mappedMin
;
}
else
{
var
val
=
input
[
i
];
var
percent
=
(
val
-
min
)
/
range
;
output
[
i
]
=
mappedRange
*
percent
+
mappedMin
;
}
}
}
function
_normalize
(
output
,
input
)
{
var
l
=
input
.
length
;
var
max
=
input
[
0
];
for
(
var
i
=
1
;
i
<
l
;
i
++
)
{
if
(
input
[
i
]
>
max
)
{
max
=
input
[
i
];
}
}
for
(
var
i
=
0
;
i
<
l
;
i
++
)
{
output
[
i
]
=
input
[
i
]
/
max
;
}
}
function
_randomInCircle
(
x
,
y
,
radius
)
{
var
theta
=
Math
.
random
()
*
Math
.
PI
*
2
;
var
r
=
radius
*
Math
.
random
();
return
{
x
:
Math
.
cos
(
theta
)
*
r
+
x
,
y
:
Math
.
sin
(
theta
)
*
r
+
y
}
}
function
_randomInSquare
(
x
,
y
,
size
)
{
return
{
x
:
(
Math
.
random
()
-
0.5
)
*
size
+
x
,
y
:
(
Math
.
random
()
-
0.5
)
*
size
+
y
}
}
// 图表注册
require
(
'
../chart
'
).
define
(
'
force
'
,
Force
);
return
Force
;
})
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录