Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
david_stocker
Advisor
Advisor

This is part of a tutorial series on creating extension components for Design Studio.


In our last installment, we got our arc into a Design Studio component.    All of the properties of our arc - color, start and end angles, inner and outer radii and centerpoint - were hardcoded.  In this installment, we're going to lay the groundwork for making our gauge's basic display properties configurable.  For this installment, we're returning to our pure .html file sandbox and investigate what our javascript needs to look like.

For starters, we need to get a handle on all of the attributes that we'll need to need.  These basic display properties will be with us for the entire series and well add others as they become nescessary:

  • Width and Height -  These attributes are inherited from the SDK framework and are properties of all Design Studio components; whether standard or extension.  These two attributes are going to define the box that we'll want to fit our gauge into.
  • Start Angle (in degrees) - This is the starting angle of the arc., with 0 degrees being straight up and +/-180 degrees being straight down.  When we actually declare the arc in D3, we'll do it in radians, but we can't expect our users to work with this unit of measure.
  • End Angle (in degrees) - Finishing angle of the arc.
  • Padding (Top/Bottom/Left/Right) - It may be that we don't want to use the full component height and width.  So we'll include properties for padding between the edge of the gauge and the edge of the component.  This defines the bounding box of the gauge. (See picture, below)
  • Inner Radius of the Arc - 0 of it is a pie, greater than 0 if we want a doughnut.
  • Outer Radius of the Arc - The distance between the centerpoint of the gauge and the nearest box edge. 
  • Centerpoint - This is the origin, around which the gauge arc will be drawn. 
  • Color - The color od the arc.

Step 3a.1 -

These properties are not wholy independent from one another.  For example, given a centerpoint, outer radius and padding, we could calculate the height and width of the component.  This is perhaps the cleanest way of defining gauge size and location.  The height and width are standard properties however.  Therefore, we'll be calculating the centerpoint and outer radius, given the height, width and padding properties.

Some properties can be declared as properties.  We'll be adding them to the properties pane in the next instalment, but for now, we can hardcode them for the purposes of our html sandbox.  The dimension values represent pixels.


//Viz definitiions


var innerRad = 0;


var width = 200;


var height = 200;


var startAngleDeg = -90;


var endAngleDeg = 90;


var colorCode = "red";



//Outer Dimensions & Positioning


var paddingTop = 10;


var paddingBottom = 10;


var paddingLeft = 10;


var paddingRight = 10;













Step 3a.2 -

First, we need to define the outer radius.  We'll use this simple rule of thumb.  If we draw the arc in 360 degrees, creating a circle, it will be equally large on both the X and Y axes.  Therefore, it's diameter should be the smaller of the axes inside the bounding box.  In the picture below, the vertical axis is the smaller of the two; therefore, it will be used.

The following Javascript code should do the trick:


//The total size of the component is calculated from its parts



// Find the larger left/right padding


var lrPadding = paddingLeft + paddingRight;


var tbPadding = paddingTop + paddingBottom;


var maxPadding = lrPadding;


if (maxPadding < tbPadding){


  maxPadding = tbPadding


}



var outerRad = (width - 2*(maxPadding))/2;








Step 3a.3 -

We'll want to position the origin of the arc at the very centre of the component.


//The offset will determine where the center of the arc shall be


var offsetLeft = width/2;


var offsetDown = height/2;








Step 3a.4 -

It is entirely possible that the user might put in some nonsensical parameters, so we'll want to insert a minimal bit of defensive programming here.  Specifically, we'll want to make sure that the arc does not have a negative radius:


//Don't let the innerRad be greater than outer rad


if (outerRad < innerRad){


  outerRad = innerRad;


  alert("Warning!  The gauge arc has a negative radius.  Please decrease the inner radius, or increase the size of the control.  Height & width (including subtraction for padding) must me at least twice as large as Internal Radius.!");


}








Step 3a.5 -

Let's go back and revisit the code for creating the arc and attaching it to the sag element, that we created in steps 2a.3 - 2a.5 in instalment 2a.  We can replace the hardcoded height, width, radii and offsets with the variables, that we defined above.


var arcDef = d3.svg.arc()


  .innerRadius(innerRad)


  .outerRadius(outerRad)


  .startAngle(startAngleDeg * (pi/180)) //converting from degs to radians


  .endAngle(endAngleDeg * (pi/180)); //converting from degs to radians





var guageArc = vis.append("path")


  .style("fill", colorCode)


  .attr("width", width).attr("height", height) // Added height and width so arc is visible


  .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")")


  .attr("d", arcDef);







Step 3a.6 -

Putting everything together, our html file should look like this:


<!DOCTYPE html>


<html>


  <head>


  <meta http-equiv='X-UA-Compatible' content='IE=edge' />


  <title>Part 3</title>


  <div id='content'></div>


  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>


  <script>


  var vis = d3.select("#content").append("svg:svg").attr("width", "100%").attr("height", "100%");



  var pi = Math.PI;



  //Viz definitiions


  var innerRad = 0;


  var width = 200;


  var height = 200;


  var startAngleDeg = -90;


  var endAngleDeg = 90;


  var colorCode = "red";




  //Outer Dimensions & Positioning


  var paddingTop = 10;


  var paddingBottom = 10;


  var paddingLeft = 10;


  var paddingRight = 10;



  //The total size of the component is calculated from its parts



  // Find the larger left/right padding


  var lrPadding = paddingLeft + paddingRight;


  var tbPadding = paddingTop + paddingBottom;


  var maxPadding = lrPadding;


  if (maxPadding < tbPadding){


  maxPadding = tbPadding


  }



  var outerRad = (width - 2*(maxPadding))/2;


  //var width = (outerRad * 2) + paddingLeft + paddingRight;


  //var height = (outerRad * 2) + paddingTop + paddingBottom;



  //The offset will determine where the center of the arc shall be


  var offsetLeft = width/2;


  var offsetDown = height/2;



  //Don't let the innerRad be greater than outer rad


  if (outerRad < innerRad){


  outerRad = innerRad;


  alert("Warning!  The gauge arc has a negative radies.  Please decrease the inner radius, or increase the size of the control.  Height & width (including subtraction for padding) must me at least twice as large as Internal Radius.!");


  }



  var arcDef = d3.svg.arc()


  .innerRadius(innerRad)


  .outerRadius(outerRad)


  .startAngle(startAngleDeg * (pi/180)) //converting from degs to radians


  .endAngle(endAngleDeg * (pi/180)); //converting from degs to radians



  var guageArc = vis.append("path")


     .style("fill", colorCode)


     .attr("width", width).attr("height", height) // Added height and width so arc is visible


     .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")")


     .attr("d", arcDef);


  </script>


    </head>


  <body class='sapUiBody'>


  <div id='content'></div>


  </body>


</html>






Step 3a. 7 -

When we open the html file in a browser, it should look like the following:

Feel free to play around with the various geometry parameters and get a feel for how they affect the arc.

Next time, we'll add those properties to the component's Properties's Pane in Design Studio.

As always, the completed extension (as of part 3) is available as a Github repository.

2 Comments