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
0 Kudos

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

The next feature that we want to add to our gauge is text callouts.  While it is certainly possible to position text labels where you want them and bind them to the data that you want to display, the approach that we will take in this installment has the advantage of being dynamic.  If the gauge guide line angles change, or if the display angle changes, we can dynamically reposition our callouts.  We want to be able to display the value of the measure, as well as the minimum and maximum values.

Before we begin adding our callouts to the sandbox file's gauge prototype, we'll create a second, simpler sandbox in order to explore the SVG text element.  The initial version uses D3's line drawing capacity (first examined in Part 8a) to create a 200x200px svg element and then draw a par of centered crosshairs.  That starter file is laid out here:


<!DOCTYPE html>


<html>


  <head>


  <title>Text with D3</title>


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


    </head>


  <body>


  <script>


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



  //Crosshairs


  var horizLineData = [{x:0, y:100}, {x:200, y:100}];


  var vertLineData = [{x:100, y:0}, {x:100, y:200}];




  var lineFunction = d3.svg.line()


  .x(function(d) { return d.x; })


  .y(function(d) { return d.y; })


  .interpolate("linear");



  var xAxis = vis


  .append("path")


  .attr("d", lineFunction(horizLineData))


  .attr("stroke", "black")


  .attr("stroke-width", 1)


  .attr("fill", "none");



  var yAxis = vis


  .append("path")


  .attr("d", lineFunction(vertLineData))


  .attr("stroke", "black")


  .attr("stroke-width", 1)


  .attr("fill", "none");


  </script>


  </body>


</html>







It has a very simple result:

Adding our first text element is very simple.  Anywhere in the script, where vis has already been declared (e.g. at the end), simply as the following:


//Text


var textElementMeasure = vis.append("text")


  .attr("transform", "translate(" + 100 + "," + 100 + ")")


  .text("Hello World");







So we now have drawn our first text element in D3.  There are a couple of things to note here.  Firstly, unless you have modified your browser's default font, "Hello World" is probably written in some member of the Times family (e.g. Times New Roman, Times-Roman, etc., depending on the browser and OS) at at a size of 16px.  This is because there are default style attributes to the fonts, assigned by the browser.  Secondly, while using a horizontal and vertical transformation of 100x each puts our position at the center of the crosshair, that is the lower left position of the text.  There are also default font attributes for governing horizontal and vertical positioning of the text.

A Side Digression: CSS

So far in this tutorial series, we've manipulated element attributes via raw JavaScript.  .attr() has become an old friend.    Many of these attributes (e.g. color, opacity, stroke) are also editable via CSS.  Virtually every aspect of text is editable in CSS, such as the font, font size, horizontal and vertical position.  Strictly speaking, it is considered a web design best practice to do everything possible in CSS.  This is the much more modern and professional way of building websites, as it allows a reskinning of the app by swapping out stylesheets.  We are not designing for professional web designers however.   The BI app designer persona is not presumed to be skilled with CSS and asking them to edit the application's visuals with CSS is asking a lot.   We'll leave two aspects of the text callouts - the font and font size - as the exercise for CSS in part 12.  Since we'll need fairly complex algorithms to determine when to use which settings for horizontal and vertical alignment, we'll handle those attributes in JavaScript.

Horizontal Positioning of Text

The attribute that governs the horizontal justification of text is text-anchortext-anchor has three possible values:

  • start - left justifies the text, so that it starts at the xy position of the text element.
  • end - right justifies the text, so that it ends at the xy position of the text element.
  • middle - centers the text horizontally at the xy position.

The table below shows these text-anchor values in action:

.attr("text-anchor", "start").attr("text-anchor", "middle").attr("text-anchor", "end")

Vertical Positioning of Text

There are two  attributes that govern vertical position of text in an SVG element:

  • dominant-baseline -  This is an SVG only attribute that can greatly simplify the vertical justification of text.  Unfortunately, it is not supported by all browsers.  Specifically, Mobile Safari and Microsoft browsers don't support dominant-baseline.  This becomes a potential problem as the Design Studio designer is an eclipse based application and browser windows in eclipse can only use the platform's default browser.  In practice, this means that the canvas in the DS designer is always internet explorer or edge.  So if the users were using Chrome, the designer would see the text callouts displayed differently than the users at runtime.  If the app was being run on an Apple mobile device, then there would be no dominant-baseline.
  • dy - this is not only an SVG property, but a general html property.  It may be defined in terms of "em", where 1em = the current vertical font size.  If the em value is negative, then the text is moved upward and if it is positive, then it is moved downward.  We will use dy vertically position our text.

The table below shows the corresponding dominant-baseline and dy values in action.

dominant-baselinedy

  .attr("dominant-baseline", "ideographic");

  .attr("dy", "-.2em");

  .attr("dy", "0em");

  .attr("dominant-baseline", "hanging");

  .attr("dy", "0.8em");

.attr("dominant-baseline", "text-after-edge");

.attr("dy", "1em");

Next time, we are going to pout these attributes to use and create the algorithms to dynamically set text-anchor and dy when we reposition our callouts.