This is part of a tutorial series on creating extension components for Design Studio.
Last time, we brought our dynamic text callouts into the sandbox html file. In this installment, we're going to bring them to the gauge component. We'll spare ourselves the need to expose any properties to the script API, as - like with animations - callouts are likely something that the designer will strictly want to control. (though an argument could also be made for user control and this could be a feature added later) This leaves us with integrating the new code from kast time into component.js and adding the required properties.
To review, when we added the callout JavaScript code to our sandbox html file, we started off by declaring four variables that we later used for controlling the callouts:
var guidePositioning = "end"; //"end" and "midpoint"
var measureTextPositionType = "upperCentral";
var drawGuideText = true;
var drawMeasureText = true;
We'll add these four as properties. The two draw… properties will be booleans, while the other two will be enumerated strings. In addition, the callouts were hardcoded in the sandbox version. In the component, we'll either want to use the relevant measure values, or (much less likely) the angle values. In practice, this means that:
None of these will require their own binding. Instead, we'll refer back to the useMeasures property, that we introduced all the way back in Part 6a. If the designer has decided to use measure values to define the gauge angles, then it makes no sense to display the angle values; and vice versa.
So our part 11 property declarations look like the following:
<!-- Part 11 -->
<property id="drawMeasureText"
title="Enable Measure Text"
type="boolean"
tooltip="Enable in-component measure value display?"
group="SCNGaugeTextCallouts"/>
<property id="measureTextPositionType"
title="Measure Text Position Type"
type="String"
tooltip="Position of the measure text value"
group="SCNGaugeTextCallouts">
<possibleValue>endpoint</possibleValue>
<possibleValue>upperCentral</possibleValue>
<possibleValue>upperIdeographic</possibleValue>
<possibleValue>lowerIdeographic</possibleValue>
<possibleValue>lowerCentral</possibleValue>
<possibleValue>bottom</possibleValue>
</property>
<property id="drawGuideText"
title="Enable Guide Text"
type="boolean"
tooltip="Enable in-component guide line value display (guide lines don't need to be enabled to show the text)?"
group="SCNGaugeTextCallouts"/>
<property id="guidePositioning"
title="Guide Text Position Type"
type="String"
tooltip="Position of the guide text value, along the guide axis (middle or end)"
group="SCNGaugeTextCallouts">
<possibleValue>end</possibleValue>
<possibleValue>middle</possibleValue>
</property>
In keeping with the good parctice of using sensible defaults, we'll set the following default values in the Initialization element (we do not default to displaying callouts):
<initialization>
...
<defaultValue property="drawMeasureText">false</defaultValue>
<defaultValue property="measureTextPositionType">upperCentral</defaultValue>
<defaultValue property="drawGuideText">false</defaultValue>
<defaultValue property="guidePositioning">end</defaultValue>
</initialization>
We'll start with the textPositioning() function, introduced last time. It will require only minimal changes when being copied over as a new function within component.js the offsetXXX variables will need to move into the me._ namespace.
//New with Part 11
// Helper function to determine the vertical alignment (called 'dominant-baseline') and horizontal alignment (called ' text-anchor')
// In essence, this function tries to find a readable position for the text, so that it lies ourside the main arc, no matter the current
// x and y are the absolute positions of the callout, within the component
// isMiddleCallout determines whether this is anchored on the middle of a guide line
// isStart determines whether or not this the start callout. this function will try to position the callouts anchoren on the middle
// guide line outside of the gauge arc.
// text-anchor: https://developer.mozilla.org/en/docs/Web/SVG/Attribute/text-anchor
function textPositioning (x, y, isStart){
var relativeOffsetX = x - me._offsetLeft;
var relativeOffsetY = y - me._offsetDown;
if (isStart == undefined){
isStart = false;
}
var dominantBaseline = null;
var textAnchor = null;
if ((relativeOffsetX >= 0) && (relativeOffsetY >= 0)){
//Lower Right Quadrant
// Both middle and enf have a negative dominant baseline
if (isStart == true){
textAnchor = "start";
dominantBaseline = "0em";
} else {
textAnchor = "end";
dominantBaseline = ".8em";
}
} else if ((relativeOffsetX >= 0) && (relativeOffsetY < 0)){
//Upper Right Quadrant
if (isStart == true){
textAnchor = "end";
dominantBaseline = "0em";
} else {
textAnchor = "start";
dominantBaseline = ".8em";
}
}
else if ((relativeOffsetX < 0) && (relativeOffsetY < 0)){
//Upper Left Quadrant
if (isStart == true){
textAnchor = "end";
dominantBaseline = ".8em";
} else {
textAnchor = "start";
dominantBaseline = "0em";
}
} else {
//Lower Left Quadrant
if (isStart == true){
textAnchor = "start";
dominantBaseline = ".8em";
} else {
textAnchor = "end";
dominantBaseline = "0em";
}
}
return [textAnchor, dominantBaseline]
}
The properties are also straightforward to bring into copmponent.js:
//Part 11 - Callouts
me._drawMeasureText = false;
me._measureTextPositionType = "upperCentral";
me._drawGuideText = false;
me._guidePositioning = "end";
And let's not forget our getter/setters:
//Part 11 Properties
me.drawMeasureText = function(value) {
if (value === undefined) {
return me._drawMeasureText;
} else {
me._drawMeasureText = value;
return me;
}
};
me.measureTextPositionType = function(value) {
if (value === undefined) {
return me._measureTextPositionType;
} else {
me._measureTextPositionType = value;
return me;
}
};
me.drawGuideText = function(value) {
if (value === undefined) {
return me._drawGuideText;
} else {
me._drawGuideText = value;
return me;
}
};
me.guidePositioning = function(value) {
if (value === undefined) {
return me._guidePositioning;
} else {
me._guidePositioning = value;
return me;
}
};
//End Part 11 Properties
And the 33 lines "Guide Positioning " code go to the end of the me.redraw() function. Don't forget to refactor it. The outerRad and xxxAnglexxx variables need a me._ prefix:
//Guide Positioning
if (me._drawGuideText == true){
var guidePositionStart = {};
var guidePositionEnd = {};
var isMiddleCO = false;
if (me._guidePositioning == "end"){
guidePositionStart = endPoints (me._outerRad, me._startAngleDeg);
guidePositionEnd = endPoints (me._outerRad, me._endAngleDegMax);
}
else {
guidePositionStart = endPoints (me._outerRad/2, me._startAngleDeg);
guidePositionEnd = endPoints (me._outerRad/2, me._endAngleDegMax);
}
var guideTextPositionStart = textPositioning (guidePositionStart.x, guidePositionStart.y, true);
var guideTextPositionEnd= textPositioning (guidePositionEnd.x, guidePositionEnd.y);
//Start Text
vis.append("text")
.attr("transform", "translate(" + guidePositionStart.x + "," + guidePositionStart.y + ")")
.text(calloutTextStart)
.attr("text-anchor", guideTextPositionStart[0])
//.attr("dominant-baseline", guideTextPositionStart[1]);
.attr("dy", guideTextPositionStart[1]);
//End Text
vis.append("text")
.attr("transform", "translate(" + guidePositionEnd.x + "," + guidePositionEnd.y + ")")
.text(calloutTextEnd)
//.attr("text-anchor", "start")
.attr("text-anchor", guideTextPositionEnd[0])
//.attr("dominant-baseline", guideTextPositionEnd[1]);
.attr("dy", guideTextPositionEnd[1]);
}
Here is a short demonstration video of it all coming together:
As usual, the current state of the project and the test app are in a public repository on Github. Next time, we'll have a look at styling the fonts in the callouts via SCC.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
10 | |
10 | |
10 | |
9 | |
8 | |
8 | |
6 | |
6 | |
5 | |
5 |