• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

3d-force-graph展示学习记录

武飞扬头像
是池池呀
帮助1

此文章仅用来记录3d-force-graph示例学习过程中的问题,以及相关笔记。

1.basic (基本)

const Graph = ForceGraph3D()(document.getElementById('3d-graph')).graphData(gData);

2.async-load (异步加载)

  1.  
    // URL scheme "file" is not supported. 未解决
  2.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  3.  
    .jsonUrl('../datasets/miserables.json')
  4.  
    .nodeLabel('id')//鼠标悬浮至mesh上显示标签,标签内容未id
  5.  
    .nodeAutoColorBy('group');//按照group进行分类

报错:URL scheme "file" is not supported. 未解决,改为:

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .graphData(gData) //直接把json内容粘贴到gData
  3.  
    .nodeLabel('id')
  4.  
    .nodeAutoColorBy('group');

效果:

学新通

 3.larger-graph

新知识点:

onNodeClick:监听事件单击,在新页面打开      

  1.  
    const Graph = ForceGraph3D()(elem)
  2.  
    .jsonUrl('../datasets/blocks.json')
  3.  
    .nodeAutoColorBy('user')
  4.  
    .nodeLabel(node => `${node.user}: ${node.description}`)
  5.  
    .onNodeClick(
  6.  
    node => window.open(`https://bl.ocks.org/${node.user}/${node.id}`, '_blank') //单击在新页面打开
  7.  
    );

4.Directional arrows(带方向的箭头)

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .graphData(gData)
  3.  
    .nodeLabel('id')
  4.  
    .linkDirectionalArrowLength(3.5) //箭头长度
  5.  
    .linkDirectionalArrowRelPos(1) //箭头位置偏移 source指向target
  6.  
    .linkCurvature(0.25); //曲度

效果:

学新通

 5.Directional moving particles Directional moving particles(定向移动例粒子)

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .graphData(gData)
  3.  
    .nodeLabel('id')
  4.  
    .nodeAutoColorBy('group')
  5.  
    .linkDirectionalParticles('value') //粒子个数
  6.  
    .linkDirectionalParticleSpeed(d => d.value * 0.001); //粒子运动速度

效果(部分截图):

学新通

6.Curved lines and self links(曲线和自链接)

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .nodeLabel('id')
  3.  
    .linkCurvature('curvature') //曲率 数值越大 弯曲程度越小
  4.  
    .linkCurveRotation('rotation') // 链接旋转方向
  5.  
    .linkDirectionalParticles(2)
  6.  
    .graphData(gData);

学新通

7.Auto-colored nodes/links

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .nodeAutoColorBy('group') //节点根据group着色
  3.  
    .linkAutoColorBy(d => gData.nodes[d.source].group) //链接根据group着色
  4.  
    .linkOpacity(0.5) //链接透明度
  5.  
    .graphData(gData);

 效果:

学新通

8.Text as nodes(文本作为节点)

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .jsonUrl('../datasets/miserables.json')
  3.  
    .nodeAutoColorBy('group')
  4.  
    .nodeThreeObject(node => {
  5.  
    const sprite = new SpriteText(node.id);
  6.  
    // sprite.material.depthWrite = false; // make sprite background transparent
  7.  
    sprite.color = node.color;
  8.  
    sprite.textHeight = 8;
  9.  
    return sprite;
  10.  
    });
  11.  
     
  12.  
    // Spread nodes a little wider
  13.  
    Graph.d3Force('charge').strength(-120); //设定引力,是排斥还是吸引

效果:

学新通

 9.Images as nodes (图像作为节点)

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .nodeThreeObject(({ img }) => {
  3.  
    const imgTexture = new THREE.TextureLoader().load(`./imgs/${img}`); //创建纹理贴图
  4.  
    const material = new THREE.SpriteMaterial({ map: imgTexture });
  5.  
    const sprite = new THREE.Sprite(material);
  6.  
    sprite.scale.set(12, 12);
  7.  
    return sprite;
  8.  
    })
  9.  
    .graphData(gData);

效果:

