Sapui5 Openui5中的D3js自定义控件问题

Sapui5 Openui5中的D3js自定义控件问题,sapui5,Sapui5,我正在使用openui5 Tabstrip。每个选项卡包含单独的js和控制器。 同样,每个选项卡包含两个视图(我使用的是sap.m.NavContainer),每个视图都是一个单独的js视图。 我为D3JS子弹图编写自定义控件,如下所示 蓟马变种 /*Bullet chart:包装一些D3.js代码的UI5自定义控件*/ sap.ui.core.Control.extend("control.BulletChart", { /* the control API */ metad

我正在使用openui5 Tabstrip。每个选项卡包含单独的js和控制器。 同样,每个选项卡包含两个视图(我使用的是sap.m.NavContainer),每个视图都是一个单独的js视图。 我为D3JS子弹图编写自定义控件,如下所示 蓟马变种

/*Bullet chart:包装一些D3.js代码的UI5自定义控件*/

sap.ui.core.Control.extend("control.BulletChart", { 
    /* the control API */
    metadata : {
         properties : {
                "items" : { type: "any" },
                "colorType" :{type:"string"},
                "height" : {type: "int"},
                "width" : {type: "int"},
                "popup" : {type: "any"}
            },
        events: {
            "select" : {},
            "selectEnd": {},
            //"click": {}
        }           
    },


    // the part creating the HTML:
    renderer : function(oRm, oControl) {    
        oRm.write("<div"); 
        oRm.writeControlData(oControl); 
        oRm.addClass("bullet");             
        oRm.writeClasses();                             
        oRm.write(">");
        oRm.write("</div>");
    },

    onAfterRendering: function() {
        var that = this;

        var deepClonedCopy = jQuery.extend(true, {}, this.getItems());
        var data;
        data = $.map(deepClonedCopy, function(el) { return el });
        var customId=this.getId();

        if(data){
        if(data[0]){
        data[0].ranges = JSON.parse("["+data[0].RANGES+"]");
        data[0].measures = JSON.parse("["+data[0].MEASURES+"]");
        data[0].markers = JSON.parse("["+data[0].MARKERS+"]");
        }

        var containerWidth = $("#"+customId).parent().width(); 
        var margin = {top: 15, right: 30, bottom: 20, left: 30},
        width = containerWidth- margin.left - margin.right,
        height = 65 - margin.top - margin.bottom;

        console.log("Actual bulletWidth",width);
        var chart = d3.bullet()
        .width(width)
        .height(height);
        var classType;
        if(this.getColorType()){
            classType = "reversebullet";
        }
        else{
            classType = "bullet";
        }
        var svg = d3.select("#"+customId).selectAll("svg")
          .data(data)
        .enter().append("svg")
          .attr("class", classType)
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
          //.on("click", click)
          .append("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
          .call(chart);
         }

});  
在我的控制器中,以下代码是用onInit编写的:

var oBusinessData = {
                                    "genericData":[
                                        { "key":"1","RANGES":"50,75,100","MEASURES":20,"MARKERS":80,"tab":"sdto"},
                                ]};
buBullet.setModel(new sap.ui.model.json.JSONModel(oBusinessData ));
根据上面的代码,当我第一次打开tab时,它工作得很好,但当我切换tab时,我的项目符号图表显示压缩。当我向
var containerWidth=$(“#”+customId.parent().width()发出警报时我看到的宽度比实际宽度小,这可能是因为图表渲染速度比其父级快,因此放置setTimeout暂时解决了问题,但不是一个正确的修复方法。有人能告诉我们如何避免它,并在视图呈现后呈现图表吗。因此,上面的问题是在一个选项卡中使用两个视图的navcontainer时。
如果我从一个选项卡切换到另一个选项卡,然后返回同一个选项卡,则活动视图工作正常,但如果我导航到第二个视图,则会出现问题。

此问题仅在我更改选项卡视图时发生。

您应该向控件注册onAfterRendering事件,而不是使用“setTimout”,这样可以在渲染完成时获得正确的计时

parentControl.addEventDelegate({  
                  "onAfterRendering": function() {  
                      // parentControl has been rendered, here comes the code..
                      // Now here has the rendering finished, now you can get 
                      // the correct height of parentControl.
                  }  
            }, this);   

编辑了评论,希望对您有所帮助;)

它与上述代码中的onAfterRendering有何不同。不同之处在于,在呈现customcontrol时会调用您实现的onAfterRendering方法。但您需要父控件的高度,因此,您必须为父控件设置一个onAfterRendering事件。我编写了类似的内容,但我得到了
错误:未能从./chartControls/customBullet.js加载'chartControls/customBullet.js'。语法错误:缺少:在属性id
之后。我尝试了它,得到的结果与没有超时的结果相同。
parentControl.addEventDelegate({  
                  "onAfterRendering": function() {  
                      // parentControl has been rendered, here comes the code..
                      // Now here has the rendering finished, now you can get 
                      // the correct height of parentControl.
                  }  
            }, this);