zoukankan      html  css  js  c++  java
  • 可视化工具D3.js教程 入门 (第十二章)—— 力导向图

    力导向图的概念这里就不细说了,力导向图适合绘制关系型的信息;

    下面先来说几个关于力导向图的知识点:

    1、d3.forceSimulation([nodes])

      创建一个新的力导向图;

    2、simulation.force(name[, force])

      如果指定了 force 则表示添加指定 name 的 force(力学模型)并返回仿真,如下:

      var simulation = d3.forceSimulation(nodes).force("charge", d3.forceManyBody());

      如果要移除对应的 name 的仿真,可以为其指定 null,如下:

      simulation.force("charge", null);

     3、simulation.nodes([nodes])

      如果指定了 nodes 则将仿真的节点设置为指定的对象数组,并根据需要创建它们的位置和速度,然后 重新初始化并且绑定 force 返回当前仿真。如果没有指定 nodes 则返回当前仿真的节点数组。

    4、d3.forceLink([links]) 

      根据指定的 links 以及默认参数创建一个弹簧力模型。如果没有指定 links 则默认为空数组。

    5、link.links([links])

      如果指定了 links 则将其设置为该弹簧力模型的关联边数组,并重新计算每个边的 distance 和 strength 参数,返回当前力模型。如果没有指定 links 则返回当前力模型的边数组,默认为空。

    6、simulation.tick()

      简单来讲就是让力导向图随时更新并且动起来的。

    7、d3.drag() 

      创建一个新的拖拽行为并返回自身。drag 既是一个对象,也是一个函数,通常通过 selection.call 被应用在选中的元素上。

      d3.selectAll(".node").call(d3.drag().on("start", started));

    有了这些新知识 我么开始绘图

    代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>force</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    </head>
    <body>

    <svg height="400" width="500"></svg>

    </body>

    <script>

    //数据
    var nodes = [//节点集
    {name:"湖南邵阳"},
    {name:"山东莱州"},
    {name:"广东阳江"},
    {name:"山东枣庄"},
    {name:"赵丽泽"},
    {name:"王恒"},
    {name:"张欣鑫"},
    {name:"赵明山"},
    {name:"班长"}
    ];
    var edges = [//边集
    {source:0,target:4,relation:"籍贯",value:1.3},
    {source:4,target:5,relation:"舍友",value:1},
    {source:4,target:6,relation:"舍友",value:1},
    {source:4,target:7,relation:"舍友",value:1},
    {source:1,target:6,relation:"籍贯",value:2},
    {source:2,target:5,relation:"籍贯",value:0.9},
    {source:3,target:7,relation:"籍贯",value:1},
    {source:5,target:6,relation:"同学",value:1.6},
    {source:6,target:7,relation:"朋友",value:0.7},
    {source:6,target:8,relation:"职责",value:2}
    ];

    var margin = 30;//边距
    var svg = d3.select('svg');
    var width = svg.attr('width');
    var height = svg.attr('height');

    //创建一个分组 并设置偏移
    var g = svg.append('g').attr('transform','translate('+ margin +','+ margin +')');


    //新建一个颜色比例尺
    var scaleColor = d3.scaleOrdinal()
    .domain(d3.range(nodes.length))
    .range(d3.schemeCategory10);

    //新建一个力导向图
    var forceSimulation = d3.forceSimulation()
    .force("link",d3.forceLink())
    .force("charge",d3.forceManyBody())
    .force("center",d3.forceCenter());


    //生成节点数据
    forceSimulation.nodes(nodes)
    .on('tick',linksTick);//这个函数下面会讲解


    //生成边数据
    forceSimulation.force('link')
    .links(edges)
    .distance(function (d,i) {
    return d.value*100;//设置边长
    });

    //设置图形 中心点
    forceSimulation.force('center')
    .x(width/2)//设置x坐标
    .y(height/2)//设置y坐标

    //再来看下顶点数据 和 边数据
    console.log(nodes);
    console.log(edges);


    //绘制边 这里注意一下绘制顺序 在d3中 各元素是有层级关系的,先绘制的在下面
    var links = g.append('g')
    .selectAll('line')
    .data(edges)
    .enter()
    .append('line')
    .attr('stroke',function (d,i) {
    return scaleColor(i);//设置边线颜色
    })
    .attr('storke-width','1');//设置边线宽度


    //绘制边上的文字
    var linksText = g.append('g')
    .selectAll('text')
    .data(edges)
    .enter()
    .append('text')
    .text(function (d,i) {
    return d.relation;
    });


    //创建节点分组
    var gs = g.selectAll('.circle')
    .data(nodes)
    .enter()
    .append('g')
    .attr('transform',function (d,i) {
    return 'translate('+ d.x +','+ d.y +')'
    })
    .call(
    d3.drag()//相当于移动端的拖拽手势 分以下三个阶段
    .on('start',start)
    .on('drag',drag)
    .on('end',end)
    );

    //绘制节点
    gs.append('circle')
    .attr('r',10)
    .attr('fill',function (d,i) {
    return scaleColor(i);
    });

    //绘制文字
    gs.append('text')
    .text(function (d,i) {
    return d.name;
    });





    function linksTick(){
    links
    .attr("x1",function(d){return d.source.x;})
    .attr("y1",function(d){return d.source.y;})
    .attr("x2",function(d){return d.target.x;})
    .attr("y2",function(d){return d.target.y;});

    linksText
    .attr("x",function(d){
    return (d.source.x+d.target.x)/2;
    })
    .attr("y",function(d){
    return (d.source.y+d.target.y)/2;
    });

    gs && gs.attr('transform',function (d,i) {
    return 'translate('+ d.x +','+ d.y +')';
    })

    }


    function start(d){
    if(!d3.event.active){//event.active 属性对判断并发的拖拽手势序列中的 start 事件和 end 事件: 在拖拽手势开始时为0,在拖拽结束最后一个手势事件时为0
    //这里就是drag的过程中
    forceSimulation.alphaTarget(0.8).restart();//设置衰减系数,对节点位置移动过程的模拟,数值越高移动越快,数值范围[0,1]
    }
    d.fx = d.x;
    d.fy = d.y;
    }

    function drag(d){
    d.fx = d3.event.x;
    d.fy = d3.event.y;
    }

    function end(d) {
    if (!d3.event.active) {
    forceSimulation.alphaTarget(0);
    }
    d.fx = null;
    d.fy = null;
    }


    </script>

    </html>

    效果:

     

  • 相关阅读:
    MySQL开发规范与使用技巧总结
    Anaconda3(在D盘)安装jieba库具体步骤
    Python的reshape的用法
    oom和cpu负载的定位
    接口安全设计
    恍然间
    java原子类
    设计模式
    微服务
    常见的代码优化
  • 原文地址:https://www.cnblogs.com/zhinian-/p/12612837.html
Copyright © 2011-2022 走看看