学新通

 10.HTML in nodes

  1.  
    const Graph = ForceGraph3D({
  2.  
    extraRenderers: [new THREE.CSS2DRenderer()]
  3.  
    })(document.getElementById('3d-graph'))
  4.  
    .graphData(gData)
  5.  
    .nodeAutoColorBy('group')
  6.  
    .nodeThreeObject(node => {
  7.  
    const nodeEl = document.createElement('div');
  8.  
    nodeEl.textContent = node.id;
  9.  
    nodeEl.style.color = node.color;
  10.  
    nodeEl.className = 'node-label';
  11.  
    return new THREE.CSS2DObject(nodeEl);
  12.  
    })
  13.  
    .nodeThreeObjectExtend(true); //节点对象访问器函数、属性或布尔值,用于确定在使用自定义nodeThreeObject(false)时是替换默认节点还是扩展它(true

 效果:(nodeThreeObjectExtend分别是true false)

学新通 学新通

 11.Custom node geometriesxiao

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .nodeThreeObject(
  3.  
    ({ id }) =>
  4.  
    new THREE.Mesh(
  5.  
    [
  6.  
    // 方块
  7.  
    new THREE.BoxGeometry(
  8.  
    Math.random() * 20,
  9.  
    Math.random() * 20,
  10.  
    Math.random() * 20
  11.  
    ),
  12.  
    // 锥体
  13.  
    new THREE.ConeGeometry(Math.random() * 10, Math.random() * 20),
  14.  
    // 圆柱
  15.  
    new THREE.CylinderGeometry(
  16.  
    Math.random() * 10,
  17.  
    Math.random() * 10,
  18.  
    Math.random() * 20
  19.  
    ),
  20.  
    // 十二面体
  21.  
    new THREE.DodecahedronGeometry(Math.random() * 10),
  22.  
    // 球体
  23.  
    new THREE.SphereGeometry(Math.random() * 10),
  24.  
    // 圆环
  25.  
    new THREE.TorusGeometry(Math.random() * 10, Math.random() * 2),
  26.  
    // 环面扭结
  27.  
    new THREE.TorusKnotGeometry(Math.random() * 10, Math.random() * 2)
  28.  
    ][id % 7],
  29.  
    new THREE.MeshLambertMaterial({
  30.  
    color: Math.round(Math.random() * Math.pow(2, 24)),
  31.  
    transparent: true,
  32.  
    opacity: 0.75
  33.  
    })
  34.  
    )
  35.  
    )
  36.  
    .graphData(gData);
学新通

效果:

 学新通

 12.Gradient Links(渐变链接)

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .nodeColor(node => nodeColorScale(node.id)) //id=0,color=c1;id=1,color=c2....id=4,color=c1...
  3.  
    .linkThreeObject(link => {
  4.  
    const colors = new Float32Array(
  5.  
    [].concat(
  6.  
    ...[link.source, link.target]
  7.  
    .map(nodeColorScale)
  8.  
    .map(d3.color)
  9.  
    .map(({ r, g, b }) => [r, g, b].map(v => v / 255))
  10.  
    )
  11.  
    );
  12.  
     
  13.  
    const material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });
  14.  
    const geometry = new THREE.BufferGeometry();
  15.  
    geometry.setAttribute(
  16.  
    'position',
  17.  
    new THREE.BufferAttribute(new Float32Array(2 * 3), 3) //三个为一组 作为坐标
  18.  
    );
  19.  
    geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)); //三个为一组 作为颜色
  20.  
     
  21.  
    return new THREE.Line(geometry, material);
  22.  
    })
  23.  
    .graphData(gData);
学新通

效果:

学新通

13.Text in Links

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .graphData(gData)
  3.  
    .nodeLabel('id')
  4.  
    .nodeAutoColorBy('group')
  5.  
    .linkThreeObjectExtend(true)
  6.  
    .linkThreeObject(link => {
  7.  
    // extend link with text sprite
  8.  
    const sprite = new SpriteText(`${link.source} > ${link.target}`);
  9.  
    sprite.color = 'lightgrey';
  10.  
    sprite.textHeight = 1.5;
  11.  
    return sprite;
  12.  
    })
  13.  
    .linkPositionUpdate((sprite, { start, end }) => {
  14.  
    const middlePos = Object.assign(
  15.  
    ...['x', 'y', 'z'].map(c => ({
  16.  
    [c]: start[c] (end[c] - start[c]) / 2 // calc middle point
  17.  
    }))
  18.  
    );
  19.  
    // Position sprite
  20.  
    Object.assign(sprite.position, middlePos);
  21.  
    });
学新通

 效果:

学新通

