UNPKG

@syncfusion/ej2-lineargauge

Version:
1,311 lines (1,306 loc) 243 kB
import { ChildProperty, Property, Complex, Collection, isNullOrUndefined, createElement, remove, compile, merge, Animation, animationMode, SanitizeHtmlHelper, Browser, Component, Internationalization, EventHandler, Event, NotifyPropertyChanges, print } from '@syncfusion/ej2-base'; import { SvgRenderer, Tooltip } from '@syncfusion/ej2-svg-base'; import { PdfPageOrientation, PdfDocument, PdfBitmap } from '@syncfusion/ej2-pdf-export'; var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * Sets and gets the options for customizing the fonts. */ class Font extends ChildProperty { } __decorate([ Property('16px') ], Font.prototype, "size", void 0); __decorate([ Property('') ], Font.prototype, "color", void 0); __decorate([ Property('Segoe UI') ], Font.prototype, "fontFamily", void 0); __decorate([ Property('Regular') ], Font.prototype, "fontWeight", void 0); __decorate([ Property('Normal') ], Font.prototype, "fontStyle", void 0); __decorate([ Property(1) ], Font.prototype, "opacity", void 0); /** * Defines the font properties such as font-size, font family and others for the text pointer. */ class TextStyle extends ChildProperty { } __decorate([ Property('16px') ], TextStyle.prototype, "size", void 0); __decorate([ Property('') ], TextStyle.prototype, "fontFamily", void 0); __decorate([ Property('normal') ], TextStyle.prototype, "fontWeight", void 0); __decorate([ Property('normal') ], TextStyle.prototype, "fontStyle", void 0); /** * Sets and gets the margin for the linear gauge. */ class Margin extends ChildProperty { } __decorate([ Property(10) ], Margin.prototype, "left", void 0); __decorate([ Property(10) ], Margin.prototype, "right", void 0); __decorate([ Property(10) ], Margin.prototype, "top", void 0); __decorate([ Property(10) ], Margin.prototype, "bottom", void 0); /** * Sets and gets the options to customize the style properties of the border for the linear gauge. */ class Border extends ChildProperty { } __decorate([ Property(null) ], Border.prototype, "color", void 0); __decorate([ Property(0) ], Border.prototype, "width", void 0); __decorate([ Property('') ], Border.prototype, "dashArray", void 0); /** * Sets and gets the options for customizing the annotation in linear gauge. */ class Annotation extends ChildProperty { } __decorate([ Property('') ], Annotation.prototype, "content", void 0); __decorate([ Property(0) ], Annotation.prototype, "x", void 0); __decorate([ Property(0) ], Annotation.prototype, "y", void 0); __decorate([ Property('None') ], Annotation.prototype, "verticalAlignment", void 0); __decorate([ Property('None') ], Annotation.prototype, "horizontalAlignment", void 0); __decorate([ Property('-1') ], Annotation.prototype, "zIndex", void 0); __decorate([ Complex({ size: '12px', color: null }, Font) ], Annotation.prototype, "font", void 0); __decorate([ Property(null) ], Annotation.prototype, "axisIndex", void 0); __decorate([ Property(null) ], Annotation.prototype, "axisValue", void 0); /** * Sets and gets the options for customizing the container of linear gauge. */ class Container extends ChildProperty { } __decorate([ Property('Normal') ], Container.prototype, "type", void 0); __decorate([ Property(0) ], Container.prototype, "height", void 0); __decorate([ Property(0) ], Container.prototype, "width", void 0); __decorate([ Property(10) ], Container.prototype, "roundedCornerRadius", void 0); __decorate([ Property('transparent') ], Container.prototype, "backgroundColor", void 0); __decorate([ Complex({ width: 1, color: null }, Border) ], Container.prototype, "border", void 0); __decorate([ Property(0) ], Container.prototype, "offset", void 0); /** * Sets and gets the options to customize the tooltip for range in axis. */ class RangeTooltip extends ChildProperty { } __decorate([ Property(null) ], RangeTooltip.prototype, "fill", void 0); __decorate([ Complex({ size: null, opacity: null, fontFamily: null, fontWeight: null }, Font) ], RangeTooltip.prototype, "textStyle", void 0); __decorate([ Property(null) ], RangeTooltip.prototype, "format", void 0); __decorate([ Property(null) ], RangeTooltip.prototype, "template", void 0); __decorate([ Property(true) ], RangeTooltip.prototype, "enableAnimation", void 0); __decorate([ Complex({ color: null, width: null }, Border) ], RangeTooltip.prototype, "border", void 0); __decorate([ Property('End') ], RangeTooltip.prototype, "position", void 0); __decorate([ Property(false) ], RangeTooltip.prototype, "showAtMousePosition", void 0); /** * Sets and gets the options for customizing the tooltip in linear gauge. */ class TooltipSettings extends ChildProperty { } __decorate([ Property(false) ], TooltipSettings.prototype, "enable", void 0); __decorate([ Property('') ], TooltipSettings.prototype, "fill", void 0); __decorate([ Complex({ color: '', size: null, opacity: null, fontFamily: null, fontWeight: null }, Font) ], TooltipSettings.prototype, "textStyle", void 0); __decorate([ Property(null) ], TooltipSettings.prototype, "format", void 0); __decorate([ Property(false) ], TooltipSettings.prototype, "showAtMousePosition", void 0); __decorate([ Complex({}, RangeTooltip) ], TooltipSettings.prototype, "rangeSettings", void 0); __decorate([ Property('End') ], TooltipSettings.prototype, "position", void 0); __decorate([ Property(null) ], TooltipSettings.prototype, "template", void 0); __decorate([ Property(true) ], TooltipSettings.prototype, "enableAnimation", void 0); __decorate([ Complex({ color: null, width: null }, Border) ], TooltipSettings.prototype, "border", void 0); __decorate([ Property('Pointer') ], TooltipSettings.prototype, "type", void 0); var __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** Sets and gets the options for customizing the appearance of axis line in linear gauge. */ class Line extends ChildProperty { } __decorate$1([ Property('') ], Line.prototype, "dashArray", void 0); __decorate$1([ Property(null) ], Line.prototype, "height", void 0); __decorate$1([ Property(2) ], Line.prototype, "width", void 0); __decorate$1([ Property(null) ], Line.prototype, "color", void 0); __decorate$1([ Property(0) ], Line.prototype, "offset", void 0); /** * Sets and gets the options for customizing the appearance of the axis labels. */ class Label extends ChildProperty { } __decorate$1([ Complex({ size: '12px', color: null, fontStyle: null, fontWeight: null, fontFamily: null }, Font) ], Label.prototype, "font", void 0); __decorate$1([ Property(false) ], Label.prototype, "useRangeColor", void 0); __decorate$1([ Property('') ], Label.prototype, "format", void 0); __decorate$1([ Property(0) ], Label.prototype, "offset", void 0); __decorate$1([ Property('Auto') ], Label.prototype, "position", void 0); /** * Sets and gets the options for customizing the ranges of an axis. */ class Range extends ChildProperty { } __decorate$1([ Property(0) ], Range.prototype, "start", void 0); __decorate$1([ Property(0) ], Range.prototype, "end", void 0); __decorate$1([ Property(null) ], Range.prototype, "linearGradient", void 0); __decorate$1([ Property(null) ], Range.prototype, "radialGradient", void 0); __decorate$1([ Property('Outside') ], Range.prototype, "position", void 0); __decorate$1([ Property('') ], Range.prototype, "color", void 0); __decorate$1([ Property(10) ], Range.prototype, "startWidth", void 0); __decorate$1([ Property(10) ], Range.prototype, "endWidth", void 0); __decorate$1([ Property(0) ], Range.prototype, "offset", void 0); __decorate$1([ Complex({ color: '#000000', width: 0 }, Border) ], Range.prototype, "border", void 0); /** * Sets and gets the options for customizing the minor tick lines in axis. */ class Tick extends ChildProperty { } __decorate$1([ Property(20) ], Tick.prototype, "height", void 0); __decorate$1([ Property(2) ], Tick.prototype, "width", void 0); __decorate$1([ Property(null) ], Tick.prototype, "interval", void 0); __decorate$1([ Property(null) ], Tick.prototype, "color", void 0); __decorate$1([ Property(null) ], Tick.prototype, "offset", void 0); __decorate$1([ Property('Auto') ], Tick.prototype, "position", void 0); /** * Sets and gets the options for customizing the pointers of an axis in linear gauge. */ class Pointer extends ChildProperty { constructor() { super(...arguments); /** @private */ this.animationComplete = true; /** @private */ this.isPointerAnimation = true; /** @private */ this.currentValue = null; } } __decorate$1([ Property('Marker') ], Pointer.prototype, "type", void 0); __decorate$1([ Property(null) ], Pointer.prototype, "linearGradient", void 0); __decorate$1([ Property(null) ], Pointer.prototype, "radialGradient", void 0); __decorate$1([ Property(null) ], Pointer.prototype, "value", void 0); __decorate$1([ Property('InvertedTriangle') ], Pointer.prototype, "markerType", void 0); __decorate$1([ Property(null) ], Pointer.prototype, "imageUrl", void 0); __decorate$1([ Complex({ color: '#808080' }, Border) ], Pointer.prototype, "border", void 0); __decorate$1([ Property(10) ], Pointer.prototype, "roundedCornerRadius", void 0); __decorate$1([ Property('Far') ], Pointer.prototype, "placement", void 0); __decorate$1([ Property(20) ], Pointer.prototype, "height", void 0); __decorate$1([ Property(20) ], Pointer.prototype, "width", void 0); __decorate$1([ Property(null) ], Pointer.prototype, "color", void 0); __decorate$1([ Property(1) ], Pointer.prototype, "opacity", void 0); __decorate$1([ Property(0) ], Pointer.prototype, "animationDuration", void 0); __decorate$1([ Property(false) ], Pointer.prototype, "enableDrag", void 0); __decorate$1([ Property(0) ], Pointer.prototype, "offset", void 0); __decorate$1([ Property('Auto') ], Pointer.prototype, "position", void 0); __decorate$1([ Property(null) ], Pointer.prototype, "description", void 0); __decorate$1([ Property('') ], Pointer.prototype, "text", void 0); __decorate$1([ Complex({ size: '16px', fontStyle: 'normal', fontWeight: 'normal', fontFamily: null }, TextStyle) ], Pointer.prototype, "textStyle", void 0); /** * Sets and gets the options for customizing the axis of a gauge. */ class Axis extends ChildProperty { constructor() { /** * Sets and gets the minimum value for the axis. * * @default 0 */ super(...arguments); /** @private */ this.visibleLabels = []; } } __decorate$1([ Property(0) ], Axis.prototype, "minimum", void 0); __decorate$1([ Property(100) ], Axis.prototype, "maximum", void 0); __decorate$1([ Property(false) ], Axis.prototype, "isInversed", void 0); __decorate$1([ Property(false) ], Axis.prototype, "showLastLabel", void 0); __decorate$1([ Property(false) ], Axis.prototype, "opposedPosition", void 0); __decorate$1([ Complex({}, Line) ], Axis.prototype, "line", void 0); __decorate$1([ Collection([{}], Range) ], Axis.prototype, "ranges", void 0); __decorate$1([ Collection([{}], Pointer) ], Axis.prototype, "pointers", void 0); __decorate$1([ Complex({ width: 2, height: 20 }, Tick) ], Axis.prototype, "majorTicks", void 0); __decorate$1([ Complex({ width: 1, height: 10 }, Tick) ], Axis.prototype, "minorTicks", void 0); __decorate$1([ Complex({}, Label) ], Axis.prototype, "labelStyle", void 0); /** * Specifies the linear gauge constant value */ /** @private */ const loaded = 'loaded'; /** @private */ const load = 'load'; /** @private */ const animationComplete = 'animationComplete'; /** @private */ const axisLabelRender = 'axisLabelRender'; /** @private */ const tooltipRender = 'tooltipRender'; /** @private */ const annotationRender = 'annotationRender'; /** @private */ const gaugeMouseMove = 'gaugeMouseMove'; /** @private */ const gaugeMouseLeave = 'gaugeMouseLeave'; /** @private */ const gaugeMouseDown = 'gaugeMouseDown'; /** @private */ const gaugeMouseUp = 'gaugeMouseUp'; /** @private */ const dragStart = 'dragStart'; /** @private */ const dragMove = 'dragMove'; /** @private */ const dragEnd = 'dragEnd'; /** @private */ const valueChange = 'valueChange'; /** @private */ const resized = 'resized'; /** @private */ const beforePrint = 'beforePrint'; /* eslint-disable jsdoc/require-jsdoc */ /** * Specifies Linear-Gauge Helper methods */ /** @private */ function stringToNumber(value, containerSize) { return value.indexOf('%') !== -1 ? (containerSize / 100) * parseInt(value, 10) : parseInt(value, 10); } /** @private */ function stringToNumberSize(value, containerSize) { if (!isNullOrUndefined(value)) { return value.indexOf('%') !== -1 ? containerSize : parseInt(value, 10); } return null; } /** * Function to measure the height and width of the text. * * @param {string} text - Specifies the text to be measured. * @param {FontModel} font - Specifies the font of the text. * @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); } htmlObject.innerText = text; htmlObject.style.position = 'absolute'; htmlObject.style.fontSize = font.size; htmlObject.style.fontWeight = font.fontWeight; htmlObject.style.fontStyle = font.fontStyle; htmlObject.style.fontFamily = font.fontFamily; htmlObject.style.visibility = 'hidden'; htmlObject.style.top = '-100'; htmlObject.style.left = '0'; htmlObject.style.whiteSpace = 'nowrap'; const size = new Size(htmlObject.clientWidth, htmlObject.clientHeight); //remove(htmlObject); return size; } /** * Trim the title text * * @private * */ function textTrim(maxWidth, text, font) { let label = text; let size = measureText(text, font).width; if (size > maxWidth) { const textLength = text.length; for (let i = textLength - 1; i >= 0; --i) { label = text.substring(0, i) + '...'; size = measureText(label, font).width; if (size <= maxWidth || label.length < 4) { if (label.length < 4) { label = ' '; } return label; } } } return label; } /** @private */ function withInRange(value, start, end, max, min, type) { let withIn; if (type === 'pointer') { withIn = (((value <= max) && (value >= min))); } else { withIn = (start != null && (start <= max) && (start >= min)) && (end != null && (end <= max) && (end >= min)); } return withIn; } function convertPixelToValue(parentElement, pointerElement, orientation, axis, type, location) { const elementRect = parentElement.getBoundingClientRect(); const pointerRect = pointerElement.getBoundingClientRect(); const height = (pointerElement.id.indexOf('MarkerPointer') > -1) ? (pointerRect.height / 2) : (!axis.isInversed) ? 0 : pointerRect.height; const width = (pointerElement.id.indexOf('MarkerPointer') > -1) ? (pointerRect.width / 2) : (!axis.isInversed) ? pointerRect.width : 0; const size = new Size(axis.lineBounds.width, axis.lineBounds.height); const y = (type === 'drag') ? (location.y - axis.lineBounds.y) : ((pointerRect.top + height) - elementRect.top - axis.lineBounds.y); const extraWidth = getExtraWidth(parentElement); const x = (type === 'drag') ? (location.x - axis.lineBounds.x + extraWidth) : ((pointerRect.left + width) - elementRect.left - axis.lineBounds.x + extraWidth); const newSize = (orientation === 'Vertical') ? size.height : size.width; const divideVal = (orientation === 'Vertical') ? y : x; let value = (orientation === 'Vertical') ? (axis.isInversed) ? (divideVal / newSize) : (1 - (divideVal / newSize)) : (axis.isInversed) ? (1 - (divideVal / newSize)) : (divideVal / newSize); value = value * (axis.visibleRange.delta) + axis.visibleRange.min; return value; } function getPathToRect(path, size, parentElement) { let tempDiv = document.getElementById('gauge_path'); if (tempDiv === null) { tempDiv = createElement('text', { id: 'gauge_path' }); tempDiv.style.position = 'absolute'; tempDiv.style.top = '0px'; tempDiv.style.left = '0px'; parentElement.appendChild(tempDiv); } const render = new SvgRenderer('id'); const svg = render.createSvg({ id: 'box_path', width: size.width, height: size.height }); svg.appendChild(path); tempDiv.appendChild(svg); const svgRect = path.getBBox(); remove(tempDiv); return svgRect; } /** @private */ function getElement(id) { return document.getElementById(id); } /** @private */ function removeElement(id) { const element = getElement(id); if (element) { remove(element); } } /** @private */ function valueToCoefficient(value, axis, orientation, range) { let result = (value - range.min) / range.delta; result = (orientation === 'Vertical') ? (!axis.isInversed) ? (1 - result) : result : (!axis.isInversed) ? result : (1 - result); return result; } 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; } // eslint-disable-next-line @typescript-eslint/no-explicit-any function textFormatter(format, data, gauge) { const keys = Object.keys(data); for (const key of keys) { format = format.split('{' + key + '}').join(formatValue(data[key], gauge).toString()); } return format; } function formatValue(value, gauge) { // eslint-disable-next-line @typescript-eslint/no-explicit-any let formatValue; let formatFunction; if (gauge.format && !isNaN(Number(value))) { formatFunction = gauge.intl.getNumberFormat({ format: gauge.format, useGrouping: gauge.useGroupingSeparator }); formatValue = formatFunction(Number(value)); } else { formatValue = value; } return formatValue !== null ? formatValue : ''; } // /** @private */ // export function getLabelFormat(format: string): string { // const customLabelFormat: boolean = format && format.match('{value}') !== null; // const skeleton: string = customLabelFormat ? '' : format; // return skeleton; // } /** @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 (document.querySelectorAll(template).length) { 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; } /** @private */ function getElementOffset(childElement, parentElement) { parentElement.appendChild(childElement); const width = childElement.offsetWidth; const height = childElement.offsetHeight; parentElement.removeChild(childElement); return new Size(width, height); } /** * To trigger the download element * * @param {string} fileName - Specifies the name of the exported file. * @param {ExportType} type - Specifies the extension type of the file to which the Linear Gauge must be exported. * @param {string} url - Specifies the blob URL of the exported file of Linear Gauge. * @param {boolean} isDownload - Specifies whether the exported file must be downloaded or not. * @private */ function triggerDownload(fileName, type, url, isDownload) { createElement('a', { attrs: { 'download': fileName + '.' + type.toLocaleLowerCase(), 'href': url } }).dispatchEvent(new MouseEvent(isDownload ? 'click' : 'move', { view: window, bubbles: false, cancelable: true })); } /** @private */ class VisibleRange { constructor(min, max, interval, delta) { this.min = min; this.max = max; this.interval = interval; this.delta = delta; } } /** * Specifies the location of the element in the linear gauge. */ class GaugeLocation { constructor(x, y) { this.x = x; this.y = y; } } /** * Specifies the size information of an element. */ class Size { constructor(width, height) { this.width = width; this.height = height; } } /** @private */ class Rect { constructor(x, y, width, height) { this.x = x; this.y = y; this.width = width; this.height = height; } } /** @private */ class CustomizeOption { constructor(id) { this.id = id; } } /** @private */ class PathOption extends CustomizeOption { constructor(id, fill, width, color, opacity, dashArray, d, transform = '') { 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; } } /** @private */ class RectOption { constructor(id, fill, border, opacity, rect) { this.opacity = opacity; this.id = id; this.y = rect.y; this.x = rect.x; this.fill = fill; this.stroke = border.color; this['stroke-width'] = border.width; this['stroke-dasharray'] = border.dashArray; this.height = rect.height; this.width = rect.width; } } /** @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, x, y) { this.text = text; this.value = value; this.size = size; this.x = x; this.y = y; } } /** @private */ class Align { constructor(axisIndex, align) { this.align = align; this.axisIndex = axisIndex; } } /** @private */ function textElement(options, font, color, opacity, parent) { // eslint-disable-next-line @typescript-eslint/no-explicit-any let renderOptions = {}; const renderer = new SvgRenderer(''); if (!isNullOrUndefined(options.id)) { removeElement(options.id); } const style = 'fill:' + color + '; font-size:' + font.size + '; font-style:' + font.fontStyle + ' ; font-weight:' + font.fontWeight + '; font-family:' + font.fontFamily + '; text-anchor:' + options.anchor + '; transform:' + options.transform + '; opacity:' + (!isNullOrUndefined(opacity) ? opacity : font.opacity) + '; dominant-baseline:' + options.baseLine + ';'; renderOptions = { 'id': options.id, 'x': options.x, 'y': options.y, 'style': style }; const htmlObject = renderer.createText(renderOptions, options.text); parent.appendChild(htmlObject); return htmlObject; } function calculateNiceInterval(min, max, size, orientation) { const delta = max - min; let currentInterval; const intervalDivs = [10, 5, 2, 1]; const desiredIntervalsCount = getActualDesiredIntervalsCount(size, orientation); let niceInterval = delta / desiredIntervalsCount; const minInterval = Math.pow(10, Math.floor(Math.log(niceInterval) / Math.log(10))); for (const interval of intervalDivs) { currentInterval = minInterval * interval; if (desiredIntervalsCount < (delta / currentInterval)) { break; } niceInterval = currentInterval; } return niceInterval; } function getActualDesiredIntervalsCount(size, orientation) { const maximumLabels = 5; let desiredIntervalsCount = (orientation === 'Horizontal' ? 0.533 : 1) * maximumLabels; desiredIntervalsCount = Math.max((size * (desiredIntervalsCount / 100)), 1); return desiredIntervalsCount; } /** @private */ function getPointer(target, gauge) { let split = []; const radix = 10; split = target.id.replace(gauge.element.id, '').split('_'); const axisIndex = parseInt(split[2], radix); const pointIndex = parseInt(split[4], radix); const axis = gauge.axes[axisIndex]; const pointer = gauge.axes[axisIndex].pointers[pointIndex]; return { axis: axis, axisIndex: axisIndex, pointer: pointer, pointerIndex: pointIndex }; } /** @private */ function getRangeColor(value, ranges) { let rangeColor = null; ranges.forEach((range) => { if ((value >= range.start && range.end >= value) && range.start !== range.end) { rangeColor = range.interior; } }); return rangeColor; } /** * Function to get the mouse position * * @param {number} pageX - Specifies the horizontal position of the click event. * @param {number} pageY - Specifies the vertical position of the click event. * @param {number} element - Specifies the target element of the client event. * @private */ function getMousePosition(pageX, pageY, element) { const elementRect = element.getBoundingClientRect(); const pageXOffset = element.ownerDocument.defaultView.pageXOffset; const pageYOffset = element.ownerDocument.defaultView.pageYOffset; const clientTop = element.ownerDocument.documentElement.clientTop; const clientLeft = element.ownerDocument.documentElement.clientLeft; const positionX = elementRect.left + pageXOffset - clientLeft; const positionY = elementRect.top + pageYOffset - clientTop; return new GaugeLocation((pageX - positionX), (pageY - positionY)); } /** @private */ function getRangePalette(theme) { let palette; 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; default: palette = ['#ff5985', '#ffb133', '#fcde0b', '#27d5ff', '#50c917']; break; } return palette; } /** @private */ function calculateShapes(location, shape, size, url, options, orientation, axis, pointer) { let path; const width = size.width; const height = size.height; let locX = location.x; let locY = location.y; let radius; switch (shape) { case 'Circle': radius = ((width + height) / 4); locX = (orientation === 'Vertical') ? (!axis.opposedPosition) ? (pointer.placement !== 'Far') ? locX - radius : locX + radius : pointer.placement === 'Near' ? locX - radius : locX + radius : locX; locY = (orientation === 'Vertical') ? locY : (!axis.opposedPosition) ? (pointer.placement === 'Far') ? locY + radius : locY - radius : (pointer.placement === 'Near') ? locY - radius : locY + radius; merge(options, { 'r': radius, 'cx': locX, 'cy': locY }); break; case 'Diamond': case 'Rectangle': locX = (orientation === 'Horizontal') ? ((locX - (width / 2))) : ((!axis.opposedPosition && pointer.placement !== 'Far') || (axis.opposedPosition && pointer.placement === 'Near')) ? locX - width : locX; locY = (orientation === 'Vertical') ? locY : (!axis.opposedPosition) ? (pointer.placement === 'Far') ? locY + (height / 2) : locY - (height / 2) : (pointer.placement === 'Near') ? locY - (height / 2) : locY + (height / 2); if (shape === 'Diamond') { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + ' ' + (locX + (width / 2)) + ' ' + (locY - (height / 2)) + ' ' + 'L' + ' ' + (locX + width) + ' ' + locY + ' ' + 'L' + ' ' + (locX + (width / 2)) + ' ' + (locY + (height / 2)) + ' ' + 'L' + ' ' + locX + ' ' + locY + ' z'; } else { path = 'M' + ' ' + locX + ' ' + (locY - (height / 2)) + ' ' + 'L' + ' ' + (locX + width) + ' ' + (locY - (height / 2)) + ' ' + 'L' + ' ' + (locX + width) + ' ' + (locY + (height / 2)) + ' ' + 'L' + ' ' + locX + ' ' + (locY + (height / 2)) + ' ' + 'L' + ' ' + locX + ' ' + (locY - (height / 2)) + ' z'; } merge(options, { 'd': path }); break; case 'Triangle': if (orientation === 'Vertical') { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + (locX - width) + ' ' + (locY - (height / 2)) + 'L' + (locX - width) + ' ' + (locY + (height / 2)) + ' Z'; } else { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + (locX + (width / 2)) + ' ' + (locY - height) + 'L' + (locX - (width / 2)) + ' ' + (locY - height) + ' Z'; } merge(options, { 'd': path }); break; case 'InvertedTriangle': if (orientation === 'Vertical') { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + (locX + width) + ' ' + (locY - (height / 2)) + 'L' + (locX + width) + ' ' + (locY + (height / 2)) + ' Z'; } else { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + (locX + (width / 2)) + ' ' + (locY + height) + 'L' + (locX - (width / 2)) + ' ' + (locY + height) + ' Z'; } merge(options, { 'd': path }); break; case 'Arrow': if (orientation === 'Vertical') { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + (locX - (width / 2)) + ' ' + (locY - (height / 2)) + ' ' + 'L' + (locX - (width / 2)) + ' ' + ((locY - (height / 2)) + (height / 4)) + ' ' + 'L' + (locX - width) + ' ' + ((locY - (height / 2)) + (height / 4)) + ' ' + 'L' + (locX - width) + ' ' + ((locY + (height / 2)) - (height / 4)) + ' ' + 'L' + (locX - (width / 2)) + ' ' + ((locY + (height / 2)) - (height / 4)) + ' ' + 'L' + (locX - (width / 2)) + ' ' + (locY + height / 2) + 'z'; } else { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + (locX + (width / 2)) + ' ' + (locY - (height / 2)) + ' ' + 'L' + ((locX + (width / 2)) - (width / 4)) + ' ' + (locY - (height / 2)) + ' ' + 'L' + ((locX + (width / 2)) - (width / 4)) + ' ' + (locY - height) + ' ' + 'L' + ((locX - (width / 2)) + (width / 4)) + ' ' + (locY - height) + ' ' + 'L' + ((locX - (width / 2)) + (width / 4)) + ' ' + (locY - (height / 2)) + ' ' + 'L' + (locX - (width / 2)) + ' ' + (locY - (height / 2)) + 'z'; } merge(options, { 'd': path }); break; case 'InvertedArrow': if (orientation === 'Vertical') { path = 'M' + ' ' + locX + ' ' + locY + 'L' + (locX + (width / 2)) + ' ' + (locY - (height / 2)) + ' ' + 'L' + (locX + (width / 2)) + ' ' + ((locY - (height / 2)) + (height / 4)) + ' ' + 'L' + (locX + width) + ' ' + ((locY - (height / 2)) + (height / 4)) + ' ' + 'L' + (locX + width) + ' ' + ((locY + (height / 2)) - (height / 4)) + ' ' + 'L' + (locX + (width / 2)) + ' ' + ((locY + (height / 2)) - (height / 4)) + ' ' + 'L' + (locX + (width / 2)) + ' ' + (locY + height / 2) + 'z'; } else { path = 'M' + ' ' + locX + ' ' + locY + ' ' + 'L' + (locX + (width / 2)) + ' ' + (locY + (height / 2)) + ' ' + 'L' + ((locX + (width / 2)) - (width / 4)) + ' ' + (locY + (height / 2)) + ' ' + 'L' + ((locX + (width / 2)) - (width / 4)) + ' ' + (locY + height) + ' ' + 'L' + ((locX - (width / 2)) + (width / 4)) + ' ' + (locY + height) + ' ' + 'L' + ((locX - (width / 2)) + (width / 4)) + ' ' + (locY + (height / 2)) + ' ' + 'L' + (locX - (width / 2)) + ' ' + (locY + (height / 2)) + 'z'; } merge(options, { 'd': path }); break; case 'Image': merge(options, { 'href': url, 'height': height, 'width': width, x: locX - (width / 2), y: locY - (height / 2) }); break; } return options; } /** @private */ function calculateTextPosition(location, shape, options, orientation, axis, pointer) { let width; let height; let textSize; let locX = location.x; let locY = location.y; switch (shape) { case 'Text': textSize = measureText(pointer.text, pointer.textStyle); height = textSize.height; width = textSize.width; locX = (orientation === 'Horizontal') ? ((locX - (width / 2))) : ((!axis.opposedPosition && pointer.placement !== 'Far') || (axis.opposedPosition && pointer.placement === 'Near')) ? (pointer.position === 'Inside' && !axis.opposedPosition) || (pointer.position === 'Cross') || (axis.opposedPosition && pointer.placement === 'Near' && pointer.position === 'Outside') ? locX - (width / 2) : locX - width : (pointer.position === 'Cross' && pointer.placement === 'Far') || (axis.opposedPosition && pointer.position === 'Cross' && (pointer.placement === 'None' || pointer.placement === 'Center')) ? locX + (width / 2) : locX; locY = (orientation === 'Vertical') ? locY + (height / 4) : (!axis.opposedPosition) ? (pointer.placement === 'Far') ? pointer.position === 'Cross' ? locY + (height / 2) + (height / 4) : pointer.position === 'Inside' ? locY + height : locY + (height / 2) : locY : (pointer.placement === 'Near') ? locY : pointer.position === 'Cross' ? locY + (height / 2) + (height / 4) : pointer.position === 'Outside' ? locY + height : locY + (height / 2); merge(options, { x: locX, y: locY }); break; } return options; } /** @private */ function getBox(location, boxName, orientation, size, type, containerWidth, axis, cornerRadius) { let path = ' '; let radius = cornerRadius; let horizontalRadius; let x1; let y1; let rectWidth; let rectHeight; let verticalRadius; let bottomRadius; let topRadius; let horizontalCurve; let verticalCurve; switch (boxName) { case 'RoundedRectangle': x1 = location.x; y1 = location.y; rectWidth = location.width; rectHeight = location.height; if (((orientation === 'Vertical' && location.height === 0) || (orientation === 'Horizontal' && location.width === 0)) && radius > 10) { radius = 10; } horizontalCurve = x1 + rectWidth - radius; verticalCurve = y1 + rectHeight - radius; verticalRadius = radius + y1; horizontalRadius = radius + x1; if (type === 'container' || type === 'bar' && ((orientation === 'Vertical' && location.height !== 0) || (orientation === 'Horizontal' && location.width !== 0))) { if (horizontalRadius > (x1 + (rectWidth / 2))) { horizontalRadius = x1 + (rectWidth / 2); horizontalCurve = horizontalRadius; } if (verticalRadius > (y1 + (rectHeight / 2))) { verticalRadius = y1 + (rectHeight / 2); verticalCurve = verticalRadius; } } if (type === 'bar' && ((orientation === 'Vertical' && location.height === 0) || (orientation === 'Horizontal' && location.width === 0))) { if (location.width < radius / 2 && !axis.isInversed) { horizontalCurve = horizontalCurve + radius + radius / 2; } else if (location.width < radius / 2 && axis.isInversed) { horizontalRadius = x1 - Math.ceil(radius / 4); } if (location.height < radius / 2 && !axis.isInversed) { verticalRadius = y1 - Math.ceil(radius / 4); } else if (location.height < radius / 2 && axis.isInversed) { verticalCurve = verticalCurve + radius + radius / 2; } } path = 'M' + ' ' + x1 + ' ' + verticalRadius + ' Q ' + x1 + ' ' + y1 + ' ' + horizontalRadius + ' ' + y1 + ' '; path += 'L' + ' ' + horizontalCurve + ' ' + y1 + ' Q ' + (x1 + rectWidth) + ' ' + y1 + ' ' + (x1 + rectWidth) + ' ' + verticalRadius + ' '; path += 'L ' + (x1 + rectWidth) + ' ' + verticalCurve + ' Q ' + (x1 + rectWidth) + ' ' + (y1 + rectHeight) + ' ' + horizontalCurve + ' ' + (y1 + rectHeight) + ' '; path += ' L ' + horizontalRadius + ' ' + (y1 + rectHeight) + ' Q ' + x1 + ' ' + (y1 + rectHeight) + ' ' + x1 + ' ' + verticalCurve + ' '; path += 'L' + ' ' + x1 + ' ' + verticalRadius + ' ' + 'z'; break; case 'Thermometer': // eslint-disable-next-line no-case-declarations const width = (orientation === 'Vertical') ? location.width : location.height; bottomRadius = width + ((width / 2) / Math.PI); topRadius = width / 2; if (orientation === 'Vertical') { const addValue = ((containerWidth + ((containerWidth / 2) / Math.PI)) - bottomRadius); const y1 = (type === 'bar') ? location.y + addValue : location.y; const locY = (type === 'bar') ? location.y + (topRadius - (topRadius / Math.PI)) : location.y; const locHeight = location.height; path = 'M' + location.x + ' ' + (y1 + locHeight) + ' A ' + bottomRadius + ' ' + bottomRadius + ', 0, 1, 0, ' + (location.x + location.width) + ' ' + (y1 + locHeight) + ' L ' + (location.x + location.width) + ' ' + locY + ' A ' + topRadius + ' ' + topRadius + ', 0, 1, 0, ' + location.x + ' ' + locY + ' z '; } else { const x1 = (type === 'bar' && !axis.isInversed) ? location.x - ((containerWidth + ((containerWidth / 2) / Math.PI)) - bottomRadius) : location.x; const locWidth = (type === 'bar') ? (location.width - (topRadius - ((topRadius / Math.PI)))) : location.width; path = 'M' + x1 + ' ' + (location.y) + ' A ' + bottomRadius + ' ' + bottomRadius + ', 0, 1, 0, ' + x1 + ' ' + (location.y + location.height) + ' L ' + ((type === 'bar' ? location.x : x1) + locWidth) + ' ' + (location.y + location.height) + ' A ' + topRadius + ' ' + topRadius + ', 0, 1, 0, ' + ((type === 'bar' ? location.x : x1) + locWidth) + ' ' + (location.y) + ' z '; } break; } return path; } /** @private */ function getExtraWidth(gaugeElement) { const svgElement = getElement(gaugeElement.id + '_svg'); let extraWidth = 0; if (!isNullOrUndefined(svgElement) && !isNullOrUndefined(gaugeElement)) { extraWidth = gaugeElement.getBoundingClientRect().left - svgElement.getBoundingClientRect().left; } return extraWidth; } /** * @param {string} text - Specifies the text. * @returns {void} * @private */ function showTooltip(text, gauge) { let tooltip = getElement(gauge.element.id + '_EJ2_Title_Tooltip'); if (!tooltip) { let titleWidth = measureText(text, { size: '12px', fontFamily: 'Segoe UI' }).width + 10; titleWidth = titleWidth < gauge.actualRect.width ? titleWidth : gauge.actualRect.width - 10; tooltip = createElement('div', { id: gauge.element.id + '_EJ2_Title_Tooltip', className: 'EJ2-LinearGauge-Tooltip' }); tooltip.innerText = text; tooltip.style.cssText = 'top:' + (gauge.actualRect.y + 10).toString() + 'px; left:' + (gauge.actualRect.x).toString() + 'px; background-color:rgb(255, 255, 255) !important; color:black !important; ' + 'position:absolute; border:1px solid rgb(112, 112, 112); padding-left:3px; padding-right:2px;' + 'padding-bottom:2px; padding-top:2px; font-size:12px; font-family:"Segoe UI";' + 'width:' + (titleWidth) + 'px;'; document.body.style.overflow = 'hidden'; getElement(gauge.element.id + '_Secondary_Element').appendChild(tooltip); } else { tooltip.innerText = text; tooltip.style.top = (gauge.actualRect.y + 10).toString() + 'px'; tooltip.style.left = (gauge.actualRect.x).toString() + 'px'; } } /** @private */ function removeTooltip() { if (document.getElementsByClassName('EJ2-LinearGauge-Tooltip').length > 0) { document.getElementsByClassName('EJ2-LinearGauge-Tooltip')[0].remove(); } } /* eslint-disable valid-jsdoc */ /** * To calculate the overall axis bounds for gauge. * * @private */ class AxisLayoutPanel { constructor(gauge) { this.gauge = gauge; } /** * To calculate the axis bounds */ calculateAxesBounds() { let axis; let bounds; this.gauge.nearSizes = []; this.gauge.farSizes = []; let x; let y; let width; let height; const axisPadding = 8; this.checkThermometer(); for (let i = 0; i < this.gauge.axes.length; i++) { axis = this.gauge.axes[i]; axis.checkAlign = new Align(i, ((!axis.opposedPosition) ? 'Near' : 'Far')); // eslint-disable-next-line @typescript-eslint/no-unused-expressions (!axis.opposedPosition) ? this.gauge.nearSizes.push(1) : this.gauge.farSizes.push(1); this.calculateLineBounds(axis, i); this.calculateTickBounds(axis); this.calculateLabelBounds(axis); if (axis.pointers.length > 0) { this.calculatePointerBounds(axis); } if (axis.ranges.length > 0) { this.calculateRangesBounds(axis); } bounds = axis.labelBounds; const offset = this.gauge.axes[i].labelStyle.offset; if (this.gauge.orientation === 'Vertical') { x = (!axis.opposedPosition) ? bounds.x - offset - axisPadding : axis.lineBounds.x; y = axis.lineBounds.y; height = axis.lineBounds.height; width = Math.abs((!axis.opposedPosition) ? (axis.lineBounds.x - x) : ((bounds.x + bounds.width + axisPadding) - x - offset)); } else { y = (!axis.opposedPosition) ? bounds.y - bounds.height - offset - axisPadding : axis.lineBounds.y; x = axis.lineBounds.x; width = axis.lineBounds.width; height = Math.abs((!axis.opposedPosition) ? Math.abs(axis.lineBounds.y - y) : (bounds.y + axisPadding) - y - offset); } axis.bounds = new Rect(x, y, width, height); } } /** * Calculate axis line bounds * * @param axis * @param axisIndex */ calculateLineBounds(axis, axisIndex) { let x; let y; let width; let height; let prevAxis; let lineHeight = axis.line.height; const orientation = this.gauge.orientation; const containerRect = this.gauge.containerBounds; lineHeight = (axis.line.width > 0) ? lineHeight : null; if (orientation === 'Vertical') { y = (isNullOrUndefined(lineHeight)) ? containerRect.y : containerRect.y + ((containerRect.height / 2) - (lineHeight / 2)); width = axis.line.width; height = (isNullOrUndefined(lineHeight)) ? containerRect.height : lineHeight; } else { x = (isNullOrUndefined(lineHeight)) ? containerRect.x : containerRect.x + ((containerRect.width / 2) - (lineHeight / 2)); height = axis.line.width; width = (isNullOrUndefined(lineHeight)) ? containerRect.width : lineHeight; } let index = this.checkPreviousAxes(axis, axisIndex); let count = 0; if (!isNullOrUndefined(index)) { for (let i = index; i >= 0; i--) { if (this.gauge.axes[i].minimum !== this.gauge.axes[i].maximum) { index = i; count++; break; } } if (count === 0) { index = null; } } if (isNullOrUndefined(index)) { if (orientation === 'Vertical') { x = (!axis.opposedPosition ? containerRect.x : containerRect.x + containerRect.width) + axis.line.offset; } else { y = (!axis.opposedPosition ? containerRect.y : containerRect.y + containerRect.height) + axis.line.offset; } } else { prevAxis = this.gauge.axes[index]; if (orientation === 'Vertical') { x = ((!axis.opposedPosition) ? prevAxis.bounds.x : (prevAxis.bounds.x + prevAxis.bounds.width)) + axis.line.offset; } else { y = ((!axis.opposedPosition) ? prevAxis.bounds.y : (prevAxis.bounds.y + prevAxis.bounds.height)) + axis.line.offset; } } axis.lineBounds = new Rect(x, y, width, height); if (axis.minimum === axis.maximum) { axis.lineBounds = new Rect(0, 0, 0, 0); } } /** * Calculate axis tick bounds * * @param axis */ calculateTickBounds(axis) { let x; let y; let min = Math.min(axis.minimum, axis.maximum); const max = Math.max(axis.minimum, axis.m