@syncfusion/ej2-circulargauge
Version:
Essential JS 2 CircularGauge Components
653 lines (627 loc) • 35.2 kB
text/typescript
/* eslint-disable max-len */
import { CircularGauge } from '../circular-gauge';
import { Pointer, Axis, NeedleTail, Cap } from './axis';
import { stringToNumber, textElement, appendPath, getAngleFromValue, getLocationFromAngle, getRoundedPathArc, calculateShapes, PathOption, Size, GaugeLocation, TextOption } from '../utils/helper-common';
import { linear, getCompleteArc } from '../utils/helper-pointer-renderer';
import { Animation, AnimationOptions, isNullOrUndefined, animationMode } from '@syncfusion/ej2-base';
import { animationComplete } from '../model/constants';
import { GaugeShape } from '../utils/enum';
import { FontModel } from '../model/base-model';
/**
* Specifies the Axis rendering for circular gauge
*/
export class PointerRenderer {
private gauge: CircularGauge;
/**
* Constructor for pointer renderer.
*
* @param {CircularGauge} gauge - Specifies the instance of the gauge.
* @private.
*/
constructor(gauge: CircularGauge) {
this.gauge = gauge;
}
/**
* Method to render the axis pointers of the circular gauge.
*
* @param {Axis} axis - Specifies the axis.
* @param {number} axisIndex - Specifies the axis index.
* @param {Element} element - Specifies the element.
* @param {CircularGauge} gauge - Specifies the instance of the gauge.
* @param {boolean} animate - Specifies the boolean value.
* @returns {void}
* @private
*/
public drawPointers(axis: Axis, axisIndex: number, element: Element, gauge: CircularGauge, animate: boolean = true): void {
const pointerElement: Element = gauge.renderer.createGroup({
id: gauge.element.id + '_Axis_Pointers_' + axisIndex
});
let childElement: Element;
if (this.gauge.allowComponentRender) {
axis.pointers.map((pointer: Pointer, pointerIndex: number) => {
if (!isNullOrUndefined(pointer.offset) && (<string>pointer.offset).length > 0) {
pointer.currentDistanceFromScale = stringToNumber(<string>pointer.offset, axis.currentRadius);
} else {
pointer.currentDistanceFromScale = <number>pointer.offset;
}
pointer.pathElement = [];
this.calculatePointerRadius(axis, pointer);
if (!gauge.allowPointerDrag) {
gauge.allowPointerDrag = pointer.enableDrag;
}
childElement = gauge.renderer.createGroup({
id: gauge.element.id + '_Axis_' + axisIndex + '_Pointer_' + pointerIndex
});
if (pointer.value != null) {
childElement.setAttribute('aria-label', pointer.description || 'Pointer:' + pointer.value.toString());
childElement.setAttribute('role', 'region');
}
this['draw' + pointer.type + 'Pointer'](axis, axisIndex, pointerIndex, childElement, gauge);
if (this.gauge.allowLoadingAnimation) {
(childElement as HTMLElement).style.visibility = 'hidden';
} else {
this.setPointerValue(axis, pointer, pointer.currentValue);
}
pointerElement.appendChild(childElement);
if (!this.gauge.allowLoadingAnimation && ((animate || pointer.animation.enable) || animationMode === 'Enable') && (!this.gauge.isPropertyChange || pointer.isPointerAnimation)) {
pointer.previousValue = !this.gauge.isPropertyChange ? axis.minimum : pointer.previousValue;
this.doPointerAnimation(childElement, pointer, axis, axisIndex);
}
});
element.appendChild(pointerElement);
}
}
/**
* Measure the pointer length of the circular gauge.
*
* @returns {void}
*/
private calculatePointerRadius(axis: Axis, pointer: Pointer): void {
const padding: number = 5;
pointer.currentRadius = !isNullOrUndefined(pointer.radius) ?
stringToNumber(pointer.radius, axis.currentRadius) : pointer.position !== 'Auto' ?
this.pointerRadiusForPosition(axis, pointer) : (axis.currentRadius - (axis.farSize + padding));
}
/**
* Measure the pointer length of the circular gauge based on pointer position.
*
* @returns {number}
*/
private pointerRadiusForPosition(axis: Axis, pointer: Pointer): number {
if (pointer.markerShape === 'Text') {
let pointerRadius: number;
const pointerSize: number = parseInt(pointer.textStyle.size, 10);
const markerOffset: number = pointer.position === 'Cross' ? pointerSize / 5 : 0;
// eslint-disable-next-line prefer-const
pointerRadius = pointer.position === 'Inside' ?
(axis.currentRadius - pointerSize / 1.2 - axis.lineStyle.width / 2 - markerOffset - pointer.currentDistanceFromScale) :
pointer.position === 'Outside' ?
(axis.currentRadius + axis.lineStyle.width / 2 + pointerSize / 4 + markerOffset +
pointer.currentDistanceFromScale) :
(axis.currentRadius - pointerSize / 6 - markerOffset - pointer.currentDistanceFromScale);
return pointerRadius;
} else {
let pointerRadius: number;
const rangeBarOffset: number = pointer.type === 'RangeBar' ? pointer.pointerWidth : 0;
const markerOffset: number = pointer.type === 'Marker' ? ((pointer.markerShape === 'InvertedTriangle' ||
pointer.markerShape === 'Triangle') ? (pointer.position === 'Cross' ? pointer.markerWidth / 2 : 0) :
pointer.markerWidth / 2) : 0;
// eslint-disable-next-line prefer-const
pointerRadius = pointer.position === 'Inside' ?
(axis.currentRadius - axis.lineStyle.width / 2 - markerOffset - pointer.currentDistanceFromScale) :
pointer.position === 'Outside' ?
(axis.currentRadius + rangeBarOffset + axis.lineStyle.width / 2 + markerOffset + pointer.currentDistanceFromScale) :
(axis.currentRadius + rangeBarOffset / 2 - pointer.currentDistanceFromScale -
((pointer.markerShape === 'InvertedTriangle' || pointer.markerShape === 'Triangle') ? markerOffset : 0));
return pointerRadius;
}
}
/**
* Method to render the needle pointer of the ciruclar gauge.
*
* @param {Axis} axis - Specifies the axis
* @param {number} axisIndex - Specifies the axis index.
* @param {number} index - Specifies the index.
* @param {Element} parentElement - Specifies the parent element.
* @param {CircularGauge} gauge - Specifies the instance of the gauge.
* @returns {void}
*/
private drawNeedlePointer(axis: Axis, axisIndex: number, index: number, parentElement: Element, gauge: CircularGauge): void {
const pointer: Pointer = <Pointer>axis.pointers[index as number];
const needle: NeedleTail = <NeedleTail>pointer.needleTail;
const cap: Cap = <Cap>pointer.cap;
let pointerRadius: number;
let location: GaugeLocation;
let direction: string;
const needleStartWidth: number = pointer.needleStartWidth;
const needleEndWidth: number = pointer.needleEndWidth;
const mid: GaugeLocation = gauge.midPoint;
const width: number = pointer.pointerWidth / 2;
let rectDirection: string;
let gradientColor: string;
let gradientTailColor: string;
let gradientCapColor: string;
// To render the needle
location = getLocationFromAngle(0, pointer.currentRadius, mid);
if ((needleStartWidth === 0) && (needleEndWidth === 0) && width) {
direction = 'M ' + mid.x + ' ' + (mid.y) + ' L ' + (location.x) + ' ' + mid.y +
' L ' + (mid.x) + ' ' + (mid.y) + ' Z';
} else {
direction = 'M ' + mid.x + ' ' + (mid.y - width - needleEndWidth) + ' L ' + (location.x) + ' ' + (mid.y - needleStartWidth / 2) +
' L ' + location.x + ' ' + (mid.y + needleStartWidth / 2) + ' L ' + mid.x + ' ' + (mid.y + width + needleEndWidth) + ' Z';
}
if (gauge.gradientModule) {
gradientColor = gauge.gradientModule.getGradientColorString(pointer);
}
pointer.pathElement.push(appendPath(
new PathOption(
gauge.element.id + '_Axis_' + axisIndex + '_Pointer_Needle_' + index, gradientColor ? gradientColor :
pointer.color || this.gauge.themeStyle.needleColor,
pointer.border.width, pointer.border.color, null, pointer.border.dashArray, direction
),
parentElement, gauge)
);
// eslint-disable-next-line prefer-const
pointerRadius = stringToNumber(
pointer.needleTail.length, pointer.currentRadius
);
// To render the rect element for touch
rectDirection = 'M ' + mid.x + ' ' + (mid.y - width) + ' L ' + (location.x) + ' ' + (mid.y - width) +
' L ' + location.x + ' ' + (mid.y + width) + ' L ' + mid.x + ' ' + (mid.y + width);
// To render the needle tail
if (gauge.gradientModule) {
gradientTailColor = gauge.gradientModule.getGradientColorString(needle);
}
if (pointerRadius) {
location = getLocationFromAngle(180, pointerRadius, gauge.midPoint);
direction = 'M ' + mid.x + ' ' + (mid.y - width) +
' L ' + (location.x) + ' ' + (mid.y - width) +
' L ' + (location.x) + ' ' + (mid.y + width) +
' L ' + (mid.x) + ' ' + (mid.y + width) + ' Z';
pointer.pathElement.push(appendPath(
new PathOption(
gauge.element.id + '_Axis_' + axisIndex + '_Pointer_NeedleTail_' + index,
gradientTailColor ? gradientTailColor : pointer.needleTail.color || this.gauge.themeStyle.needleTailColor,
pointer.needleTail.border.width, pointer.needleTail.border.color, null, pointer.needleTail.border.dashArray, direction
),
parentElement, gauge)
);
rectDirection += ' L ' + location.x + ' ' + (mid.y + width) + ' L ' + location.x + ' ' + (mid.y - width);
}
// To render the cap
if (gauge.gradientModule) {
gradientCapColor = gauge.gradientModule.getGradientColorString(cap);
}
if (pointer.cap.radius) {
pointer.pathElement.push(appendPath(
calculateShapes(
mid, 'Circle', new Size(pointer.cap.radius * 2, pointer.cap.radius * 2),
'', new PathOption(
gauge.element.id + '_Axis_' + axisIndex + '_Pointer_NeedleCap_' + index,
gradientCapColor ? gradientCapColor : pointer.cap.color || this.gauge.themeStyle.capColor, pointer.cap.border.width,
pointer.cap.border.color, null, pointer.cap.border.dashArray, '', ''
)
),
parentElement, gauge, 'Ellipse')
);
}
pointer.pathElement.push(appendPath(
new PathOption(
gauge.element.id + '_Axis_' + axisIndex + '_Pointer_NeedleRect_' + index, 'transparent',
0, 'transpanret', null, '0', rectDirection + ' Z'
),
parentElement, gauge)
);
}
/**
* Method to set the pointer value of the circular gauge.
*
* @param {Axis} axis - Specifies the axis.
* @param {Pointer} pointer - Specifies the pointer.
* @param {number} value - Specifies the value.
* @returns {void}
* @private
*/
public setPointerValue(axis: Axis, pointer: Pointer, value: number): void {
const checkMinValue: boolean = value === axis.visibleRange.min && pointer.type === 'RangeBar';
const location: GaugeLocation = this.gauge.midPoint;
const isClockWise: boolean = axis.direction === 'ClockWise';
let radius: number = pointer.roundedCornerRadius;
let minRadius: number = (radius * 0.25);
if (radius > 0 && radius <= 5) {
radius = 6;
minRadius = (radius * 0.25);
}
let startAngle: number = getAngleFromValue(
axis.visibleRange.min, axis.visibleRange.max, axis.visibleRange.min,
axis.startAngle, axis.endAngle, isClockWise
);
let endAngle: number = getAngleFromValue(
value, axis.visibleRange.max, axis.visibleRange.min,
axis.startAngle, axis.endAngle, isClockWise
);
if (isClockWise) {
if (startAngle > endAngle) {
endAngle = Math.round(startAngle) === Math.round(endAngle) && !checkMinValue ?
Math.round(endAngle) - (pointer.roundedCornerRadius > 0 ? 1.5 : 0.5) : Math.round(endAngle);
}
else {
endAngle = startAngle === endAngle && !checkMinValue ? endAngle + 1 : endAngle;
}
} else {
endAngle = Math.round(startAngle) === Math.round(endAngle) && !checkMinValue ?
[startAngle, startAngle = (endAngle > startAngle ? endAngle + (pointer.roundedCornerRadius > 0 ? 1.5 : 0.5) : endAngle - 1)][0]
: [startAngle, startAngle = endAngle][0];
}
if (value <= (axis.visibleRange.min + axis.visibleRange.interval) && pointer.roundedCornerRadius) {
radius = value === axis.visibleRange.min || (axis.visibleRange.min + 1) ? 8 : radius;
radius /= 2;
minRadius = radius * 0.25;
}
const oldStartValue: number = ((((pointer.currentRadius - (pointer.pointerWidth / 2)) * ((startAngle * Math.PI) / 180) -
(radius / minRadius)) / (pointer.currentRadius - (pointer.pointerWidth / 2))) * 180) / Math.PI;
const oldEndValue: number = ((((pointer.currentRadius - (pointer.pointerWidth / 2)) * ((endAngle * Math.PI) / 180) +
(radius / minRadius)) / (pointer.currentRadius - (pointer.pointerWidth / 2))) * 180) / Math.PI;
const angleValue: number = value === axis.maximum && (axis.startAngle === axis.endAngle ||
Math.abs(axis.startAngle - axis.endAngle) === 360) && pointer.type === 'RangeBar' ? 45 : 180;
let roundStartAngle: number = ((((pointer.currentRadius) * ((startAngle * Math.PI) / angleValue) +
radius) / (pointer.currentRadius)) * angleValue) / Math.PI;
let roundEndAngle: number = ((((pointer.currentRadius) * ((endAngle * Math.PI) / angleValue) -
radius) / (pointer.currentRadius)) * angleValue) / Math.PI;
if (roundStartAngle > roundEndAngle && (roundStartAngle - roundEndAngle) <= 36 && pointer.type === 'RangeBar') {
roundStartAngle = startAngle;
roundEndAngle = endAngle;
}
if (isNullOrUndefined(pointer.currentRadius)) {
this.calculatePointerRadius(axis, pointer);
}
pointer.pathElement.map((element: Element) => {
if (pointer.type === 'RangeBar') {
if (radius && !checkMinValue) {
element.setAttribute('d', getRoundedPathArc(
location, Math.floor(roundStartAngle), Math.ceil(roundEndAngle), oldStartValue, oldEndValue,
pointer.currentRadius, pointer.pointerWidth, pointer.pointerWidth
));
radius = 0;
} else {
element.setAttribute('d', getCompleteArc(
location, startAngle, endAngle, pointer.currentRadius, (pointer.currentRadius - pointer.pointerWidth),
checkMinValue
));
}
} else {
if (pointer.type === 'Marker' && pointer.markerShape === 'Text') {
this.calculateTextElement(axis, pointer, value, element);
} else {
element.setAttribute(
'transform', 'rotate(' + getAngleFromValue(
value, axis.visibleRange.max, axis.visibleRange.min,
axis.startAngle, axis.endAngle, isClockWise
) + ',' + location.x + ',' + location.y + ')'
);
}
}
});
}
/**
* Method to set the text value of the circular gauge.
*
* @param {Axis} axis - Specifies the axis.
* @param {Pointer} pointer - Specifies the pointer.
* @param {number} value - Specifies the value.
* @param {Element} element - Specifies the text element.
* @returns {void}
* @private
*/
public calculateTextElement(axis: Axis, pointer: Pointer, value: number, element: Element): void {
const textangle: number = getAngleFromValue(value, axis.visibleRange.max, axis.visibleRange.min, axis.startAngle, axis.endAngle, axis.direction === 'ClockWise');
const textlocation: GaugeLocation = getLocationFromAngle( textangle, pointer.currentRadius, this.gauge.midPoint);
element.setAttribute(
'transform', 'rotate(' + (textangle + 90) + ',' + textlocation.x + ',' + textlocation.y + ')'
);
element.setAttribute('x', String(textlocation.x));
element.setAttribute('y', String(textlocation.y));
}
/**
* Method to render the marker pointer of the ciruclar gauge.
*
* @param {Axis} axis - Specifies the axis
* @param {number} axisIndex - Specifies the axis index.
* @param {number} index - Specifies the index.
* @param {Element} parentElement - Specifies the parent element.
* @param {CircularGauge} gauge - Specifies the instance of the gauge.
* @returns {void}
*/
private drawMarkerPointer(axis: Axis, axisIndex: number, index: number, parentElement: Element, gauge: CircularGauge): void {
const pointer: Pointer = <Pointer>axis.pointers[index as number];
const min: number = axis.visibleRange.min;
const max: number = axis.visibleRange.max;
let gradientMarkerColor: string;
const angle: number = Math.round(getAngleFromValue(pointer.value, max, min, axis.startAngle, axis.endAngle, axis.direction === 'ClockWise'));
let shapeBasedOnPosition: GaugeShape = pointer.markerShape;
if (gauge.gradientModule) {
gradientMarkerColor = gauge.gradientModule.getGradientColorString(pointer);
}
if (isNullOrUndefined(pointer.radius) && !isNullOrUndefined(pointer.position) && (pointer.markerShape === 'InvertedTriangle' ||
pointer.markerShape === 'Triangle')) {
shapeBasedOnPosition = ((pointer.position === 'Outside' || pointer.position === 'Cross') && pointer.markerShape === 'Triangle' ?
'InvertedTriangle' as GaugeShape : (pointer.position === 'Inside' &&
pointer.markerShape === 'InvertedTriangle' ? 'Triangle' as GaugeShape : pointer.markerShape));
}
const location: GaugeLocation = getLocationFromAngle(
(pointer.markerShape === 'Text') ? angle : 0, pointer.currentRadius,
gauge.midPoint
);
if (pointer.markerShape === 'Text') {
const style: FontModel = {
size: pointer.textStyle.size,
color: pointer.textStyle.color || this.gauge.themeStyle.pointerColor,
fontFamily: pointer.textStyle.fontFamily,
fontStyle: pointer.textStyle.fontStyle,
fontWeight: pointer.textStyle.fontWeight || this.gauge.themeStyle.fontWeight,
opacity: pointer.textStyle.opacity
};
const textOption: TextOption =
new TextOption(
gauge.element.id + '_Axis_' + axisIndex + '_Pointer_Marker_' + index, location.x, location.y, 'middle',
pointer.text, 'rotate(' + (angle + 90) + ',' +
(location.x) + ',' + location.y + ')',
'auto');
const textObject: Element = textElement(textOption, style, style.color, parentElement, 'pointer-events : auto; ');
(textObject as HTMLElement).style.visibility = ((pointer.animation.enable || animationMode === 'Enable') && (!this.gauge.isPropertyChange || pointer.isPointerAnimation) && this.gauge.animatePointer) ? 'hidden' : 'visible';
pointer.pathElement.push(textObject);
} else {
pointer.pathElement.push(appendPath(
calculateShapes(
location, shapeBasedOnPosition, new Size(pointer.markerWidth, pointer.markerHeight),
pointer.imageUrl, new PathOption
(
gauge.element.id + '_Axis_' + axisIndex + '_Pointer_Marker_' + index,
gradientMarkerColor ? gradientMarkerColor : pointer.color || this.gauge.themeStyle.pointerColor,
pointer.border.width, pointer.border.color, null, pointer.border.dashArray, '', ''
)
),
parentElement, gauge,
pointer.markerShape === 'Circle' ? 'Ellipse' : (pointer.markerShape === 'Image' ? 'Image' : 'Path')
)
);
}
}
/**
* Method to render the range bar pointer of the ciruclar gauge.
*
* @param {Axis} axis - Specifies the axis
* @param {number} axisIndex - Specifies the axis index.
* @param {number} index - Specifies the index.
* @param {Element} parentElement - Specifies the parent element.
* @param {CircularGauge} gauge - Specifies the instance of the gauge.
* @returns {void}
*/
private drawRangeBarPointer(axis: Axis, axisIndex: number, index: number, parentElement: Element, gauge: CircularGauge): void {
const pointer: Pointer = <Pointer>axis.pointers[index as number];
let gradientBarColor: string;
if (gauge.gradientModule) {
gradientBarColor = gauge.gradientModule.getGradientColorString(pointer);
}
pointer.pathElement.push(appendPath(
new PathOption(
gauge.element.id + '_Axis_' + axisIndex + '_Pointer_RangeBar_' + index, gradientBarColor ? gradientBarColor :
pointer.color || this.gauge.themeStyle.pointerColor,
pointer.border.width, pointer.border.color,
1, pointer.border.dashArray, ''
),
parentElement, gauge
));
}
/**
* Method to perform the animation of the pointer in circular gauge.
*
* @param {Element} pointerElement - specifies the pointer element.
* @param {Pointer} pointer - Specifies the pointer.
* @param {Axis} axis - Specifies the axis.
* @param {number} axisIndex - Specifies the axis index.
* @returns {void}
* @private
*/
public doPointerAnimation(pointerElement: Element, pointer: Pointer, axis: Axis, axisIndex: number): void {
const startValue: number = !isNullOrUndefined(pointer.previousValue) ? pointer.previousValue : axis.visibleRange.min;
const endValue: number = pointer.currentValue;
if (((pointer.animation.enable || animationMode === 'Enable') && startValue !== endValue && this.gauge.animatePointer) ||
(!isNullOrUndefined(this.gauge.loadingAnimationDuration) && this.gauge.loadingAnimationDuration[axisIndex as number] > 0)) {
pointer.pathElement.map((element: Element) => {
if (pointer.type === 'RangeBar') {
this.performRangeBarAnimation(element as HTMLElement, startValue, endValue, axis, pointer, axisIndex);
} else {
if (pointer.type === 'Marker' && pointer.markerShape === 'Text') {
this.performTextAnimation(pointerElement as HTMLElement, startValue, endValue, axis, pointer, axisIndex);
}
else {
this.performNeedleAnimation(
element as HTMLElement, startValue, endValue, axis, pointer, axisIndex);
}
}
});
}
}
/**
* @param {HTMLElement} element - specifies the element.
* @param {number} start - specifies the start.
* @param {number} end - specifies the end.
* @param {Axis} axis - specifies the axis.
* @param {Pointer} pointer - specfies the pointer.
* @param {number} axisIndex - Specifies the axis index.
* @returns {void}
* @private
*/
public performTextAnimation(element: HTMLElement, start: number, end: number, axis: Axis, pointer: Pointer, axisIndex: number): void {
const isClockWise: boolean = axis.direction === 'ClockWise';
let textangle: number;
let textlocation: GaugeLocation;
let pointerValue: number = 0;
let timeStamp: number;
start = typeof(start) === 'string' ? parseInt(start, 10) : start;
end = typeof(end) === 'string' ? parseInt(end, 10) : end;
element = !isNullOrUndefined(element.children[0]) ? element.children[0] as HTMLElement : element;
const val: number = Math.abs(start - end);
new Animation({}).animate(element, {
duration: this.gauge.isAnimationProgress ? (isNullOrUndefined(pointer.value) || pointer.value === axis.minimum ? 0 :
(animationMode === 'Enable' && (((!pointer.animation.enable || pointer.animation.duration === 0)
&& !this.gauge.allowLoadingAnimation) || (this.gauge.allowLoadingAnimation && (this.gauge.animationDuration === 0
&& pointer.animation.enable && pointer.animation.duration === 0)))) ? 1000 :
(this.gauge.allowLoadingAnimation ? (pointer.animation.enable && pointer.animation.duration > 0 ? pointer.animation.duration
: this.gauge.loadingAnimationDuration[axisIndex as number]) : pointer.animation.duration)) : 0,
progress: (args: AnimationOptions): void => {
if (this.gauge.isAnimationProgress) {
if (args.timeStamp > args.delay) {
timeStamp = (args.timeStamp / pointer.animation.duration);
pointerValue = end > start ? start + (timeStamp * val) : start - (timeStamp * val);
textangle = getAngleFromValue(pointerValue, axis.visibleRange.max, axis.visibleRange.min, axis.startAngle, axis.endAngle, isClockWise);
textlocation = getLocationFromAngle(textangle, pointer.currentRadius, this.gauge.midPoint);
element.setAttribute(
'transform', 'rotate(' + (textangle + 90) + ',' + textlocation.x + ',' + textlocation.y + ')'
);
element.setAttribute('x', String(textlocation.x));
element.setAttribute('y', String(textlocation.y));
element.style.visibility = 'visible';
}
}
},
end: () => {
if (this.gauge.isAnimationProgress) {
this.setPointerValue(axis, pointer, end);
pointer.isPointerAnimation = false;
}
this.gauge.trigger(animationComplete, { axis: axis, pointer: pointer });
if (!isNullOrUndefined(this.gauge.loadingAnimationDuration) && (this.gauge.loadingAnimationDuration[axisIndex as number] > 0 && !isNullOrUndefined(this.gauge.annotationsModule))) {
this.gauge.annotationsModule.annotationAnimation(this.gauge);
} else {
this.gauge.isOverAllAnimationComplete = true;
}
}
});
}
/**
* Perform the needle and marker pointer animation for circular gauge.
*
* @param {HTMLElement} element - Specifies the element
* @param {number} start - Specifies the start
* @param {number} end - Specifies the end
* @param {Axis} axis - Specifies the axis
* @param {Pointer} pointer - Specifies the pointer.
* @param {number} axisIndex - Specifies the axis index.
* @returns {void}
* @private
*/
public performNeedleAnimation(
element: HTMLElement, start: number, end: number, axis: Axis, pointer: Pointer, axisIndex: number): void {
const isClockWise: boolean = axis.direction === 'ClockWise';
start = typeof(start) === 'string' ? parseInt(start, 10) : start;
end = typeof(end) === 'string' ? parseInt(end, 10) : end;
const startAngle: number = getAngleFromValue(
start, axis.visibleRange.max, axis.visibleRange.min,
axis.startAngle, axis.endAngle, isClockWise
);
const pointAngle: number = getAngleFromValue(
end, axis.visibleRange.max, axis.visibleRange.min,
axis.startAngle, axis.endAngle, isClockWise
);
const endAngle: number = startAngle > pointAngle ? (pointAngle + 360) : pointAngle;
let sweepAngle: number;
new Animation({}).animate(element, {
duration: this.gauge.isAnimationProgress ? (isNullOrUndefined(pointer.value) || pointer.value === axis.minimum ? 0 :
(animationMode === 'Enable' && (((!pointer.animation.enable || pointer.animation.duration === 0)
&& !this.gauge.allowLoadingAnimation) || (this.gauge.allowLoadingAnimation && (this.gauge.animationDuration === 0
&& pointer.animation.enable && pointer.animation.duration === 0)))) ? 1000 :
(this.gauge.allowLoadingAnimation ? (pointer.animation.enable && pointer.animation.duration > 0 ? pointer.animation.duration
: this.gauge.loadingAnimationDuration[axisIndex as number]) : pointer.animation.duration)) : 0,
progress: (args: AnimationOptions): void => {
if (this.gauge.isAnimationProgress) {
sweepAngle = (start < end || Math.round(startAngle) === Math.round(endAngle)) ?
isClockWise ? (endAngle - startAngle) : (endAngle - startAngle - 360) :
isClockWise ? (endAngle - startAngle - 360) : (endAngle - startAngle);
element.style.animation = 'None';
if (start !== end) {
element.setAttribute(
'transform', 'rotate(' + linear(args.timeStamp, startAngle, sweepAngle, args.duration) + ',' +
this.gauge.midPoint.x.toString() + ',' + this.gauge.midPoint.y.toString() + ')'
);
element.style.visibility = 'visible';
}
}
},
end: () => {
if (this.gauge.isAnimationProgress) {
this.setPointerValue(axis, pointer, end);
if (this.gauge.animationDuration > 0) {
element.style.visibility = 'visible';
}
pointer.isPointerAnimation = false;
}
if (pointer.type === 'Marker' || (element.id.indexOf('_Pointer_NeedleCap') >= 0)) {
this.gauge.trigger(animationComplete, { axis: axis, pointer: pointer });
}
if (!isNullOrUndefined(this.gauge.loadingAnimationDuration) && this.gauge.loadingAnimationDuration[axisIndex as number] > 0 && !isNullOrUndefined(this.gauge.annotationsModule)) {
this.gauge.annotationsModule.annotationAnimation(this.gauge);
} else {
this.gauge.isOverAllAnimationComplete = true;
}
}
});
}
/**
* Perform the range bar pointer animation for circular gauge.
*
* @param {HTMLElement} element - Specifies the element.
* @param {number} start - Specifies the start.
* @param {number} end - Specifies the end.
* @param {Axis} axis - Specifies the axis.
* @param {Pointer} pointer - Specifies the pointer.
* @param {number} axisIndex - Specifies the axis index.
* @returns {void}
* @private
*/
public performRangeBarAnimation(element: HTMLElement, start: number, end: number, axis: Axis, pointer: Pointer, axisIndex: number): void {
start = typeof(start) === 'string' ? parseInt(start, 10) : start;
end = typeof(end) === 'string' ? parseInt(end, 10) : end;
let pointerValue: number;
let timeStamp: number;
element.style.visibility = 'visible';
const val: number = Math.abs(start - end);
new Animation({}).animate(element, {
duration: this.gauge.isAnimationProgress ? (isNullOrUndefined(pointer.value) || pointer.value === axis.minimum ? 0 :
(animationMode === 'Enable' && (((!pointer.animation.enable || pointer.animation.duration === 0)
&& !this.gauge.allowLoadingAnimation) || (this.gauge.allowLoadingAnimation && (this.gauge.animationDuration === 0
&& pointer.animation.enable && pointer.animation.duration === 0)))) ? 1000 :
(this.gauge.allowLoadingAnimation ? (pointer.animation.enable && pointer.animation.duration > 0 ? pointer.animation.duration
: this.gauge.loadingAnimationDuration[axisIndex as number]) : pointer.animation.duration)) : 0,
progress: (arg: AnimationOptions): void => {
if (this.gauge.isAnimationProgress) {
arg.duration = !this.gauge.isAnimationProgress ? 0 : arg.duration;
timeStamp = (arg.timeStamp / arg.duration);
pointerValue = end > start ? start + (timeStamp * val) : start - (timeStamp * val);
this.setPointerValue(axis, pointer, pointerValue);
}
},
end: () => {
if (this.gauge.isAnimationProgress) {
this.setPointerValue(axis, pointer, end);
pointer.isPointerAnimation = false;
}
this.gauge.trigger(animationComplete, { axis: axis, pointer: pointer });
if (!isNullOrUndefined(this.gauge.loadingAnimationDuration) && this.gauge.loadingAnimationDuration[axisIndex as number] > 0 && !isNullOrUndefined(this.gauge.annotationsModule)) {
this.gauge.annotationsModule.annotationAnimation(this.gauge);
} else {
this.gauge.isOverAllAnimationComplete = true;
}
}
});
}
/**
*
* @returns {void}
* @private
*/
public destroy(): void {
this.gauge = null;
}
}