d3v4 force chart upgrade clean up

房东的猫 提交于 2020-07-19 04:40:48

问题


I have some old relationship type - force chart from version 3 of d3.

I am keen to clean up and reduce the codebase -- reduce the reliance on all the functions. I had to refactor the data set and make nodes. I have started trying to port the code - but now running into upgrade errors- "d3.force is not a function"

looking at this as a reference D3 forceSimulation and dragging, what is node.fx/node.fy?

  • keen to fix the upgrade
  • refactor to make the creation of this chart easier and simpler - using data maps?

//version 3 https://jsfiddle.net/695ocnv7/3/

//version 4 https://jsfiddle.net/r376fg0d/

  var forceChart = {
    buildDataStream: function(userData){
      var data = new Array();
        
      $.each(userData, function( index, value ) {
      
        var interestArray = new Array();
         $.each(value.interests, function( x, v ) {
          
           var localInterestObj = {
             "label": Object.keys(v)[0],
             "name": "--"+Object.keys(v)[0].toLowerCase(),
             "size": v[Object.keys(v)[0]],
             "group": "level1",
             "children": []
           };
           interestArray.push(localInterestObj);
         
         });
        
        var childrenArray = [
            {
              "label": "Interests",
              "name": "-interests"+"-"+index,
              "group": "level2",
              "children": interestArray
            }        
        ]
        
        var userObj = {
          "label": value.userName,
          "name": "+"+index+"-"+value.userName.toLowerCase(),
          "group": "User",
          "userID": index,
          "children": childrenArray
        }
            
        data.push(userObj);
      });
      
      return data;
    },
    addUserPatterns: function(patternsSvg, userData){

        /*
        I figured this out.

        The height and width on a pattern element seem to function sort of like a scale / percentage. So a width of "1" means it will fill the whole element it is set to. A width of ".25" means 25% of that element. Then, within the <pattern> you would specify the height and width of the image as the actual pixel value of the height and width of the circle they are filling, so in this case my code was changed to:
        */


      $.each(userData, function(index, value) {
        var defs = patternsSvg.append('svg:defs');
          defs.append('svg:pattern')
            .attr('id', "--"+index+"-"+value.userName.toLowerCase())
            .attr('width', 1)
            .attr('height', 1)
            .append('svg:image')
            .attr('image-rendering', "optimizeQuality")
            .attr('preserveAspectRatio', "xMidYMid meet")
            .attr('xlink:href', value.userImage)
            .attr('x', 0)
            .attr('y', 0)
            .attr('width', 100)
            .attr('height', 100);
      });
    },
    invoke: function(holder, userData){
      var data = this.buildDataStream(userData);

      var patternsSvg = d3.select(holder)
                .append('svg')
                .attr('class', 'patterns')
                .attr('width', 0)
                .attr('height', 0);
      
      this.addUserPatterns(patternsSvg, userData);
      
      return data;
    }
  };

  var nodeMaker = {
    recursiveNode: function(value, nodes, level){
      var that = this;
      
      var children = new Array();
      if(value.children.length > 0){
        for(var c=0;c<value.children.length;c++){
          children.push(value.children[c].name);
        }
      }
      
      var orbSizesArray = [100, 20, 3, 1];
      
      var count = orbSizesArray[level];
          
      var localNode = {
            "name": value.name,         
            "group": value.group,
            "label": value.label,
            "level": level,
            "count": count,
            "linkCount": value.children.length,
            "children": children
          };
      nodes.push(localNode);    

      if(value.children.length > 0){
        level++;
        for(var c=0;c<value.children.length;c++){
          that.recursiveNode(value.children[c], nodes, level);
        }
      }
    },
    createNode: function(data){
      var that = this;
      var nodes = new Array();

      $.each(data, function(index, value) { 
        var level = 0;    
        that.recursiveNode(value, nodes, level);
      });

      return that.discoverChildren(nodes);
    },
    findPosition: function(nodes, c){   
      var pos = 0;
      $.each(nodes, function(i, x) {
        if(x.name == c){
          pos = i;
          return false;
        }
      }); 
      
      return pos;
    },
    discoverChildren: function(nodes){
      var that = this;
      
      $.each(nodes, function( index, value ) {
        var childrenPositionArray = new Array();
        $.each(value.children, function(i, c) {
          childrenPositionArray.push(that.findPosition(nodes, c)); //positionOfChild
        });

        nodes[index]["childrenPositions"] = childrenPositionArray;
        nodes[index]["nodePosition"] = index;
      });

      return nodes;
    },
    createLinks: function(nodes){

      var links = new Array();

      $.each(nodes, function(i, val) {
        var source = val.nodePosition;
          
        if(val.childrenPositions.length > 0){
        
          for(var c=0;c<val.childrenPositions.length;c++){
            var target = val.childrenPositions[c];
              
             var localLink = {
                "source": source,
                "target": target,
                "depth": 1,
                "count": 1    
              };
            
            links.push(localLink);
          }
        }     
      });
          
      return links;
    }
  };
    

//////////

UPDATE -- 17th June 2020

this is the latest working version 4 -- but needs to integrate the patterns and the refactoring of data - https://jsfiddle.net/batv60je/1/

I've created a refactor function to take the input data and make nodes/links from it - https://jsfiddle.net/batv60je/4/

//////////

24th June 2020

the image from the pattern isn't sitting properly in the circle, wrong size or displacement? need to use readible labels for the items instead of ids. if a person clicks or hovers on a node I want to change the charge to cause a ripple effect. keen to stabilize this chart so it doesn't float off the edge of canvas. enter image description here http://jsfiddle.net/L9xodt1z

Relationship force chart I've refactored the old chart - and data configuration to generate the nodes/links to make this chart functional.

--the image from the pattern isn't sitting properly in the circle, wrong size or displacement?

--need to use readible labels for the items instead of ids.

--if a person clicks or hovers on a node I want to change the charge to cause a ripple effect.

--keen to stabilize this chart so it doesn't float off the edge of canvas.


来源:https://stackoverflow.com/questions/62115394/d3v4-force-chart-upgrade-clean-up

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!