Sap BussinessObjects Design Studio-infoChart

来源:互联网 发布:什么软件ktv便宜 编辑:程序博客网 时间:2024/05/01 17:46

​简介:SAP BusinessObjects Design Studio(简称DesignStudio),是Sap 公司提供的一款开发BI/BO 前端的开发工具。主要用于迅速的生成报表,为商业智能业务提供分析。如果对做过sap BI相关项目应该有所了解,这里就不做多的详细介绍。详细信息请查看官网信息,下载官网资料需要有Sap账号。

其实,DesignStudio只不过是封装了一系列拖拽的控件,在浏览器的底层解析成html css js这些,连接Sap HANA/BW数据源 ,也就是与数据库查询的视图封装到产品里直接使用,便于 开发人员快速上手,目前只支持HANA/BW数据,不支持其他关系型数据库 。该产品能在市场生存下来,绝对是一个奇迹。当然背后的原因就是,该工具是与SAP的产品结合。如果是web端应用程序,我们做报表可以选择像百度的echarts 或者highCharts等开源插件用于自定义的开发是足够的。   这个东西今天主要的实现的就是对原生控件-Info-Chart的功能的扩展 。场景:根据原型图,我们无法满足客户的需求,然而客户强制指定该产品,我们无法更换产品,只好改良产品本身。

简单介绍Info-Chart 控件:主要用于显示常用的数据报表,例如折线图,条形图,饼图,雷达图,散点图,气泡图等。

问题描述:1.当报表里的info-chart当中 出现了数据纵轴measures值重合的时候,DesignStudio竟然默认堆叠到一起,而且数据的文本统一都是白色。无法根据图例的颜色来设置文本颜色便于区分,在展示方面,是不太美观。如下图所示:

 移除点击此处添加图片说明文字