14.Orbit controls && Fly controls

  1.  
    const Graph = ForceGraph3D({ controlType: 'orbit' })(document.getElementById('3d-graph'))
  2.  
    .jsonUrl('../datasets/miserables.json')
  3.  
    .nodeLabel('id')
  4.  
    .nodeAutoColorBy('group');
  5.  
     
  6.  
    const Graph = ForceGraph3D({ controlType: 'fly' })(document.getElementById('3d-graph'))
  7.  
    .jsonUrl('../datasets/miserables.json')
  8.  
    .nodeLabel('id')
  9.  
    .nodeAutoColorBy('group');

设置threejs控制器的类型,效果相当于:

this.controls = new OrbitControls(this.camera, this.renderer.domElement);

this.controls = new TrackballControls(this.camera, this.renderer.domElement);

15.Camera automatic orbitting

  1.  
    const distance = 1400;
  2.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  3.  
    .enableNodeDrag(false) //节点拖拽
  4.  
    .enableNavigationControls(false) //拖拽
  5.  
    .showNavInfo(false)
  6.  
    .cameraPosition({ z: distance })
  7.  
    .graphData(gData);
  8.  
     
  9.  
    // camera orbit
  10.  
    //10ms更新一下相机的位置
  11.  
    let angle = 0;
  12.  
    setInterval(() => {
  13.  
    Graph.cameraPosition({
  14.  
    x: distance * Math.sin(angle),
  15.  
    z: distance * Math.cos(angle)
  16.  
    });
  17.  
    angle = Math.PI / 300;
  18.  
    }, 10);
学新通

相当于:camera.position.set(position); 

16.Click to focus on node

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .graphData(gData)
  3.  
    .nodeLabel('id')
  4.  
    .nodeAutoColorBy('group')
  5.  
    //点击事件
  6.  
    .onNodeClick(node => {
  7.  
    // Aim at node from outside it
  8.  
    const distance = 40;
  9.  
    const distRatio = 1 distance / Math.hypot(node.x, node.y, node.z);
  10.  
     
  11.  
    Graph.cameraPosition(
  12.  
    { x: node.x * distRatio, y: node.y * distRatio, z: node.z * distRatio }, // new position
  13.  
    node, // lookAt ({ x, y, z })
  14.  
    3000 // ms transition duration
  15.  
    );
  16.  
    });
学新通

17.Click to expand/collapse nodes

  1.  
    const Graph = ForceGraph3D()(elem)
  2.  
    .graphData(getPrunedTree())
  3.  
    .linkDirectionalParticles(2)
  4.  
    //子节点折叠 red;子节点展开 yellow;无子节点 green;
  5.  
    .nodeColor(node =>
  6.  
    !node.childLinks.length ? 'green' : node.collapsed ? 'red' : 'yellow'
  7.  
    )
  8.  
    .onNodeHover(
  9.  
    node => (elem.style.cursor = node && node.childLinks.length ? 'pointer' : null)
  10.  
    )
  11.  
    //点击事件调用getPrunedTree()更新gdata
  12.  
    .onNodeClick(node => {
  13.  
    if (node.childLinks.length) {
  14.  
    node.collapsed = !node.collapsed; // toggle collapse state
  15.  
    Graph.graphData(getPrunedTree());
  16.  
    }
  17.  
    });
学新通

18.Fix nodes after dragging

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .graphData(gData)
  3.  
    .nodeLabel('id')
  4.  
    .nodeAutoColorBy('group')
  5.  
    .onNodeDragEnd(node => {
  6.  
    node.fx = node.x;
  7.  
    node.fy = node.y;
  8.  
    node.fz = node.z;
  9.  
    });

拖动节点后,该节点位置不变。

19.Fit graph to canvas

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .cooldownTicks(100) //冷却时间 参数为时间
  3.  
    .graphData(gData);
  4.  
     
  5.  
    // fit to canvas when engine stops
  6.  
    Graph.onEngineStop(() => Graph.zoomToFit(400));

渲染完成后,会适应画布大小。

