UNPKG

@syncfusion/ej2-lineargauge

Version:
272 lines (265 loc) 17 kB
import { Animation, AnimationOptions, isNullOrUndefined, animationMode } from '@syncfusion/ej2-base'; import { LinearGauge } from '../../linear-gauge'; import { Axis, Pointer } from './axis'; import { animationComplete } from '../model/constant'; import { Size, valueToCoefficient, PathOption, TextOption, Rect } from '../utils/helper'; import { calculateShapes, calculateTextPosition, getBox, VisibleRange } from '../utils/helper'; /** * To handle the animation for gauge * * @private */ export class Animations { public gauge: LinearGauge; constructor(gauge: LinearGauge) { this.gauge = gauge; } /** * To do the marker pointer animation. * * @param element - Specifies the element of the marker pointer to which animation must be propagated. * @param axis - Specifies the axis in which the marker pointer is available to which animation must be propagated. * @param pointer - Specifies the pointer to which the animation must be propagated. */ public performMarkerAnimation(element: Element, axis: Axis, pointer: Pointer): void { const markerElement: HTMLElement = <HTMLElement>element; let options: PathOption; let textOptions: TextOption; let timeStamp: number; const range: VisibleRange = axis.visibleRange; const rectHeight: number = (this.gauge.orientation === 'Vertical') ? axis.lineBounds.height : axis.lineBounds.width; const rectY: number = (this.gauge.orientation === 'Vertical') ? axis.lineBounds.y : axis.lineBounds.x; if (this.gauge.orientation === 'Vertical') { pointer.bounds.y = (valueToCoefficient(pointer.currentValue, axis, this.gauge.orientation, range) * rectHeight) + rectY; } else { pointer.bounds.x = (valueToCoefficient(pointer.currentValue, axis, this.gauge.orientation, range) * rectHeight) + rectY; } options = new PathOption(markerElement.id, null, null, null); options = calculateShapes( pointer.bounds, pointer.markerType, new Size(pointer.width, pointer.height), pointer.imageUrl, options, this.gauge.orientation, axis, pointer); if (pointer.markerType === 'Text') { textOptions = new TextOption(markerElement.id, 0, 0, 'middle', pointer.text, null, 'auto'); textOptions = calculateTextPosition(pointer.bounds, pointer.markerType, textOptions, this.gauge.orientation, axis, pointer); } let currentValue: number; let start: number = typeof(pointer.startValue) === 'string' ? parseInt(pointer.startValue, 10) : pointer.startValue; const end: number = pointer.currentValue; start = (start === end) ? range.min : start; const val: number = Math.abs(start - end); const currentPath: string = options.d; const cx: number = options['cx']; const cy: number = options['cy']; const x: number = pointer.markerType === 'Text' ? textOptions['x'] : options['x']; const y: number = pointer.markerType === 'Text' ? textOptions['y'] : options['y']; new Animation({}).animate(markerElement, { // eslint-disable-next-line @typescript-eslint/no-explicit-any name: 'Linear' as any, duration: (animationMode === 'Enable' && ((pointer.animationDuration === 0 && !this.gauge.allowLoadingAnimation) || this.gauge.animationDuration === 0)) ? 1000 : (this.gauge.allowLoadingAnimation && pointer.animationDuration === 0 ? (this.gauge.animationDuration / this.gauge.splitUpCount) : pointer.animationDuration), progress: (args: AnimationOptions): void => { if (args.timeStamp >= args.delay) { timeStamp = ((args.timeStamp - args.delay) / args.duration); currentValue = (start < end) ? start + (timeStamp * val) : start - (timeStamp * val); if (this.gauge.orientation === 'Vertical') { pointer.bounds.y = (valueToCoefficient(currentValue, axis, this.gauge.orientation, range) * rectHeight) + rectY; options = calculateShapes( pointer.bounds, pointer.markerType, new Size(pointer.width, pointer.height), pointer.imageUrl, options, this.gauge.orientation, axis, pointer); if (pointer.markerType === 'Text') { textOptions = calculateTextPosition(pointer.bounds, pointer.markerType, textOptions, this.gauge.orientation, axis, pointer); } if (!isNullOrUndefined(options['r'])) { markerElement.setAttribute('cy', options['cy'].toString()); } else if (!isNullOrUndefined(pointer.markerType === 'Text' ? textOptions['y'] : options['y'])) { markerElement.setAttribute('y', pointer.markerType === 'Text' ? textOptions['y'] : options['y'].toString()); } else { markerElement.setAttribute('d', options.d); } markerElement.style.visibility = 'visible'; } else { pointer.bounds.x = (valueToCoefficient(currentValue, axis, this.gauge.orientation, range) * rectHeight) + rectY; options = calculateShapes( pointer.bounds, pointer.markerType, new Size(pointer.width, pointer.height), pointer.imageUrl, options, this.gauge.orientation, axis, pointer); if (pointer.markerType === 'Text') { textOptions = calculateTextPosition(pointer.bounds, pointer.markerType, textOptions, this.gauge.orientation, axis, pointer); } if (!isNullOrUndefined(options['r'])) { markerElement.setAttribute('cx', options['cx'].toString()); } else if (!isNullOrUndefined(pointer.markerType === 'Text' ? textOptions['x'] : options['x'])) { markerElement.setAttribute('x', pointer.markerType === 'Text' ? textOptions['x'] : options['x'].toString()); } else { markerElement.setAttribute('d', options.d); } markerElement.style.visibility = 'visible'; } } }, end: () => { if (!isNullOrUndefined(cy)) { markerElement.setAttribute('cy', cy.toString()); markerElement.setAttribute('cx', cx.toString()); } else if (!isNullOrUndefined(y)) { markerElement.setAttribute('y', y.toString()); markerElement.setAttribute('x', x.toString()); } else { markerElement.setAttribute('d', currentPath); } markerElement.style.visibility = 'visible'; pointer.isPointerAnimation = false; pointer.animationComplete = true; pointer.startValue = pointer.value = pointer.currentValue; this.gauge.trigger(animationComplete, { axis: axis, pointer: pointer }); if (this.gauge.allowLoadingAnimation) { if (!isNullOrUndefined(this.gauge.annotationsModule) && (this.gauge.annotations.length > 0 && (this.gauge.annotations[0].content !== '' || this.gauge.annotations.length > 1))) { const element: Element = document.getElementById(this.gauge.element.id + '_AnnotationsGroup'); this.gauge.annotationsModule.annotationAnimate(element, this.gauge); } else { this.gauge.allowLoadingAnimation = false; this.gauge.isOverAllAnimationComplete = true; } } } }); } /** * Perform the bar pointer animation * * @param element * @param axis * @param pointer */ public performBarAnimation(element: Element, axis: Axis, pointer: Pointer): void { const radix: number = 10; let timeStamp: number; let value2: number; let value1: number; let currentValue: number; let clipHeight: string; let clipY: string; let clipX: string; let clipVal: number; let clipWidth: string; let currentHeight: number; let clipElement: HTMLElement; const range: VisibleRange = axis.visibleRange; const pointerElement: HTMLElement = <HTMLElement>element; const lineHeight: number = (this.gauge.orientation === 'Vertical') ? axis.lineBounds.height : axis.lineBounds.width; const lineY: number = (this.gauge.orientation === 'Vertical') ? axis.lineBounds.y : axis.lineBounds.x; let start: number = typeof(pointer.startValue) === 'string' ? parseInt(pointer.startValue, 10) : pointer.startValue; const end: number = pointer.currentValue; start = (start === end) ? range.min : start; let path: string = ''; let currentPath: string = ''; const tagName: string = pointerElement.tagName; const val: number = Math.abs(start - end); const pointerValue: number = (valueToCoefficient(end, axis, this.gauge.orientation, range) * lineHeight) + lineY; const startPointerVal: number = (valueToCoefficient(range.min, axis, this.gauge.orientation, range) * lineHeight) + lineY; const rectY: number = (this.gauge.orientation === 'Vertical') ? !axis.isInversed ? pointerValue : startPointerVal : axis.isInversed ? pointerValue : startPointerVal; const rectHeight: number = Math.abs(startPointerVal - pointerValue); if (this.gauge.container.type === 'Thermometer' && start === 0 && this.gauge.container.width > 0) { if (end === axis.minimum) { (element as HTMLElement).style.visibility = 'visible'; } else { clipElement = <HTMLElement>pointerElement.parentElement.childNodes[1].childNodes[0].childNodes[0]; if (this.gauge.orientation === 'Vertical') { clipY = clipElement.getAttribute('y'); clipHeight = clipElement.getAttribute('height'); clipVal = parseInt(clipY, radix) + parseInt(clipHeight, radix); clipElement.setAttribute('y', clipVal.toString()); } else { clipX = clipElement.getAttribute('x'); clipWidth = clipElement.getAttribute('width'); clipVal = parseInt(clipX, radix) + parseInt(clipWidth, radix); clipElement.setAttribute('width', '0'); } } } path = pointer.value === axis.minimum && this.gauge.container.type === 'RoundedRectangle' ? '' : getBox( pointer.bounds, this.gauge.container.type, this.gauge.orientation, new Size(pointer.bounds.width, pointer.bounds.height), 'bar', this.gauge.container.width, axis, pointer.roundedCornerRadius); let animatedPointerWidth: number = pointer.bounds.width; let animatedPointerHeight: number = pointer.bounds.height; new Animation({}).animate(pointerElement, { // eslint-disable-next-line @typescript-eslint/no-explicit-any name: 'Linear' as any, duration: (animationMode === 'Enable' && ((pointer.animationDuration === 0 && !this.gauge.allowLoadingAnimation) || this.gauge.animationDuration === 0)) ? 1000 : (this.gauge.allowLoadingAnimation && pointer.animationDuration === 0 ? (this.gauge.animationDuration / this.gauge.splitUpCount) : pointer.animationDuration), progress: (animate: AnimationOptions): void => { if (animate.timeStamp >= animate.delay) { timeStamp = ((animate.timeStamp - animate.delay) / animate.duration); currentValue = (start < end) ? start + (timeStamp * val) : start - (timeStamp * val); value2 = (valueToCoefficient(currentValue, axis, this.gauge.orientation, range) * lineHeight) + lineY; value1 = (valueToCoefficient(range.min, axis, this.gauge.orientation, range) * lineHeight) + lineY; currentHeight = Math.abs(value2 - value1); if (this.gauge.orientation === 'Vertical') { pointer.bounds.y = (!axis.isInversed) ? value2 : value1; animatedPointerHeight = currentHeight; } else { pointer.bounds.x = (axis.isInversed) ? value2 : value1; animatedPointerWidth = currentHeight; } if (tagName === 'path') { if (start === 0 && this.gauge.container.type === 'Thermometer') { // eslint-disable-next-line @typescript-eslint/no-unused-expressions (this.gauge.orientation === 'Vertical') ? clipElement.setAttribute('y', (clipVal - (timeStamp * parseInt(clipHeight, radix))).toString()) : clipElement.setAttribute('width', (timeStamp * parseInt(clipWidth, radix)).toString()); } currentPath = pointer.value === axis.minimum && this.gauge.container.type === 'RoundedRectangle' ? '' : getBox( new Rect(pointer.bounds.x, pointer.bounds.y, animatedPointerWidth, animatedPointerHeight), this.gauge.container.type, this.gauge.orientation, new Size(animatedPointerWidth, animatedPointerHeight), 'bar', this.gauge.container.width, axis, pointer.roundedCornerRadius); pointerElement.setAttribute('d', currentPath); pointerElement.style.visibility = 'visible'; } else { if (this.gauge.orientation === 'Vertical') { pointerElement.setAttribute('y', pointer.bounds.y.toString()); pointerElement.setAttribute('height', animatedPointerHeight.toString()); } else { pointerElement.setAttribute('x', pointer.bounds.x.toString()); pointerElement.setAttribute('width', animatedPointerWidth.toString()); } pointerElement.style.visibility = 'visible'; } } }, end: () => { if (tagName === 'path') { if (start === 0 && this.gauge.container.type === 'Thermometer') { pointerElement.parentElement.children[1].remove(); } else { pointerElement.setAttribute('d', path); } } else { if (this.gauge.orientation === 'Vertical') { pointerElement.setAttribute('y', rectY.toString()); pointerElement.setAttribute('height', rectHeight.toString()); } else { pointerElement.setAttribute('x', rectY.toString()); pointerElement.setAttribute('width', rectHeight.toString()); } } pointerElement.style.visibility = 'visible'; pointer.isPointerAnimation = false; pointer.startValue = pointer.value = pointer.currentValue; this.gauge.trigger(animationComplete, { axis: axis, pointer: pointer }); if (this.gauge.allowLoadingAnimation) { if (!isNullOrUndefined(this.gauge.annotationsModule) && (this.gauge.annotations.length > 0 && (this.gauge.annotations[0].content !== '' || this.gauge.annotations.length > 1))) { const element: Element = document.getElementById(this.gauge.element.id + '_AnnotationsGroup'); this.gauge.annotationsModule.annotationAnimate(element, this.gauge); } else { this.gauge.allowLoadingAnimation = false; this.gauge.isOverAllAnimationComplete = true; } } } }); } }