​(说明:这里的数据源来自SCN社区库的插件所提供的数据源,正式开发一般采用HANA或者BW数据源,这里是为了方便我们的演示所用。SCN下载地址:https://blogs.sap.com/2015/12/22/scn-design-studio-16-sdk-components-ver-30/      git下载地址:https://github.com/org-scn-design-studio/community/sdkinstall/blob/master/releases/stable/org.scn.community.sdk.package_stable.zip?raw=true)。

在开发工具中Ctrl+F11,运行效果图如下:

 移除点击此处添加图片说明文字

​我们可以看见,在DesignStudio当中,我们的数据源设置了mesures值有3个,这里应该显示的是三条折线图。但是由于我设置了相同的 mesures值,导致了三条曲线重合。这个问题也是我们在开发报表的时候根据客户提供的数据发现出来了。这是产品本身就不支持的问题导致。而实际情况当中有重合但是却没有完全重合的情况,在一样报表中有多个infochart,就导致我们的报表及其的不美观。 客户要求我们必须把重合的数据分离开。当时问了SAP官方人员,结果人家一句不支持直接给我们怼回来了。百度了一下,没有这方面的资料。翻墙上youtube查询,只有基础教程,却没有这方面的问题。 好在本屌在学习该产品的时候,在SCN上面看见了一款插件,里面可以编写js代码。于是,在浏览器中观察了infochart底层的元素规律,最后发现是由SVG元素组成。如下图:

 移除点击此处添加图片说明文字

​js插件就是和数据源一起的插件

 移除点击此处添加图片说明文字

​在图片的右边可以看见,是有编写js的区域。于是本屌就花了1天,怼出针对N条曲线文本数据重合的情况,再次执行之后,可以看见效果如下图所示:

 移除点击此处添加图片说明文字

​我们可以看出,重合的数据被分离开来,而且是根据图例的颜色动态生成。针对N条曲线,还适用于联合图:柱状图和折现的联合图。使用说明:每个infochart放在一个 panel当中,在js当中 设置panel名称,则会读取所有的panel下的infochart。如图:

 移除点击此处添加图片说明文字

​运行效果:

 移除点击此处添加图片说明文字


代码下载地址:https://github.com/Rain-R/Sap-DesignStudio

具体代码如下:

  <script>

  /**

 *@author:Rain

 *@date:Aug. 18th,2017

 *@description:由于Sap BuessinessObject DesignStudio工具中图标组件本身并不支持

 *图表数据文本的颜色以及高亮,该js文件用于自定义开发

 **/

  $(document).ready(function(){

 //DesignStudio中所有的图表控件的最完成panel的name

 //var panels=[ "PANEL_GC01","PANEL_GC10","PANEL_GC11","PANEL_GC20","PANEL_GC21"];

 var panels=["PANEL_G01","PANEL_G02"];

 //var panel10=$("div[id^='PANEL_G20']");

 var svg,datapoint,groups;

 //从transform里面拆分坐标值

 var getData=function(type,string){

  if(type=='left'){

   var left=string.split(",")[0];

   left=left.split("(")[1];

   return parseFloat(left);

  }else{

   var top=string.split(",")[1];

   top=top.substring(0,top.length-1);

   return parseFloat(top);

  }

 };

 var  count=0;

  //接受所有的文本节点分组

    var textLabelGroups=[];

     var  textLabelGroup=[];  //每一组,每一条线的文本节点数组

     var  panelId;

     var  rectTopMax;

     var  rectTopMin=7.0;

     var  textColors=[];

     var  monthLJWC=-1;

     var  monthGDJH=-1;

 var init=function(){

  setTimeout(function(){

   ///所有的折现图

   for(var index=0;index<panels.length;index++){

    panelId="div[id^='"+panels[index]+"']";

    var panel=$(panelId);

    svg=$(panel.find("svg")[0]);  //对于一个区域有多个 

    rectTopMax=$(panel.find("rect")[0]).attr("height");

     textColors=[];//获取图例的颜色

    $(svg.find(".v-groups")[0]).find("path").each(function(index,node){

     textColors.push($(node).attr("fill"));

     });

       svg.find(".v-legend-element").each(function(index,node){

     if( $($(node).find("tspan")[0]).html()=='累计完成'){

      monthLJWC=index;

    // console.info("累计完成当前月份是------------------>"+index) 

     }

     if($($(node).find("tspan")[0]).html()=='滚动计划'){

      monthGDJH=index;

    //  console.info("滚动计划当前月份是------------->"+index);

     }

    });   

  //  svg=$(panel10.find("svg")[0]);

    //获得所有线条节点的文本值节点

    groups=$(svg.find(".v-datalabel-group")[0]).children("g");

    resetFun();

    textLabelGroups=[];

   }


 },2000); 

 }  

    init(); 

   window.onresize=function(){       $(".labelTipPOP").hide(); init();} 

   $(".iconClose").click(function(){

      $(".labelTipPOP").hide();

   });


  function    resetFun(){

  //获得线条

   datapoint=svg.find(".v-datapoint-group").children("g");

   datapoint.each(function(index,value){

    //获取每根线条上面的节点 b==一个节点

   var gs=$(value).children("g");  

   gs.each(function(a,b){

   //d==每个节点的文本值节点

   groups.each(function(c,d){

   if($(b).attr("data-datapoint-id") && $(d).attr("data-datapoint-id")){

    if($(b).attr("data-datapoint-id")==$(d).attr("data-datapoint-id")){

    textLabelGroup.push(d);//获取所有的文本节点与圆圈节点对应

      }

    }

   });

     });

     textLabelGroups.push(textLabelGroup);//每条线的文本节点分组

     textLabelGroup=[];

        });

   setDataLableColor(textLabelGroups); //设置文本节点的颜色 

       var  textLeft=[];

       var  textEveryMonth=[];

  textEveryMonth=textLabelGroupsToEveryMonth(textLabelGroups,textLeft);//将文本节点分组转换成  每个月对应的分组

  //每条折现 当中默认拥有整个横轴的长度  没有数据的节点设置为null 

    for(var k=0;k<textEveryMonth.length;k++){

    var  tempGroup=[];

    tempGroup=deleteNullTextLabelAndSort(textEveryMonth,k);

      for(var xtop=tempGroup.length-1;xtop>0;xtop--){

         var  topValue=getData("top",$(tempGroup[xtop]).attr("transform"));

          console.info("panelId-->"+panelId+"第"+(k+1)+"月");

         var  tempTopValue=getData("top",$(tempGroup[xtop]).attr("transform"));

         var  everyTopMax=getData("top",$(tempGroup[tempGroup.length-1]).attr("transform"));

        //如果最大的点有足够的偏移的空间

  /*   if( k==10 && panelId=="div[id^='PANEL_POP']"){

     console.info("panelId-------------->"+panelId);//

     if( everyTopMax>(10*(xtop+1 )+10 )){

      if(getData("top",$(tempGroup[xtop-1]).attr("transform"))+10>tempTopValue ){ //

       $(tempGroup[xtop-1]).attr("transform","translate("+(getData("left",$(tempGroup[xtop-1]).attr("transform")))+","+(getData("top",$(tempGroup[xtop]).attr("transform"))-15)+")");

      if(getData("top",$(tempGroup[xtop-1]).attr("transform"))<=10){

         console.info("第"+(xtop)+"个点向上偏移3")

       $(tempGroup[xtop-1]).attr("transform","translate("+(getData("left",$(tempGroup[xtop-1]).attr("transform")))+","+(getData("top",$(tempGroup[xtop-1]).attr("transform"))+3)+")");

      }

     }

    }else{

     $(tempGroup[xtop]).attr("transform","translate("+(getData("left",$(tempGroup[xtop]).attr("transform")))+","+(getData("top",$(tempGroup[xtop-1]).   attr("transform"))+20)+")");

      for(var s=xtop-1;s>0;s--){

       console.info("第"+(s)+"个点向下偏移")

       $(tempGroup[s]).attr("transform","translate("+(getData("left",$(tempGroup[s]).attr("transform")))+","+(getData("top",$(tempGroup[s-1]).attr("transform"))+10)+")");

     } 

    }

            }else{ */

     if( everyTopMax>(10*(xtop+1 )+10 )){

       if(getData("top",$(tempGroup[xtop-1]).attr("transform"))+10>tempTopValue ){ //

        $(tempGroup[xtop-1]).attr("transform","translate("+(getData("left",$(tempGroup[xtop-1]).attr("transform")))+","+(getData("top",$(tempGroup[xtop]).attr("transform"))-15)+")");

       if(getData("top",$(tempGroup[xtop-1]).attr("transform"))<=10){

        console.info("第"+(xtop)+"个点向上偏移3")

         $(tempGroup[xtop-1]).attr("transform","translate("+(getData("left",$(tempGroup[xtop-1]).attr("transform")))+","+(getData("top",$(tempGroup[xtop-1]).attr("transform"))+3)+")");

          }

      }

        }else{

       $(tempGroup[xtop]).attr("transform","translate("+(getData("left",$(tempGroup[xtop]).attr("transform")))+","+(getData("top",$(tempGroup[xtop-1]).attr("transform"))+20)+")");

       for(var s=xtop-1;s>0;s--){

        console.info("第"+(s)+"个点向下偏移")

      $(tempGroup[s]).attr("transform","translate("+(getData("left",$(tempGroup[s]).attr("transform")))+","+(getData("top",$(tempGroup[s-1]).attr("transform"))+10)+")");

       } 

        }

                //}//

   //判断结束

      }

    }

     //显示当累计完成和滚动计划的当前月

     var monthIndex=(new Date()).getMonth()-1;

   if(monthLJWC>=0){

        //alert($(textEveryMonth[monthIndex][monthLJWC]));

        if(textEveryMonth[monthIndex][monthLJWC]!=null ){

         var  g=$(textEveryMonth[monthIndex][monthLJWC]).get(0);

         showHight(g,monthLJWC);

        }

       } 

       if(monthGDJH>=0){

          if(textEveryMonth[monthIndex][monthGDJH]!=null ){

          var  g=$(textEveryMonth[monthIndex][monthGDJH]).get(0);

        showHight(g,monthGDJH);

        }  

         }  

  }

     //设置文本节点的颜色

  var   setDataLableColor=function(textLabelGroups){

    for(var index=0;index<textLabelGroups.length;index++){

        var colorIndex=index;  

        for(var  textIndex=0;   textIndex <textLabelGroups[index].length;textIndex++){

         var text=$(textLabelGroups[index][textIndex]);

         text.attr("fill",textColors[colorIndex]);

       }       

       }

         }

     var   showHight=function(g,color){                                                                                                                                                          

    var  gTop=g.getBoundingClientRect().top+2;

    var  gLeft=g.getBoundingClientRect().left;

    var  gWidth=(g.getBoundingClientRect().width+7)+"px";

    var div=$("<div class='labelTipPOP'  style='position:absolute;z-index:8888;height:13px;font-size:10px;width:20px'></div>");

    var gText=$(g).html();

    $("body").append(div);

    div.css("top",gTop);

    div.css("left",gLeft);

    div.css("width",gWidth);

    div.html(gText);

    //div.css("border","2px solid "+textColors[color]);

    //div.css("border-color",);     

     div.css("background-color",textColors[color]); 

      }

  var   textLabelGroupsToEveryMonth=function(textLabelGroups,textLeft){

              var  textEveryMonth=[];

              for(var  groupIndex=0;groupIndex<textLabelGroups.length;groupIndex++){ 

       if(groupIndex==0){

        //第一条为年度计划的节点默认都有值     折线默认的对应的每个横轴的节点存在 

           for(var textIndex=0;textIndex<textLabelGroups[groupIndex].length;textIndex++ ){

          textLeft.push(textLabelGroups[groupIndex][textIndex]);//12个月的长度

          var temp=[];

          temp.push(textLabelGroups[groupIndex][textIndex]);

          textEveryMonth.push(temp);

         }

       }else{

         //其他的折线 如果对应的横轴节点上面没有节点存储null

          for(var  i=0;i<textLeft.length;i++){

         var textLeftX= getData("left",$(textLeft[i]).attr("transform"));//年度计划为基准

          for(var j=0;j<textLabelGroups[groupIndex].length;j++){

            var  everyLineLeftX=getData("left",$(textLabelGroups[groupIndex][j]).attr("transform"));

          //如果对应的位置有     

            if(everyLineLeftX==textLeftX|| (everyLineLeftX-textLeftX)< 20 && (everyLineLeftX-textLeftX)>-20         ){

             textEveryMonth[i][groupIndex]=textLabelGroups[groupIndex][j];

              break; 

           }

          }

          if( textEveryMonth[i][groupIndex]==undefined){    textEveryMonth[i][groupIndex]=null;           } 

           }

       }

     }

           return textEveryMonth;

   } 

  var    deleteNullTextLabelAndSort=function(textEveryMonth,k){

                            //第一条折线默认有所有节点的值存在

     var  textOneTop=getData("top",$(textEveryMonth[k][0]).attr("transform"));

       // minTop=textOneTop; 

     var  tempGroup=[];

     var  monthGroup=[];

       //将横轴对应的不为空的节点 放在一个数组里面并排序 

     for(var t=0;t<textEveryMonth[k].length ;t++){

       if(textEveryMonth[k][t]!=null){

       tempGroup.push(textEveryMonth[k][t]);

       monthGroup.push(textEveryMonth[k][t]);

       }

     }

     console.info("每个月的点的数量-->"+tempGroup.length);

      //按 top值排序

       for(var index=0;index<tempGroup.length;index++){

       var m=index;

       for(var j=m+1;j<tempGroup.length;j++){

       if(getData("top",$(tempGroup[j]).attr("transform"))<= getData("top",$(tempGroup[m]).attr("transform"))){

       m=j;

     }

       }

       if(index!=m){

       var  tempNode= tempGroup[index];

       tempGroup[index]=tempGroup[m];

       tempGroup[m]=tempNode;

       }

       }

       return  tempGroup;

         }   

  //jq end 

  });

</script>