20.Highlight nodes/links

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .graphData(gData)
  3.  
    //node颜色
  4.  
    .nodeColor(node =>
  5.  
    highlightNodes.has(node)
  6.  
    ? node === hoverNode
  7.  
    ? 'rgb(255,0,0,1)'
  8.  
    : 'rgba(255,160,0,0.8)'
  9.  
    : 'rgba(0,255,255,0.6)'
  10.  
    )
  11.  
    .linkWidth(link => (highlightLinks.has(link) ? 4 : 1))
  12.  
    .linkDirectionalParticles(link => (highlightLinks.has(link) ? 4 : 0))
  13.  
    .linkDirectionalParticleWidth(4)
  14.  
    .onNodeHover(node => {
  15.  
    // no state change
  16.  
    if ((!node && !highlightNodes.size) || (node && hoverNode === node)) return;
  17.  
     
  18.  
    highlightNodes.clear();
  19.  
    highlightLinks.clear();
  20.  
    if (node) {
  21.  
    highlightNodes.add(node);
  22.  
    node.neighbors.forEach(neighbor => highlightNodes.add(neighbor));
  23.  
    node.links.forEach(link => highlightLinks.add(link));
  24.  
    }
  25.  
     
  26.  
    hoverNode = node || null;
  27.  
     
  28.  
    updateHighlight();
  29.  
    })
  30.  
    .onLinkHover(link => {
  31.  
    highlightNodes.clear();
  32.  
    highlightLinks.clear();
  33.  
     
  34.  
    if (link) {
  35.  
    highlightLinks.add(link);
  36.  
    highlightNodes.add(link.source);
  37.  
    highlightNodes.add(link.target);
  38.  
    }
  39.  
    updateHighlight();
  40.  
    });
学新通

效果: 

学新通

 21.Multiple Node Selection

  1.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  2.  
    .graphData(gData)
  3.  
    .nodeRelSize(9) //节点大小
  4.  
    .nodeColor(node => (selectedNodes.has(node) ? 'yellow' : 'grey'))
  5.  
    .onNodeClick((node, event) => {
  6.  
    if (event.ctrlKey || event.shiftKey || event.altKey) {
  7.  
    // multi-selection
  8.  
    selectedNodes.has(node) ? selectedNodes.delete(node) : selectedNodes.add(node);
  9.  
    } else {
  10.  
    // single-selection
  11.  
    const untoggle = selectedNodes.has(node) && selectedNodes.size === 1;
  12.  
    selectedNodes.clear();
  13.  
    !untoggle && selectedNodes.add(node);
  14.  
    }
  15.  
     
  16.  
    Graph.nodeColor(Graph.nodeColor()); // update color of selected nodes
  17.  
    })
  18.  
    .onNodeDrag((node, translate) => {
  19.  
    if (selectedNodes.has(node)) {
  20.  
    // moving a selected node
  21.  
    [...selectedNodes]
  22.  
    .filter(selNode => selNode !== node) // don't touch node being dragged
  23.  
    .forEach(node =>
  24.  
    ['x', 'y', 'z'].forEach(
  25.  
    coord => (node[`f${coord}`] = node[coord] translate[coord])
  26.  
    )
  27.  
    ); // translate other nodes by same amount
  28.  
    }
  29.  
    })
  30.  
    .onNodeDragEnd(node => {
  31.  
    if (selectedNodes.has(node)) {
  32.  
    // finished moving a selected node
  33.  
    [...selectedNodes]
  34.  
    .filter(selNode => selNode !== node) // don't touch node being dragged
  35.  
    .forEach(node =>
  36.  
    ['x', 'y', 'z'].forEach(coord => (node[`f${coord}`] = undefined))
  37.  
    ); // unfix controlled nodes
  38.  
    }
  39.  
    });
学新通

效果:按住alt 、 shift、alt均可以进行多选。

学新通

22.Dynamic data changes

  1.  
    const Graph = ForceGraph3D()(elem)
  2.  
    .enableNodeDrag(false)
  3.  
    .onNodeClick(removeNode)
  4.  
    .graphData(initData);
  5.  
     
  6.  
    //定时添加节点,并连接dst为已有的随机节点
  7.  
    setInterval(() => {
  8.  
    const { nodes, links } = Graph.graphData();
  9.  
    const id = nodes.length;
  10.  
    Graph.graphData({
  11.  
    nodes: [...nodes, { id }],
  12.  
    links: [...links, { source: id, target: Math.round(Math.random() * (id - 1)) }]
  13.  
    });
  14.  
    }, 1000);
  15.  
     
  16.  
    //
  17.  
    function removeNode(node) {
  18.  
    let { nodes, links } = Graph.graphData();
  19.  
    links = links.filter(l => l.source !== node && l.target !== node); // Remove links attached to node
  20.  
    nodes.splice(node.id, 1); // Remove node 从node.id开始删除1个元素
  21.  
    //修正其他节点的id
  22.  
    nodes.forEach((n, idx) => {
  23.  
    n.id = idx;
  24.  
    }); // Reset node ids to array index
  25.  
    Graph.graphData({ nodes, links });
  26.  
    }
