作业源码链接
https://github.com/978543210/Frontend-01-Template/blob/master/week04/Realm.html
思路:
从ECMA262 中找到JS引擎中内置的对象,以这些对象为基础。通过遍历这些对象的原型、值属性和访问器属性的方法获得所有内置对象。
内置的对象包括:(ECMA262 P102 15. Standard Built-in ECMAScript Objects )
var globalProperties = [
"eval","isFinite","isNaN","parseFloat","parseInt",
"decodeURI","decodeURIComponent","encodeURI",
"encodeURIComponent","Array","Date","RegExp",
"Promise","Proxy","Map","WeakMap","Set",
"WeakSet","Function","Boolean","String",
"Number","Symbol","Object","Error",
"EvalError","RangeError","ReferenceError",
"SyntaxError","TypeError","URIError",
"ArrayBuffer","SharedArrayBuffer","DataView",
"Float32Array","Float64Array","Int8Array",
"Int16Array","Int32Array","Uint8Array",
"Uint16Array","Uint32Array","Uint8ClampedArray",
"Atomics","JSON","Math","Reflect"];
避免重复添加,使用set去重,最终set中的所有的所有对象即为所求。
广度优先遍历
先将globalProperties
中的所有对象入队,依次查找对象的原型、值属性和访问器属性中的对象,并将其入队,并放入set集合中自动去重,依次检索队列中所有对象知道直到队列为空。
自从知道可以在电脑上乱写乱画之后,总合计折腾一些新的玩法,正好试试瞎画一下,然后生成一个gif文件,毕竟一图胜千言……
忽然想到,对象的关系如果不是树形结构,是一个图,里面要是有环什么办……
可视化
生成数据
可视化结果应该是一个关系图,对于图来说,我们重点关注顶点和边的生成,
参考g6的demo,我们需要使用json格式生成nodes和edges
因此,
- 在每次把节点装入集合中的时候,我们同时把对象的“toString()”结果放到nodes中;
- 在每次按照线索找到对象的时候,把原对象和目标对象的“toString()”结果放到edges中。
程序中的bug:
有些对象调用toString()方法报错。 目前偷懒,直接使用try屏蔽了,考虑的解决方案是生成一个字典,对于这些特殊对象,查表得到对应的字符串。
代码如下:
var set = new Set();
var jsondata = {nodes: [],edges: [],};
var globalProperties = [
"eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI",
"encodeURIComponent","Array","Date","RegExp","Promise","Proxy","Map","WeakMap","Set",
"WeakSet","Function","Boolean","String","Number","Symbol","Object","Error",
"EvalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError",
"ArrayBuffer","SharedArrayBuffer","DataView","Float32Array","Float64Array","Int8Array",
"Int16Array","Int32Array","Uint8Array","Uint16Array","Uint32Array","Uint8ClampedArray",
"Atomics","JSON","Math","Reflect"];
var queue = [];
for (var p of globalProperties){
queue.push({
path: [p],
object:this[p]
});
}
let current;
while(queue.length){
current = queue.shift();
console.log(current.path.join('.'));
if (set.has(current.object))
continue;
if (current.object == undefined )
continue;
set.add(current.object);
try {
jsondata.nodes.push({id: current.object.toString(), label: current.object.toString()})
} catch (error) {
console.log(current.object)
}
// console.log(current.object)
let proto = Object.getPrototypeOf(current.object);
if(proto){
queue.push({
path: current.path.concat("__proto__"),
object: proto
});
try {
jsondata.edges.push({source: current.object.toString(), target: proto.toString()})
} catch (error) {
console.log(proto)
}
}
for (let p of Object.getOwnPropertyNames(current.object)) {
var property = Object.getOwnPropertyDescriptor(current.object,p)
if (property.hasOwnProperty("value") &&
((property.value != null) && (typeof property.value == "object") || (typeof property.value == "object"))
&& property.value instanceof Object){
queue.push({
path: current.path.concat([p]),
object:property.value
});
try {
jsondata.edges.push({source: current.object.toString(), target: property.value.toString()})
} catch (error) {
console.log(property.value)
}
}
if (property.hasOwnProperty("get") && (typeof property.get == "function") ) {
queue.push({
path:current.path.concat([p]),
object:property.get
});
try {
jsondata.edges.push({source: current.object.toString(), target: property.get.toString()})
} catch (error) {
console.log(property.get)
}
}
if (property.hasOwnProperty("set") && (typeof property.get == "function") ) {
queue.push({
path:current.path.concat([p]),
object:property.set
});
try {
jsondata.edges.push({source: current.object.toString(), target: property.set.toString()})
} catch (error) {
console.log(property.set)
}
}
}
}
console.log(set)
console.log(jsondata)
测试可视化g6的使用、
生成nodes和edges数据后,使用默认demo程序测试一下,结果如图
期待的数据关系
观察数据结果,就像人物关系网一样,想把核心的,高密度的放在中间逐步外扩。
考虑使用的方案是,计算每个顶点的出度和入度,入度越多,说明重要性越高。越应该放置在中心。
可以类似PageRank算法,生成各个节点的权值,然后再去做布局。
还有就是考虑按照名称,比如都包含error的,按照一定的聚类算法,使其最终呈现在一起。
尝试新的模型
试过几种模型,force的,没有想好如何去设置,引力和斥力最终都聚集到一起了,如果设置得当,应该能很好的体现聚类的效果
在不修改代码,人为计算入度、权值、聚类的情况下,觉得Radial展示效果比较符合我个人预期,就先这样吧。
const graph = new G6.Graph({
container: 'mountNode', // 指定图画布的容器 id
// 画布宽高
width: 2000,
height: 2000,
modes: {
default: ['drag-canvas', 'drag-node'],
},
layout: {
type: 'radial',
linkDistance: 300, // 设置边长为 100
preventOverlap: true, // 设置防止重叠
},
animate: true,
defaultNode: {
size: 30,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 3,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',
fill: '#e2e2e2'
},
},
},
});
graph.data(jsondata);
graph.render();