UNPKG

@syncfusion/ej2-circulargauge

Version:
653 lines (627 loc) 35.2 kB
/* 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; } }