学新通

23.Node collision detection(节点碰撞检测)

  1.  
    const N = 50;
  2.  
    const nodes = [...Array(N).keys()].map(() => ({
  3.  
    // Initial velocity in random direction
  4.  
    // 随机方向上的初始速度
  5.  
    vx: Math.random(),
  6.  
    vy: Math.random(),
  7.  
    vz: Math.random()
  8.  
    }));
  9.  
     
  10.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'));
  11.  
     
  12.  
    Graph.cooldownTime(Infinity)
  13.  
    .d3AlphaDecay(0) //alpha 衰减率
  14.  
    .d3VelocityDecay(0) //默认为 0.4,较低的衰减系数可以使得迭代次数更多,其布局结果也会更理性,但是可能会引起数值不稳定从而导致震荡。
  15.  
     
  16.  
    // Deactivate existing forces
  17.  
    .d3Force('center', null) //centering作用力可以使得节点布局开之后围绕某个中心
  18.  
    .d3Force('charge', null) //作用力应用在所用的节点之间
  19.  
     
  20.  
    // Add collision and bounding box forces
  21.  
    .d3Force('collide', d3.forceCollide(Graph.nodeRelSize()))
  22.  
    .d3Force('box', () => {
  23.  
    const CUBE_HALF_SIDE = Graph.nodeRelSize() * N * 0.5;
  24.  
     
  25.  
    nodes.forEach(node => {
  26.  
    const x = node.x || 0,
  27.  
    y = node.y || 0,
  28.  
    z = node.z || 0;
  29.  
     
  30.  
    // bounce on box walls
  31.  
    if (Math.abs(x) > CUBE_HALF_SIDE) {
  32.  
    node.vx *= -1;
  33.  
    }
  34.  
    if (Math.abs(y) > CUBE_HALF_SIDE) {
  35.  
    node.vy *= -1;
  36.  
    }
  37.  
    if (Math.abs(z) > CUBE_HALF_SIDE) {
  38.  
    node.vz *= -1;
  39.  
    }
  40.  
    });
  41.  
    })
  42.  
     
  43.  
    // Add nodes
  44.  
    .graphData({ nodes, links: [] });
学新通

24.暂停、恢复动画

  1.  
    const distance = 1400;
  2.  
     
  3.  
    let isRotationActive = true;
  4.  
    const Graph = ForceGraph3D()(document.getElementById('3d-graph'))
  5.  
    .enableNodeDrag(false)
  6.  
    .enableNavigationControls(false)
  7.  
    .showNavInfo(true)
  8.  
    .cameraPosition({ z: distance })
  9.  
    .graphData(gData);
  10.  
    // camera orbit
  11.  
    let angle = 0;
  12.  
     
  13.  
    //使得物体旋转
  14.  
    setInterval(() => {
  15.  
    if (isRotationActive) {
  16.  
    Graph.cameraPosition({
  17.  
    x: distance * Math.sin(angle),
  18.  
    z: distance * Math.cos(angle)
  19.  
    });
  20.  
    angle = Math.PI / 300;
  21.  
    }
  22.  
    }, 10);
  23.  
     
  24.  
    document.getElementById('rotationToggle').addEventListener('click', event => {
  25.  
    isRotationActive = !isRotationActive;
  26.  
    event.target.innerHTML = `${isRotationActive ? 'Pause' : 'Resume'} Rotation`;
  27.  
    });
  28.  
     
  29.  
    let isAnimationActive = true;
  30.  
    document.getElementById('animationToggle').addEventListener('click', event => {
  31.  
    isAnimationActive ? Graph.pauseAnimation() : Graph.resumeAnimation();
  32.  
     
  33.  
    isAnimationActive = !isAnimationActive;
  34.  
    event.target.innerHTML = `${isAnimationActive ? 'Pause' : 'Resume'} Animation`;
  35.  
    });
学新通

初学结束~~~Fighting!

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgafaif
系列文章
更多 icon
同类精品
更多 icon
继续加载