zoukankan      html  css  js  c++  java
  • Vue和d3.js(v4)力导向图force结合使用,v3版本升级v4

    前段时间因为参与项目涉密,所以一直没有更新博客,有些博友给我私信或者留言要部分博文的源码,因为我的电脑更换,demo的源码没有备份 所以无法提供。大家可针对具体问题问我,有空我定会回复的。另外转发文章请说明出处,谢谢关注!
    之前有多篇博文介绍了d3力导向图的绘制过程的一些问题,现在由于性能和UI的要求,要升级d3版本。因为v3版本现在使用的不多了,网上可找的资料不多且拓展性不好,因此花了点时间做了版本升级。

    效果展示

    初始化布局

    this.force = d3.forceSimulation(nodes)
            .force('link', d3.forceLink(links).id(d => d.id).strength(0.6).distance(Math.floor(height / 4)))
            .force('charge', d3.forceManyBody().strength(-500).distanceMin(50).distanceMax(400))
            .force('center', d3.forceCenter())
            .force('collision', d3.forceCollide().radius(50))
            .velocityDecay(0.5)
    

    基础的配置,中文api里说的很清楚,d3-force

    容器创建

    
    let circles = null; // circle元素集合
    let lines = null; // line元素集合
    let gContainer = null; // 所有元素容器
    let gCircle = null; // circle元素容器
    let gLine = null; // line元素容器
    let svg = null;
    
    ......
    
       svg = d3.select('#svgForce')
            .append('svg')
            .attr('class', 'svg__container')
            .attr('viewBox', [-width / 2, -height / 2, width, height])
    
       // g容器,存放其他元素
          gContainer = svg
            .append('g')
            .attr('class', 'force__container')
            .attr('transform', 'translate(' + 10 + ',' + 10 + ')');
    
          // 容器
          gLine = gContainer.append('g').attr('class', 'force__line');
          gCircle = gContainer.append('g').attr('class', 'force__circle');
    

    容器创建,区分线和节点,便于维护和处理

    Zoom缩放(仅附上关键代码,不可粘贴复制直接实现哦~)

    // zoom缩放
        let zoom = d3.zoom()
           .scaleExtent([0.5, 5])
           .on('zoom', this.zoomed);
    
    // 鼠标放大缩小
        zoomed () {
          const transform = d3.event.transform;
          d3.selectAll('.force__container').attr('transform', transform);
        }
    ....
    svg.call(zoom)
    

    Drag拖拽

    // 拖拽
          let drag = d3.drag()
            .on('start', d => {
              if (!d3.event.active) this.force.alphaTarget(0.8).restart(); // 当alpha为0 设置值让其动起来
              d.fx = d.x;
              d.fy = d.y;
            })
            .on('drag', d => {
              d.fx = d3.event.x;
              d.fy = d3.event.y;
              d.drag = true;
              this.force.force('center', null) // 允许随意拖动
            })
            .on('end', d => {
              if (!d3.event.active) this.force.alphaTarget(0); // 静下来
            })
    
          circles = gCircle.selectAll('g')
            .data(that.nodes, d => `circle${d.id}`)
            .join('g')
            .call(drag)
    
    1. d.fx 和 d.fy 表示设置拖拽固定的节点位置,如果想结束拽动后固定,需要在end中 删除2个值~
    2. 拖拽函数:start,dragend
    3. 设置this.force.force('center', null) 是让节点随着拖动的位置随意飘动,不然你拽不走它的,它会被center的向心力吸引的

    仿真tick

    this.force.on('tick', () => {
            circles.attr('transform', d => `translate(${d.x},${d.y})`);
    
            lines.selectAll('path')
              .attr('d', d => that.linkTick(d))
    

    linkTick 是直线平行线的绘制方法,上篇博文有写,d3力导图绘制节点间多条关系平行线的方法

    小结

    本文主要写了下布局,拖拽,缩放一些基础方法的改变和使用。下篇将说一些最近调研的一些新玩意,包括文字加底色,线条加底色的方法。

  • 相关阅读:
    第四次作业—四则运算
    第四次作业—代码规范
    【欢迎来怼】事后诸葛亮会议
    软件工程——第七次作业
    第17次Scrum会议(10/29)【欢迎来怼】
    软件工程——第六次作业
    第10次Scrum会议(10/22)【欢迎来怼】
    软件工程——第五次作业
    欢迎来怼——第四次Scrum会议
    软件工程——第四次作业(3)
  • 原文地址:https://www.cnblogs.com/webhmy/p/13665852.html
Copyright © 2011-2022 走看看