UNPKG

@syncfusion/ej2-circulargauge

Version:
1,063 lines (1,059 loc) 379 kB
import { createElement, isNullOrUndefined, compile, remove, merge, setStyleAttribute, ChildProperty, Property, Complex, Collection, Animation as Animation$1, SanitizeHtmlHelper, Browser, animationMode, print, Component, EventHandler, Internationalization, Event, NotifyPropertyChanges } from '@syncfusion/ej2-base'; import { SvgRenderer, Tooltip } from '@syncfusion/ej2-svg-base'; import { PdfPageOrientation, PdfDocument, PdfBitmap } from '@syncfusion/ej2-pdf-export'; /* eslint-disable max-len */ /** * Function to measure the height and width of the text. * * @param {string} text - Specifies the text. * @param {FontModel} font - Specifies the font. * @returns {Size} - Returns the size of the text. * @private */ function measureText(text, font) { let htmlObject = document.getElementById('gauge-measuretext'); if (htmlObject === null) { htmlObject = createElement('text', { id: 'gauge-measuretext' }); document.body.appendChild(htmlObject); } const style = 'position: absolute; visibility: hidden;' + ';left: 0px; top: -100px; white-space: nowrap;' + getFontStyle(font); htmlObject.innerText = text; htmlObject.style.cssText = style; return new Size(htmlObject.clientWidth, htmlObject.clientHeight); } /** * Function to find number from string * * @param {string} value - Specifies the value. * @param {number} maxDimension - Specifies the maximum dimension. * @returns {number} - Returns the number. * @private */ function toPixel(value, maxDimension) { return value.indexOf('%') !== -1 ? (maxDimension / 100) * parseInt(value, 10) : parseInt(value, 10); } /** * Function to get the style from FontModel. * * @param {FontModel} font - Specifies the font. * @returns {string} - Returns the string. * @private */ function getFontStyle(font) { let style = ''; style = 'font-size:' + font.size + '; font-style:' + font.fontStyle + '; font-weight:' + font.fontWeight + '; font-family:' + font.fontFamily + ';opacity:' + font.opacity + '; color:' + font.color + ';'; return style; } /** * Function to create the text element. * * @param {TextOption} options - Specifies the options. * @param {FontModel} font - Specifies the font. * @param {string} color - Specifies the color. * @param {HTMLElement | Element} parent - Specifies the html element. * @param {string} styles - Specifies the style. * @returns {Element} - Returns the element. * @private */ function textElement(options, font, color, parent, styles) { // eslint-disable-next-line @typescript-eslint/no-explicit-any let renderOptions = {}; const renderer = new SvgRenderer(''); const style = styles + ' font-size:' + font.size + '; font-style:' + font.fontStyle + ' ; font-weight:' + font.fontWeight + '; font-family:' + font.fontFamily + ';'; renderOptions = { 'id': options.id, 'x': options.x, 'y': options.y, 'fill': color, 'text-anchor': options.anchor, 'transform': options.transform, 'opacity': font.opacity, 'dominant-baseline': options.baseLine, 'style': style }; const htmlObject = renderer.createText(renderOptions, options.text); parent.appendChild(htmlObject); return htmlObject; } /** * Function to append the path to the element. * * @param {PathOption} options - Specifies the options. * @param {Element} element - Specifies the element. * @param {CircularGauge} gauge - Specifies the gauge. * @param {string} functionName - Specifies the function name. * @returns {Element} - Returns the element. * @private */ function appendPath(options, element, gauge, functionName) { functionName = functionName ? functionName : 'Path'; const htmlObject = gauge.renderer['draw' + functionName](options); htmlObject.setAttribute('transform', options.transform); htmlObject.style.cssText = options.style; element.appendChild(htmlObject); return htmlObject; } /** * Function to check whether it's a complete circle for circular gauge. * * @param {number} startAngle - Specifies the startAngle. * @param {number} endAngle - Specifies the endAngle. * @returns {boolean} Returns the boolean value. * @private */ function isCompleteAngle(startAngle, endAngle) { let totalAngle = endAngle - startAngle; totalAngle = totalAngle <= 0 ? (totalAngle + 360) : totalAngle; return Math.floor(totalAngle / 360) !== 0; } /** * Function to get the degree for circular gauge. * * @param {number} startAngle - Specifies the startAngle. * @param {number} endAngle - Specifies the endAngle. * @returns {number} - Returns the number. * @private */ function getDegree(startAngle, endAngle) { const degree = endAngle - startAngle; return degree < 0 ? (degree + 360) : degree; } /** * Function to get the angle from value for circular gauge. * * @param {number} value - Specifies the value. * @param {number} maximumValue - Specifies the maximumValue. * @param {number} minimumValue - Specifies the minimumValue. * @param {number} startAngle - Specifies the startAngle. * @param {number} endAngle - Specifies the endAngle. * @param {boolean} isClockWise - Specifies the isClockWise. * @returns {number} - Returns the number. * @private */ function getAngleFromValue(value, maximumValue, minimumValue, startAngle, endAngle, isClockWise) { let angle; endAngle -= isCompleteAngle(startAngle, endAngle) ? 0.0001 : 0; startAngle -= 90; endAngle -= 90; if (isClockWise) { angle = ((value - minimumValue) * (getDegree(startAngle, endAngle) / (maximumValue - minimumValue))) + startAngle; } else { angle = endAngle - ((value - minimumValue) * (getDegree(startAngle, endAngle) / (maximumValue - minimumValue))); angle = angle < 0 ? 360 + angle : angle; } angle = Math.round(angle) >= 360 ? (angle - 360) : Math.round(angle) < 0 ? (360 + angle) : angle; return angle; } /** * Function to get angle from location for circular gauge. * * @param {GaugeLocation} center - Specifies the center. * @param {GaugeLocation} point - Specifies the point. * @returns {number} - Returns the number. * @private */ function getAngleFromLocation(center, point) { let angle = Math.atan2((point.y - center.y), (point.x - center.x)); angle = Math.round((angle < 0 ? (6.283 + angle) : angle) * (180 / Math.PI)) - 270; angle += angle < 0 ? 360 : 0; return angle; } /** * Function to get the location from angle for circular gauge. * * @param {number} degree - Specifies the degree. * @param {number} radius - Specifies the radius. * @param {GaugeLocation} center - Specifies the center. * @returns {GaugeLocation} - Returns the gauge location. * @private */ function getLocationFromAngle(degree, radius, center) { const radian = (degree * Math.PI) / 180; return new GaugeLocation(Math.cos(radian) * radius + center.x, Math.sin(radian) * radius + center.y); } /** * Function to get the path direction of the circular gauge. * * @param {GaugeLocation} center - Specifies the center. * @param {number} start - Specifies the start. * @param {number} end - Specifies the end. * @param {number} radius - Specifies the radius. * @param {number} startWidth - Specifies the startWidth. * @param {number} endWidth - Specifies the endWidth. * @param {Range} range - Specifies the range. * @param {Axis} axis - Specifies the axis. * @returns {string} - Returns the string. * @private */ function getPathArc(center, start, end, radius, startWidth, endWidth, range, axis) { if (isNullOrUndefined(range) || (range.start !== range.end)) { end -= isCompleteAngle(start, end) ? 0.0001 : 0; } const degree = getDegree(start, end); const startRadius = !isNullOrUndefined(range) ? (range.position === 'Outside' && !range.isLinearCircularGradient ? radius + startWidth : range.position === 'Cross' && axis.direction === 'AntiClockWise' ? radius - (endWidth + startWidth) / 2 : radius - startWidth) : radius - startWidth; const endRadius = !isNullOrUndefined(range) ? (range.position === 'Outside' && !range.isLinearCircularGradient ? radius + endWidth : range.position === 'Cross' && axis.direction === 'ClockWise' ? radius - (endWidth + startWidth) / 2 : radius - endWidth) : radius - endWidth; const arcRadius = !isNullOrUndefined(range) ? (range.position === 'Outside' && !range.isLinearCircularGradient ? radius + ((startWidth + endWidth) / 2) : range.position === 'Cross' ? (radius - ((startWidth + endWidth) / 4) - (axis.direction === 'ClockWise' ? startWidth : endWidth) / 2) : radius - ((startWidth + endWidth) / 2)) : radius - ((startWidth + endWidth) / 2); const insideArcRadius = !isNullOrUndefined(range) && range.position === 'Cross' ? radius + ((startWidth + endWidth) / 4) - (axis.direction === 'ClockWise' ? startWidth : endWidth) / 2 : radius; let insideEndRadius = !isNullOrUndefined(range) && range.position === 'Cross' && axis.direction === 'ClockWise' ? radius - ((startWidth - endWidth) / 2) : radius; const insideStartRadius = !isNullOrUndefined(range) && range.position === 'Cross' && axis.direction === 'AntiClockWise' ? radius + ((startWidth - endWidth) / 2) : radius; if (startWidth !== undefined && endWidth !== undefined) { insideEndRadius = range.position === 'Cross' ? (degree > 325 ? insideStartRadius : insideEndRadius) : insideEndRadius; return getRangePath(getLocationFromAngle(start, insideStartRadius, center), getLocationFromAngle(end, insideEndRadius, center), getLocationFromAngle(start, startRadius, center), getLocationFromAngle(end, endRadius, center), insideArcRadius, startRadius, endRadius, arcRadius, (degree < 180) ? 0 : 1, center, degree, range, axis); } else { return getCirclePath(getLocationFromAngle(start, radius, center), getLocationFromAngle(end, radius, center), radius, (degree < 180) ? 0 : 1); } } /** * Function to get the range path arc direction of the circular gauge. * * @param {GaugeLocation} start - Specifies the start. * @param {GaugeLocation} end - Specifies the end. * @param {number} radius - Specifies the radius. * @param {number} arcStartOne - Specifies the arcStartOne. * @param {number} arcEndOne - Specifies the arcEndOne. * @param {number} arcStartTwo - Specifies the arcStartTwo. * @param {number} arcEndTwo - Specifies the arcEndTwo. * @param {number} clockWise - Specifies the clockWise. * @param {GaugeLocation} innerStart - Specifies the innerStart. * @param {GaugeLocation} innerEnd - Specifies the innerEnd. * @param {GaugeLocation} pointPosition - Specifies the pointPosition. * @returns {string} - Returns the string. * @private */ function arcPath(start, end, radius, arcStartOne, arcEndOne, arcStartTwo, arcEndTwo, clockWise, innerStart, innerEnd, pointPosition) { return 'M ' + start.x + ' ' + start.y + ' A ' + radius + ' ' + radius + ' 0 ' + clockWise + ' 1 ' + end.x + ' ' + end.y + ' L ' + innerEnd.x + ' ' + innerEnd.y + ' A ' + arcStartOne + ' ' + arcEndOne + ' 0 ' + clockWise + ' 0 ' + pointPosition.x + ' ' + pointPosition.y + ' ' + ' A ' + arcStartTwo + ' ' + arcEndTwo + ' 0 ' + clockWise + ' 0 ' + innerStart.x + ' ' + innerStart.y + ' Z '; } /** * Function to get the range path arc direction of the circular gauge. * * @param {GaugeLocation} start - Specifies the start. * @param {GaugeLocation} end - Specifies the end. * @param {number} radius - Specifies the radius. * @param {GaugeLocation} outerOldEnd - Specifies the outerOldEnd. * @param {GaugeLocation} innerOldEnd - Specifies the innerOldEnd. * @param {number} arcStartOne - Specifies the arcStartOne. * @param {number} arcEndOne - Specifies the arcEndOne. * @param {number} arcStartTwo - Specifies the arcStartTwo. * @param {number} arcEndTwo - Specifies the arcEndTwo. * @param {number} clockWise - Specifies the clockWise. * @param {GaugeLocation} innerStart - Specifies the innerStart. * @param {GaugeLocation} innerEnd - Specifies the innerEnd. * @param {GaugeLocation} innerOldStart - Specifies the innerOldStart. * @param {GaugeLocation} outerOldStart - Specifies the outerOldStart. * @param {GaugeLocation} pointPosition - Specifies the pointPosition. * @returns {string} - Returns the string. * @private */ function arcRoundedPath(start, end, radius, outerOldEnd, innerOldEnd, arcStartOne, arcEndOne, arcStartTwo, arcEndTwo, clockWise, innerStart, innerEnd, innerOldStart, outerOldStart, pointPosition) { const roundedPath = 'M ' + start.x + ' ' + start.y + ' A ' + radius + ' ' + radius + ' 0 ' + clockWise + ' 1 ' + end.x + ' ' + end.y + ' C ' + outerOldEnd.x + ' ' + outerOldEnd.y + ' ' + innerOldEnd.x + ' ' + innerOldEnd.y + ' ' + innerEnd.x + ' ' + innerEnd.y; if (isNullOrUndefined(arcStartTwo) && isNullOrUndefined(arcEndTwo)) { return roundedPath + ' A ' + arcStartOne + ' ' + arcEndOne + ' 0 ' + clockWise + ' 0 ' + innerStart.x + ' ' + innerStart.y + ' C ' + innerOldStart.x + ' ' + innerOldStart.y + ' ' + outerOldStart.x + ' ' + outerOldStart.y + ' ' + start.x + ' ' + start.y + ' Z'; } else { return roundedPath + ' A ' + arcStartOne + ' ' + arcEndOne + ' 0 ' + clockWise + ' 0 ' + pointPosition.x + ' ' + pointPosition.y + ' ' + ' A ' + arcStartTwo + ' ' + arcEndTwo + ' 0 ' + clockWise + ' 0 ' + innerStart.x + ' ' + innerStart.y + ' C ' + innerOldStart.x + ' ' + innerOldStart.y + ' ' + outerOldStart.x + ' ' + outerOldStart.y + ' ' + start.x + ' ' + start.y + ' Z'; } } /** * Function to get the range path direction for different start and end width of the circular gauge. * * @param {GaugeLocation} start - Specifies the options. * @param {GaugeLocation} end - Specifies the end. * @param {GaugeLocation} innerStart - Specifies the innerStart. * @param {GaugeLocation} innerEnd - Specifies the innerEnd. * @param {number} radius - Specifies the radius. * @param {number} startRadius - Specifies the startRadius. * @param {number} endRadius - Specifies the endRadius. * @param {number} clockWise - Specifies the clockWise. * @returns {string} - Returns the string. * @private */ function arcWidthPath(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise) { return 'M ' + start.x + ' ' + start.y + ' A ' + radius + ' ' + radius + ' 0 ' + clockWise + ' 1 ' + end.x + ' ' + end.y + ' L ' + innerEnd.x + ' ' + innerEnd.y + ' A ' + endRadius + ' ' + startRadius + ' 0 ' + clockWise + ' 0 ' + innerStart.x + ' ' + innerStart.y + ' Z'; } /** * Function to get the range path direction of the circular gauge. * * @param {GaugeLocation} start - Specifies the start values. * @param {GaugeLocation} end - Specifies the end values. * @param {GaugeLocation} innerStart - Specifies the innerStart values. * @param {GaugeLocation} innerEnd - Specifies the innerEnd values. * @param {number} radius - Specifies the radius value. * @param {number} startRadius - Specifies the startRadius value. * @param {number} endRadius - Specifies the endRadius value. * @param {number} arcRadius - Specifies the arcRadius value. * @param {number} clockWise - Specifies the clockWise value. * @param {GaugeLocation} center - Specifies the center value. * @param {number} degree - Specifies the degree value. * @param {Range} range - Specifies the range value. * @param {Axis} axis - Specifies the axis value. * @returns {string} - Returns the string value. * @private */ function getRangePath(start, end, innerStart, innerEnd, radius, startRadius, endRadius, arcRadius, clockWise, center, degree, range, axis) { const startWidth = range.startWidth; const endWidth = range.endWidth; const widthDifference = Math.abs(startWidth - endWidth); let endArc; let startArc; if (startWidth > endWidth && degree <= 260 && range.position !== 'Cross' && range.position !== 'Outside') { endArc = (endRadius + (axis.direction === 'ClockWise' ? -(widthDifference / 2) : (widthDifference / 2))); startArc = (startRadius + (axis.direction === 'ClockWise' ? (widthDifference / 2) : -(widthDifference / 2))); return arcWidthPath(start, end, innerStart, innerEnd, radius, startArc, endArc, clockWise); } else if (endWidth > startWidth && degree <= 260 && range.position !== 'Cross' && range.position !== 'Outside') { endArc = (startRadius + (axis.direction === 'ClockWise' ? -(widthDifference / 2) : (widthDifference / 2))); startArc = (endRadius + (axis.direction === 'ClockWise' ? (widthDifference / 2) : -(widthDifference / 2))); return arcWidthPath(start, end, innerStart, innerEnd, radius, startArc, endArc, clockWise); } else if ((endWidth === startWidth) && (axis.startAngle !== 0 || axis.endAngle !== 0)) { return arcWidthPath(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise); } else if ((degree > 260) || (!range.isLinearCircularGradient && axis.startAngle === 0 && axis.endAngle === 0)) { if (range.roundedCornerRadius <= 0 && range.startWidth === range.endWidth) { return arcWidthPath(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise); } else { return arcWidthPathCalculation(start, end, innerStart, innerEnd, radius, startRadius, endRadius, arcRadius, clockWise, center, null, null, null, null, startWidth, endWidth, degree, range, axis); } } else { if (range.position === 'Cross' || range.position === 'Outside') { return arcWidthPath(start, end, innerStart, innerEnd, radius, arcRadius, arcRadius, clockWise); } else { return arcWidthPath(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise); } } } /** * Function to get start and end width range path calculation to the circular gauge. * * @param {GaugeLocation} start - Specifies the start value. * @param {GaugeLocation} end - Specifies the end value. * @param {GaugeLocation} innerStart - Specifies the innerStart value. * @param {GaugeLocation} innerEnd - Specifies the innerEnd value. * @param {number} radius - Specifies the radius value. * @param {number} startRadius - Specifies the startRadius value. * @param {number} endRadius - Specifies the endRadius value. * @param {number} arcRadius - Specifies the arcRadius value. * @param {number} clockWise - Specifies the clockWise value. * @param {GaugeLocation} center - Specifies the center value. * @param {GaugeLocation} outerOldEnd - Specifies the outerOldEnd value. * @param {GaugeLocation} innerOldEnd - Specifies the innerOldEnd value. * @param {GaugeLocation} outerOldStart - Specifies the outerOldStart value. * @param {GaugeLocation} innerOldStart - Specifies the innerOldStart value. * @param {number} startWidth - Specifies the startWidth value. * @param {number} endWidth - Specifies the endWidth value. * @param {number} degree - Specifies the degree value. * @param {Range} range - Specifies the range value. * @param {Axis} axis - Specifies the axis value. * @returns {string} - Returns the svg path. * @private */ function arcWidthPathCalculation(start, end, innerStart, innerEnd, radius, startRadius, endRadius, arcRadius, clockWise, center, outerOldEnd, innerOldEnd, outerOldStart, innerOldStart, startWidth, endWidth, degree, range, axis) { if (!isNullOrUndefined(range)) { let arcStartOne; let arcEndOne; let widthDifference = Math.abs(startWidth - endWidth); let arcStartTwo; let arcEndTwo; const startValueToAngle = getAngleFromValue(((range.start + range.end) / 2), axis.maximum, axis.minimum, axis.startAngle, axis.endAngle, axis.direction === 'ClockWise'); const pointPosition = (startWidth < ((endWidth))) ? getLocationFromAngle(startValueToAngle, endRadius, center) : getLocationFromAngle(startValueToAngle, startRadius, center); const endDistance = Math.sqrt((Math.pow((innerEnd.x - pointPosition.x), 2)) + (Math.pow((innerEnd.y - pointPosition.y), 2))); const endRadii = endDistance / 2; const centerStartDistance = Math.sqrt((Math.pow((center.x - innerStart.x), 2)) + (Math.pow((center.y - innerStart.y), 2))); const centerDistance = Math.sqrt((Math.pow((center.x - pointPosition.x), 2)) + (Math.pow((center.y - pointPosition.y), 2))); if (range.roundedCornerRadius <= 0) { widthDifference = widthDifference === 0 ? 1 : widthDifference; innerEnd.y = (range.position === 'Cross' && axis.direction === 'ClockWise') ? degree > 325 ? innerEnd.y - (widthDifference / 2) : innerEnd.y : innerEnd.y; const degreeValue = range.position === 'Cross' ? 330 : 325; if (((degreeValue <= degree && degree <= 360))) { arcStartTwo = (axis.direction === 'ClockWise' ? (centerDistance / 2) : (degree >= 345 ? (startRadius - (widthDifference / 2) - (endWidth / 2)) : range.position === 'Cross' ? (startRadius + (widthDifference / 4) - (startWidth / 2)) : (startRadius - (widthDifference / 2) - (startWidth / 2)))); arcEndTwo = (axis.direction === 'ClockWise' ? (centerStartDistance / 2) : range.position === 'Cross' ? (endRadius + (widthDifference / 4)) - (endWidth / 4) : (range.position === 'Outside' && axis.direction === 'AntiClockWise') ? degree < 345 ? (startRadius - (widthDifference) - (endWidth / 4)) : (startRadius - (widthDifference / 2)) : (endRadius + (widthDifference / 2)) - (endWidth / 2)); return arcPath(start, end, radius, endRadii, endRadii, arcStartTwo, arcEndTwo, clockWise, innerStart, innerEnd, pointPosition); } else if ((degree > 260 && degree < 325) && range.position !== 'Cross' && range.position !== 'Outside') { let arcStart = (arcRadius - (widthDifference / 2)); const arcEnd = (arcRadius - (widthDifference / 2)); const angleValueDirection = axis.direction === 'ClockWise' ? degree >= 310 : degree < 345; if (degree < 310) { return arcWidthPath(start, end, innerStart, innerEnd, radius, arcStart, arcEnd, clockWise); } else if (degree >= 310 || angleValueDirection) { arcStart = (arcRadius - (widthDifference)); return arcWidthPath(start, end, innerStart, innerEnd, radius, arcEnd, arcStart, clockWise); } else { return arcWidthPath(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise); } } else { if (range.position === 'Cross') { const endRadiusValue = axis.direction === 'ClockWise' ? degree <= 300 && degree >= 260 ? endRadius - (widthDifference / 2) - (startWidth / 4) : endRadius - (widthDifference) - (startWidth / 2) : degree <= 300 && degree >= 260 ? endRadius + (widthDifference / 4) - (startWidth / 4) : endRadius + (widthDifference / 4) - (startWidth / 2); const startRadiusValue = axis.direction === 'ClockWise' ? degree > 325 ? degree > 340 ? (startRadius - startWidth) - (widthDifference / 4) : startRadius - (widthDifference / 4) : startRadius : startRadius - (widthDifference / 4); return arcWidthPath(start, end, innerStart, innerEnd, radius, startRadiusValue, endRadiusValue, clockWise); } else if (range.position === 'Outside') { if (degree < 325 && degree > 285) { let arcTwo; const startGreater = startWidth / 2; const endGreater = endWidth / 2; const arcOne = arcTwo = arcRadius + (widthDifference / 2) + startGreater + endGreater; innerEnd.y = axis.direction === 'ClockWise' && startWidth !== endWidth && startWidth > widthDifference ? innerEnd.y - (widthDifference / 2) : innerEnd.y + startGreater; return arcWidthPath(start, end, innerStart, innerEnd, radius, arcOne, arcTwo, clockWise); } else { return arcWidthPath(start, end, innerStart, innerEnd, radius, arcRadius, arcRadius, clockWise); } } else { return arcWidthPath(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise); } } } else { const degreeAngle = axis.endAngle < 4 ? 356 : 360; clockWise = degree > degreeAngle ? 0 : clockWise; const degreeValueOne = axis.direction === 'ClockWise' ? 327 : 322; const degreeValueTwo = axis.direction === 'ClockWise' ? 328 : 325; if ((endWidth === startWidth) && (axis.startAngle !== 0 || axis.endAngle !== 0)) { return roundedArcWidthPathCalculation(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise, outerOldEnd, innerOldEnd, outerOldStart, innerOldStart); } else if ((degree <= degreeAngle && degree > degreeValueOne) && range.roundedCornerRadius > 0) { arcStartOne = axis.direction === 'ClockWise' ? degree < 334 && degree > 324 ? endRadii - (widthDifference / 2) : endRadii - (widthDifference / 4) : endRadii; arcStartTwo = (centerDistance / 2); arcEndTwo = axis.direction === 'ClockWise' ? ((centerStartDistance / 2) + (widthDifference / 2)) : (centerStartDistance / 2); return arcRoundedPath(start, end, radius, outerOldEnd, innerOldEnd, arcStartOne, endRadii, arcStartTwo, arcEndTwo, clockWise, innerStart, innerEnd, innerOldStart, outerOldStart, pointPosition); } else if (degree > 270 && degree < degreeValueTwo) { const startAddArc = endRadius + (widthDifference / 2) - (endWidth / 2); const startSubArc = endRadius - (widthDifference / 2) - (endWidth / 2); arcStartOne = (startRadius - (widthDifference / 2) - (startWidth / 2)); arcEndOne = (axis.direction === 'ClockWise' ? startSubArc : startAddArc); return arcRoundedPath(start, end, radius, outerOldEnd, innerOldEnd, arcStartOne, arcEndOne, null, null, clockWise, innerStart, innerEnd, innerOldStart, outerOldStart, null); } else { return roundedArcWidthPathCalculation(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise, outerOldEnd, innerOldEnd, outerOldStart, innerOldStart); } } } else { return roundedArcWidthPathCalculation(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise, outerOldEnd, innerOldEnd, outerOldStart, innerOldStart); } } /** * Function to get start and end width range rounded path calculation to the circular gauge. * * @param {GaugeLocation} start - Specifies the start value. * @param {GaugeLocation} end - Specifies the end value. * @param {GaugeLocation} innerStart - Specifies the innerStart value. * @param {GaugeLocation} innerEnd - Specifies the innerEnd value. * @param {number} radius - Specifies the radius value. * @param {number} startRadius - Specifies the startRadius value. * @param {number} endRadius - Specifies the endRadius value. * @param {number} clockWise - Specifies the clockWise value. * @param {GaugeLocation} outerOldEnd - Specifies the outerOldEnd value. * @param {GaugeLocation} innerOldEnd - Specifies the innerOldEnd value. * @param {GaugeLocation} outerOldStart - Specifies the outerOldStart value. * @param {GaugeLocation} innerOldStart - Specifies the innerOldStart value. * @returns {string} - Returns the path value. * @private */ function roundedArcWidthPathCalculation(start, end, innerStart, innerEnd, radius, startRadius, endRadius, clockWise, outerOldEnd, innerOldEnd, outerOldStart, innerOldStart) { return 'M ' + start.x + ' ' + start.y + ' A ' + radius + ' ' + radius + ' 0 ' + clockWise + ' 1 ' + end.x + ' ' + end.y + ' C ' + outerOldEnd.x + ' ' + outerOldEnd.y + ' ' + innerOldEnd.x + ' ' + innerOldEnd.y + ' ' + innerEnd.x + ' ' + innerEnd.y + ' A ' + endRadius + ' ' + startRadius + ' 0 ' + clockWise + ' 0 ' + innerStart.x + ' ' + innerStart.y + ' C ' + innerOldStart.x + ' ' + innerOldStart.y + ' ' + outerOldStart.x + ' ' + outerOldStart.y + ' ' + start.x + ' ' + start.y + ' Z'; } /** * Function to get the rounded path direction of the circular gauge. * * @param {GaugeLocation} center - Specifies the center value. * @param {number} actualStart - Specifies the actualStart value. * @param {number} actualEnd - Specifies the actualEnd value. * @param {number} oldStart - Specifies the oldStart value. * @param {number} oldEnd - Specifies the oldEnd value. * @param {number} radius - Specifies the radius value. * @param {number} startWidth - Specifies the startWidth value. * @param {number} endWidth - Specifies the endWidth value. * @param {Range} range - Specifies the range value. * @param {Axis} axis - Specifies the axis value. * @returns {string} - Returns the path value. * @private */ function getRoundedPathArc(center, actualStart, actualEnd, oldStart, oldEnd, radius, startWidth, endWidth, range, axis) { actualEnd -= isCompleteAngle(actualStart, actualEnd) ? 0.0001 : 0; const degree = getDegree(actualStart, actualEnd); const startRadius = radius - startWidth; const endRadius = radius - endWidth; const arcRadius = radius - ((startWidth + endWidth) / 2); return arcWidthPathCalculation(getLocationFromAngle(actualStart, radius, center), getLocationFromAngle(actualEnd, radius, center), getLocationFromAngle(actualStart, startRadius, center), getLocationFromAngle(actualEnd, endRadius, center), radius, arcRadius, arcRadius, arcRadius, (degree < 180) ? 0 : 1, center, getLocationFromAngle(oldEnd, radius, center), getLocationFromAngle(oldEnd, endRadius, center), getLocationFromAngle(oldStart, radius, center), getLocationFromAngle(oldStart, startRadius, center), startWidth, endWidth, degree, range, axis); } /** * Function to get the circular path direction of the circular gauge. * * @param {GaugeLocation} start - Specifies the start value. * @param {GaugeLocation} end - Specifies the end value. * @param {number} radius - Specifies the radius value. * @param {number} clockWise - Specifies the clockWise. * @returns {string} - Returns the path. * @private */ function getCirclePath(start, end, radius, clockWise) { return 'M ' + start.x + ' ' + start.y + ' A ' + radius + ' ' + radius + ' 0 ' + clockWise + ' 1 ' + end.x + ' ' + end.y; } /** * Function to compile the template function for circular gauge. * * @param {string} template - Specifies the template. * @param {CircularGauge} gauge - Specifies the gauge instance. * @returns {Function} - Returns the template function. * @private */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function getTemplateFunction(template, gauge) { // eslint-disable-next-line @typescript-eslint/no-explicit-any let templateFn = null; try { if (typeof template === 'function') { templateFn = compile(template); } else if (isNaN(parseFloat(template)) && document.querySelectorAll(template).length) { if ((template.charAt(0) !== 'a' || template.charAt(0) !== 'A') && template.length !== 1) { templateFn = compile(document.querySelector(template).innerHTML.trim()); } // eslint-disable-next-line @typescript-eslint/no-explicit-any } else if (gauge.isVue || gauge.isVue3) { templateFn = compile(template); } } catch (e) { templateFn = compile(template); } return templateFn; } /** * Function to remove the element from id. * * @param {string} id Specifies the id * @returns {void} * @private */ function removeElement(id) { const element = getElement(id); if (element) { remove(element); } } /** * Function to get element from id. * * @param {string} id - Specifies the id. * @returns {Element} - Returns the element. * @private */ function getElement(id) { return document.getElementById(id); } /** * Function to convert the number from string. * * @param {string} value - Specifies the value. * @param {number} containerSize - Specifies the container size. * @returns {number} - Returns the number. * @private */ function stringToNumber(value, containerSize) { if (value !== null && value !== undefined) { return value.indexOf('%') !== -1 ? (containerSize / 100) * parseInt(value, 10) : parseInt(value, 10); } return null; } /** * Function to get current point for circular gauge using element id. * * @param {string} targetId - Specifies the target id. * @param {CircularGauge} gauge - Specifies the gauge instance. * @returns {IVisiblePointer} - Returns the pointer and axis index. * @private */ function getPointer(targetId, gauge) { const tempString = targetId.replace(gauge.element.id, '').split('_Axis_')[1]; const tempStringArray = tempString.indexOf('_Range_') > -1 ? tempString.split('_Range_') : tempString.indexOf('_Pointer_NeedleCap_') > -1 ? tempString.split('_Pointer_NeedleCap_') : tempString.indexOf('_Pointer_NeedleTail_') > -1 ? tempString.split('_Pointer_NeedleTail_') : tempString.indexOf('_Pointer_NeedleRect_') > -1 ? tempString.split('_Pointer_NeedleRect_') : tempString.indexOf('_Pointer_Needle_') > -1 ? tempString.split('_Pointer_Needle_') : tempString.indexOf('_Pointer_RangeBar_') > -1 ? tempString.split('_Pointer_RangeBar_') : tempString.indexOf('_Pointer_Marker_') > -1 ? tempString.split('_Pointer_Marker_') : tempString.indexOf('_Pointer_') > -1 ? tempString.split('_Pointer_') : tempString.split('_Annotation_'); return { axisIndex: +tempStringArray[0], pointerIndex: +tempStringArray[tempStringArray.length - 1] }; } /** * Function to convert the label using format for cirular gauge. * * @param {string} format - Specifies the format. * @returns {string} - Returns th string. * @private */ function getLabelFormat(format) { const customLabelFormat = format && format.match('{value}') !== null; const skeleton = customLabelFormat ? '' : format; return skeleton; } /** * Function to calculate the marker shape for circular gauge. * * @param {GaugeLocation} location - Specifies the location. * @param {string} shape - Specifies the shape. * @param {Size} size - Specifies the size. * @param {string} url - Specifies the url. * @param {PathOption} options - Specifies the path option. * @returns {PathOption} - Returns the path. * @private */ function calculateShapes(location, shape, size, url, options) { let path; const width = typeof size.width === 'string' ? parseFloat(size.width) : size.width; const height = typeof size.height === 'string' ? parseFloat(size.height) : size.height; const locX = location.x; const locY = location.y; const x = location.x + (-width / 2); const y = location.y + (-height / 2); const isLegend = options.id.indexOf('Shape') > -1; let space; switch (shape) { case 'Circle': merge(options, { 'rx': width / 2, 'ry': height / 2, 'cx': locX, 'cy': locY }); break; case 'Diamond': path = 'M' + ' ' + x + ' ' + locY + ' ' + 'L' + ' ' + locX + ' ' + (locY + (-height / 2)) + ' ' + 'L' + ' ' + (locX + (width / 2)) + ' ' + locY + ' ' + 'L' + ' ' + locX + ' ' + (locY + (height / 2)) + ' ' + 'L' + ' ' + x + ' ' + locY + ' Z'; merge(options, { 'd': path }); break; case 'Rectangle': path = 'M' + ' ' + x + ' ' + (locY + (-height / 2)) + ' ' + 'L' + ' ' + (locX + (width / 2)) + ' ' + (locY + (-height / 2)) + ' ' + 'L' + ' ' + (locX + (width / 2)) + ' ' + (locY + (height / 2)) + ' ' + 'L' + ' ' + x + ' ' + (locY + (height / 2)) + ' ' + 'L' + ' ' + x + ' ' + (locY + (-height / 2)) + ' Z'; merge(options, { 'd': path }); break; case 'Triangle': if (isLegend) { path = 'M' + ' ' + (x + (width / 2)) + ' ' + y + ' ' + 'L' + ' ' + (x + width) + ' ' + (y + height) + 'L' + ' ' + x + ' ' + (y + height) + ' Z'; } else { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + ' ' + (locX - height) + ' ' + (locY - (width / 2)) + 'L' + ' ' + (locX - height) + ' ' + (locY + (width / 2)) + ' Z'; } merge(options, { 'd': path }); break; case 'InvertedTriangle': if (isLegend) { path = 'M' + ' ' + (x + width) + ' ' + y + ' ' + 'L' + ' ' + (x + (width / 2)) + ' ' + (y + height) + 'L' + ' ' + x + ' ' + (y) + ' Z'; } else { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + ' ' + (locX + height) + ' ' + (locY - (width / 2)) + 'L' + ' ' + (locX + height) + ' ' + (locY + (width / 2)) + ' Z'; } merge(options, { 'd': path }); break; case 'Image': merge(options, { 'href': url, 'height': height, 'width': width, x: x, y: y }); break; case 'RightArrow': space = 2; path = 'M' + ' ' + (locX + (-width / 2)) + ' ' + (locY - (height / 2)) + ' ' + 'L' + ' ' + (locX + (width / 2)) + ' ' + (locY) + ' ' + 'L' + ' ' + (locX + (-width / 2)) + ' ' + (locY + (height / 2)) + ' L' + ' ' + (locX + (-width / 2)) + ' ' + (locY + (height / 2) - space) + ' ' + 'L' + ' ' + (locX + (width / 2) - (2 * space)) + ' ' + (locY) + ' L' + (locX + (-width / 2)) + ' ' + (locY - (height / 2) + space) + ' Z'; merge(options, { 'd': path }); break; case 'LeftArrow': options.fill = options.stroke; options.stroke = 'transparent'; space = 2; path = 'M' + ' ' + (locX + (width / 2)) + ' ' + (locY - (height / 2)) + ' ' + 'L' + ' ' + (locX + (-width / 2)) + ' ' + (locY) + ' ' + 'L' + ' ' + (locX + (width / 2)) + ' ' + (locY + (height / 2)) + ' ' + 'L' + ' ' + (locX + (width / 2)) + ' ' + (locY + (height / 2) - space) + ' L' + ' ' + (locX + (-width / 2) + (2 * space)) + ' ' + (locY) + ' L' + (locX + (width / 2)) + ' ' + (locY - (height / 2) + space) + ' Z'; merge(options, { 'd': path }); break; } return options; } /** @private */ class CustomizeOption { constructor(id) { this.id = id; } } /** @private */ class PathOption extends CustomizeOption { constructor(id, fill, width, color, opacity, dashArray, d, transform = '', style = '') { super(id); this.opacity = opacity; this.fill = fill; this.stroke = color; this['stroke-width'] = width; this['stroke-dasharray'] = dashArray; this.d = d; this.transform = transform; this.style = style; } } /** @private */ class RectOption extends CustomizeOption { constructor(id, fill, border, opacity, rect) { super(id); this.y = rect.y; this.x = rect.x; this.height = rect.height; this.width = rect.width; this.opacity = opacity; this.fill = fill; this.stroke = border.color; this['stroke-width'] = border.width; this['stroke-dasharray'] = border.dashArray; } } /** * Specifies the size information of an element. */ class Size { constructor(width, height) { this.width = width; this.height = height; } } /** * Specifies the location of the element in the circular gauge. */ class GaugeLocation { constructor(x, y) { this.x = x; this.y = y; } } /** @private */ class Rect { constructor(x, y, width, height) { this.x = x; this.y = y; this.width = width; this.height = height; } } /** @private */ class TextOption extends CustomizeOption { constructor(id, x, y, anchor, text, transform = '', baseLine) { super(id); this.transform = ''; this.baseLine = 'auto'; this.x = x; this.y = y; this.anchor = anchor; this.text = text; this.transform = transform; this.baseLine = baseLine; } } /** @private */ class VisibleLabels { constructor(text, value, size) { this.text = text; this.value = value; this.size = size; } } /** * Specifies Circular-Gauge Helper methods */ /** * Function to set style to the element. * * @param {HTMLElement} element - Specifies the element. * @param {string} fill - Specifies the fill of the element. * @param {BorderModel} border - Specifies the border of the element. * @returns {void} * @private */ function setStyles(element, fill, border) { setStyleAttribute(element, { 'stroke': border.color, 'stroke-width': border.width, 'fill': fill }); } /** * Function to get the value from angle for circular gauge. * * @param {number} angle - Specifies the angle. * @param {number} maximumValue - Specifies the maximumValue. * @param {number} minimumValue - Specifies the minimumValue. * @param {number} startAngle - Specifies the startAngle. * @param {number} endAngle - Specifies the endAngle. * @param {boolean} isClockWise - Specifies the isClockWise. * @returns {number} - Returs the number. * @private */ function getValueFromAngle(angle, maximumValue, minimumValue, startAngle, endAngle, isClockWise) { endAngle -= isCompleteAngle(startAngle, endAngle) ? 0.0001 : 0; angle = angle < startAngle ? (angle + 360) : angle; if (isClockWise) { return (((angle - startAngle) / getDegree(startAngle, endAngle)) * (maximumValue - minimumValue)) + minimumValue; } else { return maximumValue - ((((angle - startAngle) / getDegree(startAngle, endAngle)) * (maximumValue - minimumValue))); } } /** * Function to get current point for circular gauge using element id. * * @param {string} targetId - Specifies the target id. * @param {CircularGauge} gauge - Specifies the gauge instance. * @returns {IVisibleRange} - Returns the current point. * @private */ function getRange(targetId, gauge) { const tempString = targetId.replace(gauge.element.id, '').split('_Axis_')[1]; return { axisIndex: +tempString[0], rangeIndex: +tempString.split('Range_')[1] }; } /** * Specifies gauge Themes */ var Theme; (function (Theme) { /** @private */ Theme.axisLabelFont = { size: null, fontWeight: null, color: null, fontStyle: 'Normal', fontFamily: null }; Theme.legendLabelFont = { size: null, fontWeight: null, color: null, fontStyle: 'Normal', fontFamily: null }; })(Theme || (Theme = {})); /** * @param {string} theme theme * @returns {string[]} palette * @private */ function getRangePalette(theme) { let palette = ['#50c917', '#27d5ff', '#fcde0b', '#ffb133', '#ff5985']; switch (theme.toLowerCase()) { case 'tailwind': palette = ['#0369A1', '#14B8A6', '#15803D', '#334155', '#5A61F6', '#65A30D', '#8B5CF6', '#9333EA', '#F59E0B', '#F97316']; break; case 'tailwinddark': palette = ['#10B981', '#22D3EE', '#2DD4BF', '#4ADE80', '#8B5CF6', '#E879F9', '#F472B6', '#F87171', '#F97316', '#FCD34D']; break; case 'tailwind3': palette = ['#2F4074', '#03B4B4', '#0D72DE', '#FF5733', '#D63384', '#F39C12', '#EF291F', '#91C822']; break; case 'tailwind3dark': palette = ['#8029F1', '#1ABC9C', '#0D72DE', '#FF5733', '#D63384', '#F39C12', '#EF291F', '#91C822']; break; case 'fluent': palette = ['#614570', '#4C6FB1', '#CC6952', '#3F579A', '#4EA09B', '#6E7A89', '#D4515C', '#E6AF5D', '#639751', '#9D4D69']; break; case 'fluentdark': palette = ['#8AB113', '#2A72D5', '#43B786', '#584EC6', '#E85F9C', '#6E7A89', '#EA6266', '#EBA844', '#26BC7A', '#BC4870']; break; case 'material3': palette = ['#6200EE', '#E77A16', '#82C100', '#7107DC', '#05BB3D', '#D21020', '#FAD200', '#0085FF', '#9204EA', '#08EE9B']; break; case 'material3dark': palette = ['#4EAAFF', '#FA4EAB', '#FFF500', '#17EA58', '#38FFE7', '#FF9E45', '#B3F32F', '#B93CE4', '#FC5664', '#9B55FF']; break; case 'fluent2': palette = ['#6200EE', '#09AF74', '#0076E5', '#CB3587', '#E7910F', '#0364DE', '#66CD15', '#F3A93C', '#107C10', '#C19C00']; break; case 'fluent2dark': case 'fluent2highcontrast': palette = ['#9BB449', '#2A72D5', '#43B786', '#3F579A', '#584EC6', '#E85F9C', '#6E7A89', '#EA6266', '#0B6A0B', '#C19C00']; break; case 'bootstrap5': case 'bootstrap5dark': palette = ['#6610F2', '#6f42C1', '#D63384', '#DC3545', '#FD7E14', '#FFC107', '#198754', '#0DCAF0']; break; } return palette; } /** * Function to get ThemeStyle * * @param {GaugeTheme} theme theme * @returns {IThemeStyle} style * @private */ function getThemeStyle(theme) { let style; switch (theme.toLowerCase()) { case 'materialdark': case 'fabricdark': case 'bootstrapdark': style = { backgroundColor: '#333232', titleFontColor: '#ffffff', tooltipFillColor: '#FFFFFF', tooltipFontColor: '#000000', tooltipFontSize: '13px', tooltipTextOpacity: 1, labelColor: '#DADADA', lineColor: '#C8C8C8', majorTickColor: '#C8C8C8', minorTickColor: '#9A9A9A', pointerColor: '#9A9A9A', capColor: '#9A9A9A', needleColor: '#9A9A9A', needleTailColor: '#9A9A9A', fontSize: '12px', titleFontSize: '15px', labelFontFamily: 'Segoe UI', fontFamily: 'Segoe UI', fontWeight: 'Normal', titleFontWeight: 'Normal' }; break; case 'highcontrast': style = { backgroundColor: '#000000', titleFontColor: '#FFFFFF', tooltipFillColor: '#ffffff', tooltipFontColor: '#000000', tooltipFontSize: '13px', tooltipTextOpacity: 1, labelColor: '#FFFFFF', lineColor: '#FFFFFF', majorTickColor: '#FFFFFF', minorTickColor: '#FFFFFF', pointerColor: '#FFFFFF', capColor: '#FFFFFF', needleColor: '#FFFFFF', needleTailColor: '#FFFFFF', fontSize: '12px', titleFontSize: '15px', labelFontFamily: 'Segoe UI', fontFamily: 'Segoe UI', fontWeight: 'Normal', titleFontWeight: 'Normal' }; break; case 'bootstrap4': style = { backgroundColor: '#FFFFFF', titleFontColor: '#212529', tooltipFillColor: '#000000', tooltipFontColor: '#FFFFFF', tooltipFontSize: '13px', labelColor: '#212529', lineColor: '#DEE2E6', majorTickColor: '#ADB5BD', minorTickColor: '#CED4DA', pointerColor: '#6C757D', capColor: '#6C757D', needleColor: '#6C757D', needleTailColor: '#6C757D', fontFamily: 'HelveticaNeue-Medium', fontSize: '12px', titleFontSize: '16px', labelFontFamily: 'HelveticaNeue', tooltipFillOpacity: 1, tooltipTextOpacity: 0.9, fontWeight: 'Normal', titleFontWeight: 'Normal' }; break; case 'tailwind': style = { backgroundColor: 'rgba(255,255,255, 0.0)', titleFontColor: '#374151', tooltipFillColor: '#111827', tooltipFontColor: '#F9FAFB', tooltipFontSize: '13px', labelColor: '#6B7280', lineColor: '#E5E7EB', majorTickColor: '#9CA3AF', minorTickColor: '#9CA3AF',