将数据传递给 D3 函数 - Ext JS 4.2.2

Passing datum to D3 function - Ext JS 4.2.2

我正在尝试在 Ext JS 4.2 应用程序中使用 D3 实现类似的东西。

http://bl.ocks.org/mbostock/1153292

在D3中,'path.attr("d", linkArc);',调用linkArc函数并将数据传递给linkArc函数。这在 D3 世界中工作正常。

function tick() {
  path.attr("d", linkArc);
  circle.attr("transform", transform);
  text.attr("transform", transform);
}

function linkArc(d) {
  var dx = d.target.x - d.source.x,
      dy = d.target.y - d.source.y,
      dr = Math.sqrt(dx * dx + dy * dy);
  return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

但是,我正在尝试在 Ext JS 中使用它(D3 JS 在 afterRender() 函数中加载)-

(function() {
 
Ext.define("d3.widgets.D3Widgets", {
    extend: 'Ext.Component',
    alias: 'widget.d3_workflow',
    width: 800,
    height: 400, 
 circle : '',
 text : '',
    constructor: function(config) {
      ...
    },

    
    initComponent : function() {
     ...
    },

    afterRender: function() {
        this.loadScript(this.onD3Loaded, this);
        return this.callParent(arguments);
    },

 loadScript: function(callback, scope) {
  Ext.Loader.injectScriptElement('http://d3js.org/d3.v3.js', this.onLoad, this.onError, this);
  
    },

    onError : function() {
  console.log('On Error');
 },
 
 onLoad : function() {

  var nodes = {};
  
  var links = [
    {source: "Initiate", target: "Department Approver Approves", type: "licensing"},
    {source: "Department Approver Approves", target: "Division Approver Approves", type: "licensing"},
    {source: "Division Approver Approves", target: "End", type: "suit"}
  ];

  links.forEach(function(link) {
    link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
    link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
  });

  var width = 960,
   height = 500;
   
  var path = ''; 

  var force = d3.layout.force()
   .nodes(d3.values(nodes))
   .links(links)
   .size([width, height])
   .linkDistance(60)
   .charge(-300)
   .on("tick", this.tick(path))
   .start();

  var svg = d3.select("body").append("svg")
   .attr("width", width)
   .attr("height", height);

  // Per-type markers, as they don't inherit styles.
  svg.append("defs").selectAll("marker")
   .data(["suit", "licensing", "resolved"])
    .enter().append("marker")
   .attr("id", function(d) { return d; })
   .attr("viewBox", "0 -5 10 10")
   .attr("refX", 15)
   .attr("refY", -1.5)
   .attr("markerWidth", 6)
   .attr("markerHeight", 6)
   .attr("orient", "auto")
    .append("path")
   .attr("d", "M0,-5L10,0L0,5");

  var path = svg.append("g").selectAll("path")
   .data(force.links())
    .enter().append("path")
   .attr("class", function(d) { return "link " + d.type; })
   .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

  circle = svg.append("g").selectAll("circle")
   .data(force.nodes())
    .enter().append("circle")
   .attr("r", 6)
   .call(force.drag);

  text = svg.append("g").selectAll("text")
   .data(force.nodes())
    .enter().append("text")
   .attr("x", 8)
   .attr("y", ".31em")
   .text(function(d) { return d.name; });

  
 },
 
 
    onRender :function(ct, position) {     
        this.callParent(arguments);
    },

     // Use elliptical arc path segments to doubly-encode directionality.
 tick: function(path)  {
   console.log('Inside Tick --');
   path.attr("d", linkArc);
   circle.attr("transform", transform);
   text.attr("transform", transform);
 },

 linkArc: function(d) {
   var dx = d.target.x - d.source.x,
    dy = d.target.y - d.source.y,
    dr = Math.sqrt(dx * dx + dy * dy);
   return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
 },

 transform: function(d) {
   return "translate(" + d.x + "," + d.y + ")";
 }

});

})();

在tick函数中,调用linkArc函数使用

path.attr("d", linkArc);

并且 linkArc 函数定义为

linkArc:函数(d){ }

在 Ext JS 中,当这是 运行 时,我在浏览器控制台中收到以下错误 -

未捕获的 ReferenceError:未定义 linkArc

发生这种情况似乎是因为 linkArc 需要数据,但未通过。

在 Ext JS 中是否应该以不同的方式调用此函数?

谢谢

错误是因为linkArc没有定义在tick函数的范围内。您要么必须在 tick 函数中定义该函数,要么如下面的代码所示使用它。

解决方案一:

tick: function(path)  {
      var widget = this;
      console.log('Inside Tick --');
      path.attr("d", widget.linkArc);
      circle.attr("transform", widget.transform);
      text.attr("transform", widget.transform);
}

方案二:

tick: function(path)  {
      function linkArc(d) {
           var dx = d.target.x - d.source.x,
           dy = d.target.y - d.source.y,
           dr = Math.sqrt(dx * dx + dy * dy);
           return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
      };
      function transform(d) {
          return "translate(" + d.x + "," + d.y + ")";
      } 
      console.log('Inside Tick --');
      path.attr("d", linkArc);
      circle.attr("transform", transform);
      text.attr("transform", transform);
}

正如Gilsha所说,这是范围的问题。但是你还必须添加指向 transform 的正确指针,因为它不会给你一个错误,但它不会正常工作。

这是我使用的代码 fiddle:https://fiddle.sencha.com/#fiddle/lr6

Ext.application({
        name: 'Fiddle',

        launch: function() {
            Ext.create('Ext.window.Window', {
                width: 900,
                height: 500,
                itemId : 'd3TestWindow',
                title: 'Custom D3',
                listeners: {
                    afterrender: function(window) {
                        var nodes = {};
                        links.forEach(function(link) {
                            link.source = nodes[link.source] || (nodes[link.source] = {
                                name: link.source
                            });
                            link.target = nodes[link.target] || (nodes[link.target] = {
                                name: link.target
                            });
                        });

                        window.force = d3.layout.force().nodes(d3.values(nodes)).links(links).size([window.getWidth(), window.getHeight()]).linkDistance(60).charge(-300).on("tick", window.tick).start();

                        window.svg = d3.select("#" + window.id + "-innerCt").append("svg").attr("width", window.getWidth()).attr("height", window.getHeight());
                        window.appendPath();
                        window.appendCircle();
                        window.appendText();

                        // Per-type markers, as they don't inherit styles.
                        window.svg.append("defs").selectAll("marker").data(["suit", "licensing", "resolved"]).enter().append("marker").attr("id", function(d) {
                            return d;
                        }).attr("viewBox", "0 -5 10 10").attr("refX", 15).attr("refY", - 1.5).attr("markerWidth", 6).attr("markerHeight", 6).attr("orient", "auto").append("path").attr("d", "M0,-5L10,0L0,5");



                    }
                },
                appendPath : function () {
                    var me = this;
                    this.path = this.svg.append("g").selectAll("path").data(me.force.links()).enter().append("path").attr("class", function(d) {
                        return "link " + d.type;
                    }).attr("marker-end", function(d) {
                        return "url(#" + d.type + ")";
                    });
                },
                appendCircle: function() {
                    var me = this;
                    this.circle = this.svg.append("g").selectAll("circle").data(me.force.nodes()).enter().append("circle").attr("r", 6).call(me.force.drag);
                },
                appendText: function() {
                    var me = this;
                    this.text = this.svg.append("g").selectAll("text").data(me.force.nodes()).enter().append("text").attr("x", 8).attr("y", ".31em").text(function(d) {
                        return d.name;
                    });
                },
                transform: function(d) {
                    return "translate(" + d.x + "," + d.y + ")";
                },
                linkArc: function(d) {
                    var dx = d.target.x - d.source.x,
                        dy = d.target.y - d.source.y,
                        dr = Math.sqrt(dx * dx + dy * dy);
                    return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
                },
                tick :  function() {
                    var window = Ext.ComponentQuery.query('#d3TestWindow')[0];
                    window.path.attr("d", window.linkArc);
                    window.circle.attr("transform", window.transform);
                    window.text.attr("transform", window.transform);
                }
            }).show();
        }
    });